// app/api/appapis/update-appointment-status/[id]/route.js
import { NextRequest, NextResponse } from 'next/server';
import pool from '../../../../../lib/db/db';
import { RowDataPacket, ResultSetHeader } from 'mysql2';
import { verifyAuthentication } from '../../../../utils/verifyAuthentication';
import { z } from 'zod';

// Validation schema
const statusSchema = z.object({
  status: z.enum(['pending', 'confirmed', 'scheduled', 'completed', 'cancelled', 'no_show'])
});

// CORS headers
const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization, x-api-key',
  'Access-Control-Allow-Credentials': 'true',
};

export async function OPTIONS() {
  return new NextResponse(null, {
    status: 204,
    headers: corsHeaders,
  });
}

export async function POST(
  request: NextRequest,
  { params }
) {
  const connection = await pool.getConnection();
  
  try {
    const appointmentId = params.id;
    
    if (!appointmentId) {
      connection.release();
      return NextResponse.json(
        { success: false, message: 'Invalid appointment ID' },
        { status: 400, headers: corsHeaders }
      );
    }

    // Get token from Authorization header for mobile app
    const authHeader = request.headers.get('authorization');
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      connection.release();
      return NextResponse.json(
        { success: false, message: 'No valid authorization header found' },
        { status: 401, headers: corsHeaders }
      );
    }

    const token = authHeader.substring(7);
    
    // Verify token
    const authResult = await verifyAuthentication(token);
    
    if (authResult instanceof NextResponse) {
      connection.release();
      return authResult;
    }
    
    const decoded = authResult as { id: number; role: string };
    
    if (!decoded || !decoded.id) {
      connection.release();
      return NextResponse.json(
        { success: false, message: 'Invalid token - no user ID found' },
        { status: 401, headers: corsHeaders }
      );
    }

    // Check if user is authorized (foreign student)
    if (decoded.role !== 'foreign-student') {
      connection.release();
      return NextResponse.json(
        { success: false, message: 'Access denied. Foreign student access only.' },
        { status: 403, headers: corsHeaders }
      );
    }

    const foreignStudentId = decoded.id;
    
    // Check if foreign student exists and is active
    const [studentExists] = await connection.query<RowDataPacket[]>(
      'SELECT id, name, email FROM foreign_students WHERE id = ? AND is_active = 1',
      [foreignStudentId]
    );

    if (studentExists.length === 0) {
      connection.release();
      return NextResponse.json(
        { success: false, message: 'Foreign student not found or inactive' },
        { status: 404, headers: corsHeaders }
      );
    }

    const body = await request.json();
    
    // Validate input
    const validatedData = statusSchema.parse(body);

    // Start transaction
    await connection.beginTransaction();

    // 1. Check if appointment exists and belongs to this foreign student
    const [appointment] = await connection.query<RowDataPacket[]>(
      `SELECT 
        fsbs.id, 
        fsbs.status as current_status,
        fsbs.session_date,
        fsbs.start_time,
        fsbs.end_time,
        fsbs.meeting_link,
        s.id as student_id,
        s.first_name as student_name, 
        s.email as student_email,
        s.phone as student_phone
      FROM foreign_student_booked_sessions fsbs
      INNER JOIN users s ON fsbs.student_id = s.id
      WHERE fsbs.id = ? AND fsbs.foreign_student_id = ?`,
      [appointmentId, foreignStudentId]
    );

    if (appointment.length === 0) {
      await connection.rollback();
      connection.release();
      return NextResponse.json(
        { success: false, message: 'Appointment not found or access denied' },
        { status: 404, headers: corsHeaders }
      );
    }

    const appointmentData = appointment[0];
    const currentStatus = appointmentData.current_status;
    
    // Prevent invalid status transitions
    const allowedTransitions: Record<string, string[]> = {
      pending: ['confirmed', 'cancelled'],
      confirmed: ['completed', 'cancelled'],
      scheduled: ['completed', 'cancelled'],
      completed: [],
      cancelled: [],
      no_show: []
    };

    if (!allowedTransitions[currentStatus]?.includes(validatedData.status)) {
      await connection.rollback();
      connection.release();
      return NextResponse.json(
        { 
          success: false, 
          message: `Invalid status transition from ${currentStatus} to ${validatedData.status}` 
        },
        { status: 400, headers: corsHeaders }
      );
    }

    // Get current date and time for comparison
    const currentDateTime = new Date();
    
    // Parse the session date and time
    // Handle different date formats
    let sessionDateObj;
    if (appointmentData.session_date instanceof Date) {
      sessionDateObj = appointmentData.session_date;
    } else {
      sessionDateObj = new Date(appointmentData.session_date);
    }
    
    // Combine date and time
    const meetingDateTime = new Date(sessionDateObj);
    const [hours, minutes, seconds] = appointmentData.start_time.split(':');
    meetingDateTime.setHours(parseInt(hours), parseInt(minutes), parseInt(seconds) || 0);
    
    // Additional validation for marking as completed
    if (validatedData.status === 'completed') {
      // Check if meeting link has been shared
      if (!appointmentData.meeting_link) {
        await connection.rollback();
        connection.release();
        return NextResponse.json(
          { 
            success: false, 
            message: 'Cannot mark as completed. Please share the meeting link first.' 
          },
          { status: 400, headers: corsHeaders }
        );
      }

      // Check if meeting time has passed
      if (currentDateTime < meetingDateTime) {
        const formattedMeetingTime = meetingDateTime.toLocaleString('en-US', {
          weekday: 'long',
          year: 'numeric',
          month: 'long',
          day: 'numeric',
          hour: '2-digit',
          minute: '2-digit',
          timeZoneName: 'short'
        });
        
        await connection.rollback();
        connection.release();
        return NextResponse.json(
          { 
            success: false, 
            message: `Cannot mark as completed. The meeting is scheduled for ${formattedMeetingTime} which is in the future. Please wait until after the meeting to mark as completed.`,
            meeting_time: meetingDateTime.toISOString(),
            current_time: currentDateTime.toISOString()
          },
          { status: 400, headers: corsHeaders }
        );
      }

      // Optional: Add a grace period for marking as completed (e.g., within 7 days after meeting)
      const daysAfterMeeting = (currentDateTime.getTime() - meetingDateTime.getTime()) / (1000 * 60 * 60 * 24);
      
      if (daysAfterMeeting > 7) {
        await connection.rollback();
        connection.release();
        return NextResponse.json(
          { 
            success: false, 
            message: 'Cannot mark as completed. The meeting was more than 7 days ago. Please contact support for assistance.' 
          },
          { status: 400, headers: corsHeaders }
        );
      }
    }

    // Additional validation for confirming appointment
    if (validatedData.status === 'confirmed') {
      // Check if meeting time is in the future
      if (currentDateTime > meetingDateTime) {
        const formattedMeetingTime = meetingDateTime.toLocaleString('en-US', {
          weekday: 'long',
          year: 'numeric',
          month: 'long',
          day: 'numeric',
          hour: '2-digit',
          minute: '2-digit',
          timeZoneName: 'short'
        });
        
        await connection.rollback();
        connection.release();
        return NextResponse.json(
          { 
            success: false, 
            message: `Cannot confirm past appointments. The meeting was scheduled for ${formattedMeetingTime} and has already passed.`,
            meeting_time: meetingDateTime.toISOString(),
            current_time: currentDateTime.toISOString()
          },
          { status: 400, headers: corsHeaders }
        );
      }
    }

    // 2. Update appointment status
    const [updateResult] = await connection.query<ResultSetHeader>(
      `UPDATE foreign_student_booked_sessions 
       SET status = ?, updated_at = NOW()
       WHERE id = ? AND foreign_student_id = ?`,
      [validatedData.status, appointmentId, foreignStudentId]
    );

    if (updateResult.affectedRows === 0) {
      await connection.rollback();
      connection.release();
      return NextResponse.json(
        { success: false, message: 'Failed to update appointment status' },
        { status: 500, headers: corsHeaders }
      );
    }

    // 3. If status is completed, update statistics
    if (validatedData.status === 'completed') {
      await connection.query(
        `UPDATE foreign_students 
         SET updated_at = NOW()
         WHERE id = ?`,
        [foreignStudentId]
      );
    }

    // Commit transaction
    await connection.commit();

    // Get the updated appointment data for response
    const [updatedAppointment] = await connection.query<RowDataPacket[]>(
      `SELECT 
        fsbs.id,
        fsbs.status,
        fsbs.session_date,
        fsbs.start_time,
        fsbs.end_time,
        fsbs.amount,
        fsbs.meeting_link,
        s.first_name as student_name,
        s.email as student_email
      FROM foreign_student_booked_sessions fsbs
      INNER JOIN users s ON fsbs.student_id = s.id
      WHERE fsbs.id = ?`,
      [appointmentId]
    );

    connection.release();

    // Prepare response message based on status change
    let responseMessage = `Appointment ${validatedData.status} successfully`;
    let canShareMeetingLink = false;
    let isMeetingPassed = currentDateTime > meetingDateTime;
    
    if (validatedData.status === 'completed') {
      responseMessage = 'Session marked as completed successfully! Payment will be processed.';
    } else if (validatedData.status === 'confirmed') {
      responseMessage = 'Appointment confirmed! You can now share the meeting link with the student.';
      canShareMeetingLink = true;
    } else if (validatedData.status === 'cancelled') {
      responseMessage = 'Appointment cancelled successfully.';
    }

    // Format meeting time for response
    const formatMeetingTime = (date: any, time: string) => {
      let meetingDate;
      if (date instanceof Date) {
        meetingDate = new Date(date);
      } else {
        meetingDate = new Date(date);
      }
      const [hours, minutes] = time.split(':');
      meetingDate.setHours(parseInt(hours), parseInt(minutes));
      
      return meetingDate.toLocaleString('en-US', {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
        timeZoneName: 'short'
      });
    };

    return NextResponse.json({
      success: true,
      message: responseMessage,
      data: {
        id: appointmentId,
        previous_status: currentStatus,
        new_status: validatedData.status,
        can_share_meeting_link: canShareMeetingLink,
        meeting_time: meetingDateTime.toISOString(),
        meeting_time_formatted: formatMeetingTime(appointmentData.session_date, appointmentData.start_time),
        meeting_time_passed: isMeetingPassed,
        appointment: updatedAppointment[0] || null
      }
    }, { status: 200, headers: corsHeaders });

  } catch (err: any) {
    // Rollback on any error
    if (connection) {
      await connection.rollback();
      connection.release();
    }
    
    console.error('Update appointment status error:', err);
    
    // Zod validation errors
    if (err instanceof z.ZodError) {
      const errors = {};
      err.errors.forEach(error => {
        const path = error.path.join('.');
        errors[path] = error.message;
      });
      
      return NextResponse.json(
        { 
          success: false, 
          message: 'Validation failed', 
          errors 
        },
        { status: 400, headers: corsHeaders }
      );
    }
    
    // Database or other errors
    return NextResponse.json(
      { 
        success: false, 
        message: err.message || 'Failed to update appointment status' 
      },
      { status: 500, headers: corsHeaders }
    );
  }
}