<?php
session_start();
header('Content-Type: application/json');
include '../layouts/dbconn.php';
include '../layouts/session.php';

// Ensure user is authenticated
if (!isset($_SESSION['user_id'])) {
    echo json_encode([
        'success' => false,
        'message' => 'Unauthorized access'
    ]);
    exit();
}

$user_id = $_SESSION['user_id'];
$user_role = $_SESSION['role_code'];

try {
    // Get form data
    $patient_id = intval($_POST['patient_id'] ?? 0);
    $department_id = intval($_POST['department_id'] ?? 0);
    
    // CRITICAL FIX: Clean any literal quotes from form data
    $priority_raw = $_POST['priority'] ?? 'NORMAL';
    $priority = strtoupper(trim(str_replace(["'", '"', "'", '"', '"'], '', $priority_raw)));
    
    // Validate against allowed values
    $valid_priorities = ['NORMAL', 'URGENT', 'EMERGENCY'];
    if (!in_array($priority, $valid_priorities, true)) {
        error_log("Invalid priority received: '" . $priority_raw . "' -> cleaned: '" . $priority . "'");
        $priority = 'NORMAL'; // Safe default
    }
    
    // Service type - can be NULL
    $service_type = !empty($_POST['service_type']) ? trim($_POST['service_type']) : null;
    
    // Chief complaint - can be NULL
    $chief_complaint = !empty($_POST['chief_complaint']) ? trim($_POST['chief_complaint']) : null;
    
    // Special needs - can be NULL
    $special_needs = !empty($_POST['special_needs']) ? trim($_POST['special_needs']) : null;
    
    // Has appointment - boolean
    $has_appointment = intval($_POST['has_appointment'] ?? 0);

    // Assigned doctor (for ENT Consultation) - optional
    $assigned_doctor_id = !empty($_POST['assigned_doctor_id']) ? intval($_POST['assigned_doctor_id']) : null;

    // Change insurance / payment type (Add to Queue: select Cash or another insurance)
    $change_insurance = isset($_POST['change_insurance']) && $_POST['change_insurance'] == '1';
    $new_insurance_provider_id_raw = $_POST['new_insurance_provider_id'] ?? null;
    $new_member_number = trim($_POST['new_member_number'] ?? '');

    // Validate required fields
    if ($patient_id <= 0) {
        throw new Exception('Patient is required');
    }
    
    if ($department_id <= 0) {
        throw new Exception('Department is required');
    }

    // Verify patient exists with proper JOIN to users table
    $patient_check_sql = "SELECT 
                            p.patient_id,
                            p.patient_number,
                            p.registration_type,
                            u.full_name,
                            u.phone_primary,
                            u.date_of_birth,
                            u.gender
                        FROM patients p
                        INNER JOIN users u ON p.user_id = u.user_id
                        WHERE p.patient_id = ? AND p.is_active = 1";
    
    $stmt = $conn->prepare($patient_check_sql);
    $stmt->bind_param("i", $patient_id);
    $stmt->execute();
    $result = $stmt->get_result();
    
    if ($result->num_rows === 0) {
        throw new Exception('Patient not found');
    }
    
    $patient = $result->fetch_assoc();
    $stmt->close();

    // If user chose to change insurance: update patient record (Cash or new provider)
    if ($change_insurance) {
        if ($new_insurance_provider_id_raw === 'CASH' || $new_insurance_provider_id_raw === '' || $new_insurance_provider_id_raw === null) {
            // Switch to Cash (WALK_IN): clear insurance
            $upd = $conn->prepare("UPDATE patients SET registration_type = 'WALK_IN', insurance_provider_id = NULL, insurance_number = NULL WHERE patient_id = ?");
            $upd->bind_param("i", $patient_id);
            $upd->execute();
            $upd->close();
            $patient['registration_type'] = 'WALK_IN';
        } else {
            $new_provider_id = intval($new_insurance_provider_id_raw);
            if ($new_provider_id > 0 && $new_member_number !== '') {
                $upd = $conn->prepare("UPDATE patients SET registration_type = 'INSURANCE', insurance_provider_id = ?, insurance_number = ? WHERE patient_id = ?");
                $upd->bind_param("isi", $new_provider_id, $new_member_number, $patient_id);
                $upd->execute();
                $upd->close();
                $patient['registration_type'] = 'INSURANCE';
            } else {
                throw new Exception('When changing to an insurance provider, both provider and member number are required.');
            }
        }
        // Re-fetch patient so queue insert uses updated registration_type
        $stmt = $conn->prepare($patient_check_sql);
        $stmt->bind_param("i", $patient_id);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result->num_rows > 0) {
            $patient = $result->fetch_assoc();
        }
        $stmt->close();
    }

    // Clean and validate GENDER
    $raw_gender = $patient['gender'] ?? null;
    $gender = null;
    if ($raw_gender !== null && trim($raw_gender) !== '') {
        $g = strtoupper(trim(str_replace(["'", '"', "'", '"', '"'], '', $raw_gender)));
        $gender_map = ['M' => 'MALE', 'F' => 'FEMALE', 'MALE' => 'MALE', 'FEMALE' => 'FEMALE', 'OTHER' => 'OTHER'];
        $gender = $gender_map[$g] ?? (in_array($g, ['MALE', 'FEMALE', 'OTHER'], true) ? $g : null);
        if ($gender === null) error_log("Invalid gender for patient_queue: '" . $raw_gender . "'");
    }

    // Clean and validate REGISTRATION_TYPE
    $valid_reg_types = ['WALK_IN', 'INSURANCE', 'PRO_BONO'];
    $raw_reg_type = $patient['registration_type'] ?? null;
    
    if ($raw_reg_type === null || trim($raw_reg_type) === '') {
        $registration_type = 'WALK_IN';
    } else {
        $registration_type = strtoupper(trim(str_replace(["'", '"', "'", '"', '"'], '', $raw_reg_type)));
        if (!in_array($registration_type, $valid_reg_types, true)) {
            error_log("registration_type '" . $raw_reg_type . "' not in patient_queue ENUM, defaulting to WALK_IN");
            $registration_type = 'WALK_IN';
        }
    }

    // Calculate age
    $age = 0;
    if (!empty($patient['date_of_birth'])) {
        try {
            $dob = new DateTime($patient['date_of_birth']);
            $now = new DateTime();
            $age = $dob->diff($now)->y;
        } catch (Exception $e) {
            $age = 0;
        }
    }

    // Phone number - ensure it's not NULL
    $phone_number = !empty($patient['phone_primary']) ? $patient['phone_primary'] : '';

    // Verify target department exists
    $dept_check_sql = "SELECT department_id, department_name, department_code 
                       FROM departments 
                       WHERE department_id = ? AND is_active = 1";
    $stmt = $conn->prepare($dept_check_sql);
    $stmt->bind_param("i", $department_id);
    $stmt->execute();
    $dept_result = $stmt->get_result();
    
    if ($dept_result->num_rows === 0) {
        throw new Exception('Department not found');
    }
    
    $department = $dept_result->fetch_assoc();
    $stmt->close();

    // Get TRIAGE department
    $triage_sql = "SELECT department_id, department_code FROM departments WHERE department_code = 'TRIAGE' LIMIT 1";
    $triage_result = $conn->query($triage_sql);
    if (!$triage_result || $triage_result->num_rows === 0) {
        throw new Exception('Triage department not found. Please contact administrator.');
    }
    $triage_dept = $triage_result->fetch_assoc();
    $triage_department_id = (int) $triage_dept['department_id'];
    $triage_dept_code = $triage_dept['department_code'];

    // next_department_id: where to route after triage
    $next_department_id = ($department_id == $triage_department_id) ? null : $department_id;

    // Check if patient is already in triage queue today
    $duplicate_check_sql = "SELECT queue_id FROM patient_queue 
                            WHERE patient_id = ? 
                            AND department_id = ?
                            AND queue_status IN ('WAITING', 'IN_SERVICE')
                            AND DATE(queue_entry_time) = CURDATE()";
    $stmt = $conn->prepare($duplicate_check_sql);
    $stmt->bind_param("ii", $patient_id, $triage_department_id);
    $stmt->execute();
    $dup_result = $stmt->get_result();
    
    if ($dup_result->num_rows > 0) {
        throw new Exception('Patient is already in triage queue today. Complete triage first, then they will be routed.');
    }
    $stmt->close();

    // Start transaction
    $conn->begin_transaction();

    try {
        // 1. Create patient_visits
        $visit_seq_sql = "SELECT COALESCE(MAX(CAST(SUBSTRING(visit_number, -4) AS UNSIGNED)), 0) + 1 as next_num 
                          FROM patient_visits WHERE visit_number LIKE CONCAT('VST-', DATE_FORMAT(NOW(), '%Y%m%d'), '-%')";
        $visit_seq = $conn->query($visit_seq_sql);
        $next_visit = ($visit_seq && $r = $visit_seq->fetch_assoc()) ? (int) $r['next_num'] : 1;
        $visit_number = 'VST-' . date('Ymd') . '-' . str_pad($next_visit, 4, '0', STR_PAD_LEFT);

        $visit_sql = "INSERT INTO patient_visits (
                        visit_number, patient_id, visit_type, visit_source, 
                        registration_type, registration_date, status, registered_by, created_at
                     ) VALUES (?, ?, 'CONSULTATION', 'WALK_IN', ?, CURDATE(), 'REGISTERED', ?, NOW())";
        $stmt = $conn->prepare($visit_sql);
        if (!$stmt) throw new Exception('Failed to prepare visit statement');
        $stmt->bind_param("sisi", $visit_number, $patient_id, $registration_type, $user_id);
        $stmt->execute();
        $visit_id = $conn->insert_id;
        $stmt->close();

        // 2. Generate triage queue number
        $queue_num_stmt = $conn->prepare("SELECT GenerateQueueNumber(?) as queue_number");
        $queue_num_stmt->bind_param("s", $triage_dept_code);
        $queue_num_stmt->execute();
        $qn_res = $queue_num_stmt->get_result();
        $queue_number = $qn_res->fetch_assoc()['queue_number'] ?? ('TRIAGE-' . date('Ymd') . '-' . str_pad(1, 3, '0', STR_PAD_LEFT));
        $queue_num_stmt->close();

        // 3. Prepare values
        $chief_complaint_val = !empty($chief_complaint) ? $chief_complaint : '';
        $special_needs_val = !empty($special_needs) ? $special_needs : null;
        $is_vip = 0;

        // 4. ✅ FIXED: Insert into patient_queue with correct column-value mapping
        $insert_sql = "INSERT INTO patient_queue (
                        queue_number, patient_id, visit_id, department_id,
                        next_department_id, queue_status, priority, registration_priority, 
                        registration_type, patient_name, patient_number, phone_number, age, gender,
                        service_type, assigned_doctor_id, chief_complaint, special_needs, is_vip,
                        notification_preference, has_appointment, vitals_taken,
                        arrival_time, queue_entry_time, created_by, created_at
                    ) VALUES (?, ?, ?, ?, ?, 'WAITING', ?, 'NORMAL', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'SMS', ?, 0, NOW(), NOW(), ?, NOW())";

        $stmt = $conn->prepare($insert_sql);
        if (!$stmt) throw new Exception('Prepare failed: ' . $conn->error);

        // ✅ FIXED: Properly bind all parameters including is_vip
        // Handle next_department_id NULL case
        if ($next_department_id === null) {
            $stmt->bind_param(
                "siiissssssisssissiii",
                $queue_number,
                $patient_id,
                $visit_id,
                $triage_department_id,
                $next_department_id,  // NULL will be properly handled
                $priority,
                $registration_type,
                $patient['full_name'],
                $patient['patient_number'],
                $phone_number,
                $age,
                $gender,
                $service_type,
                $assigned_doctor_id,
                $chief_complaint_val,
                $special_needs_val,
                $is_vip,              // ✅ Now properly bound
                $has_appointment,
                $user_id
            );
        } else {
            $stmt->bind_param(
                "siiiissssisssissiii",
                $queue_number,
                $patient_id,
                $visit_id,
                $triage_department_id,
                $next_department_id,
                $priority,
                $registration_type,
                $patient['full_name'],
                $patient['patient_number'],
                $phone_number,
                $age,
                $gender,
                $service_type,
                $assigned_doctor_id,
                $chief_complaint_val,
                $special_needs_val,
                $is_vip,              // ✅ Now properly bound
                $has_appointment,
                $user_id
            );
        }

        if (!$stmt->execute()) {
            throw new Exception('Failed to add patient to triage queue: ' . $stmt->error);
        }
        
        $queue_id = $conn->insert_id;
        $stmt->close();

        // 5. Update queue positions and wait times
        @$conn->query("CALL UpdateQueuePositions($triage_department_id)");
        @$conn->query("CALL UpdateQueueWaitTimes($triage_department_id)");

        // 6. Get position for response
        $pos_sql = "SELECT position_in_queue, estimated_wait_minutes FROM patient_queue WHERE queue_id = ?";
        $pos_stmt = $conn->prepare($pos_sql);
        $pos_stmt->bind_param("i", $queue_id);
        $pos_stmt->execute();
        $pos_row = $pos_stmt->get_result()->fetch_assoc();
        $position = $pos_row['position_in_queue'] ?? 0;
        $estimated_wait = $pos_row['estimated_wait_minutes'] ?? 0;
        $pos_stmt->close();

        // 7. Log activity
        $activity_sql = "INSERT INTO activity_logs (
                            user_id, action, entity_type, entity_id, description,
                            ip_address, user_agent, status, created_at
                        ) VALUES (?, 'CREATE', 'patient_queue', ?, ?, ?, ?, 'SUCCESS', NOW())";
        
        $stmt = $conn->prepare($activity_sql);
        $action_desc = $next_department_id
            ? "Added patient {$patient['full_name']} ({$patient['patient_number']}) to triage queue (route to {$department['department_name']})"
            : "Added patient {$patient['full_name']} ({$patient['patient_number']}) to triage queue";
        $ip_address = $_SERVER['REMOTE_ADDR'] ?? '';
        $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
        
        $stmt->bind_param("iisss", $user_id, $queue_id, $action_desc, $ip_address, $user_agent);
        $stmt->execute();
        $stmt->close();

        // Commit transaction
        $conn->commit();

        $routing_msg = $next_department_id
            ? ('After vitals, they will be routed to ' . $department['department_name'])
            : 'Triage only – complete vitals then route manually.';
        echo json_encode([
            'success' => true,
            'message' => 'Patient added to triage queue. ' . $routing_msg,
            'queue_id' => $queue_id,
            'queue_number' => $queue_number,
            'position' => $position,
            'estimated_wait' => $estimated_wait
        ]);

    } catch (Exception $e) {
        $conn->rollback();
        throw $e;
    }

} catch (Exception $e) {
    echo json_encode([
        'success' => false,
        'message' => $e->getMessage()
    ]);
    error_log("Add to queue error: " . $e->getMessage());
    error_log("Stack trace: " . $e->getTraceAsString());
}

$conn->close();
?>