<?php
session_start();
ob_start();  // Buffer output to capture early errors (keep for now)

// Force error display for debugging (remove in production after testing)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// Custom logging
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/../logs/booking_error.log');  // Adjust path if needed

header('Content-Type: application/json; charset=utf-8');
header('X-Content-Type-Options: nosniff');  // Security

$response = [
    'success' => false,
    'message' => 'Unknown error',
    'debug' => []  // Temp: for error details (remove after fixing)
];

$inTransaction = false;  // NEW: Manual flag for transaction state

try {
    // Debug: Log incoming data early
    error_log("Booking request received: " . json_encode($_POST));

    // Check & include DB
    $dbconn_path = __DIR__ . '/../layouts/dbconn.php';
    if (!file_exists($dbconn_path)) {
        throw new Exception("DB config file not found: $dbconn_path");
    }
    include $dbconn_path;

    // Validate connection
    if (!isset($conn) || !$conn) {
        throw new Exception("DB connection variable not set.");
    }
    if ($conn->connect_error) {
        throw new Exception("DB connection failed: " . $conn->connect_error);
    }
    if ($conn->connect_errno) {
        throw new Exception("DB connection errno: " . $conn->connect_errno);
    }

    // Ensure user is logged in
    if (!isset($_SESSION['user_id'])) {
        throw new Exception("Unauthorized access. Please log in.");
    }

    // Validate required POST data
    $required_fields = [
        'patient_id',
        'doctor_id',
        'appointment_type',
        'chief_complaint',
        'appointment_date',
        'appointment_time',
        'slot_id'
    ];
    foreach ($required_fields as $field) {
        if (!isset($_POST[$field]) || $_POST[$field] === '') {
            throw new Exception("Missing required field: $field");
        }
    }

    // Sanitize & collect inputs
    $patient_id = (int) $_POST['patient_id'];
    $doctor_id = (int) $_POST['doctor_id'];
    $appointment_type = strtoupper(trim($_POST['appointment_type']));
    $chief_complaint = trim($_POST['chief_complaint']);
    $appointment_date = trim($_POST['appointment_date']);
    $appointment_time = trim($_POST['appointment_time']);
    $slot_id = (int) $_POST['slot_id'];
    $special_requirements = trim($_POST['special_requirements'] ?? '');
    $booking_source = strtoupper(trim($_POST['booking_source'] ?? 'ONLINE'));
    $created_by = (int) $_SESSION['user_id'];

    // Validate appointment type and source
    $valid_types = ['CONSULTATION', 'FOLLOW_UP', 'PROCEDURE', 'EMERGENCY', 'TELEMEDICINE'];
    if (!in_array($appointment_type, $valid_types)) {
        throw new Exception("Invalid appointment type provided.");
    }

    $valid_sources = ['ONLINE', 'PHONE', 'WALK_IN', 'STAFF'];
    if (!in_array($booking_source, $valid_sources)) {
        throw new Exception("Invalid booking source provided.");
    }

    // Validate date & time formats
    if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $appointment_date)) {
        throw new Exception("Invalid date format. Use YYYY-MM-DD.");
    }

    if (!preg_match('/^\d{2}:\d{2}$/', $appointment_time)) {
        throw new Exception("Invalid time format. Use HH:MM (24-hour).");
    }

    // Begin transaction (add check for support)
    if (!$conn->begin_transaction()) {
        throw new Exception("Failed to start transaction: " . $conn->error);
    }
    $inTransaction = true;  // NEW: Set flag on success

    // Step 1: Verify slot availability
    $check_slot_sql = "SELECT slot_id, booked_patients, max_patients 
                       FROM appointment_slots 
                       WHERE slot_id = ? AND doctor_id = ? 
                       AND slot_date = ? AND start_time = ? AND is_available = 1
                       LIMIT 1";
    $stmt = $conn->prepare($check_slot_sql);
    if (!$stmt) {
        throw new Exception("Prepare failed for slot check: " . $conn->error);
    }
    $stmt->bind_param("iiss", $slot_id, $doctor_id, $appointment_date, $appointment_time);
    $stmt->execute();
    $slot_result = $stmt->get_result();
    $slot = $slot_result->fetch_assoc();
    $stmt->close();

    if (!$slot) {
        throw new Exception("Selected slot is no longer available. Please choose another.");
    }

    // If slot is full
    if ($slot['booked_patients'] >= $slot['max_patients']) {
        throw new Exception("This slot is already fully booked.");
    }

    // Step 2: Insert into appointments table
    $insert_sql = "INSERT INTO appointments (
        appointment_number, patient_id, doctor_id, slot_id, appointment_date,
        appointment_time, appointment_type, booking_source, chief_complaint,
        special_requirements, status, created_at
    ) VALUES ('', ?, ?, ?, ?, ?, ?, ?, ?, ?, 'SCHEDULED', NOW())";

    $stmt = $conn->prepare($insert_sql);
    if (!$stmt) {
        throw new Exception("Prepare failed for appointment insert: " . $conn->error);
    }
    $stmt->bind_param(
        "iiissssss",
        $patient_id,
        $doctor_id,
        $slot_id,
        $appointment_date,
        $appointment_time,
        $appointment_type,
        $booking_source,
        $chief_complaint,
        $special_requirements
    );
    if (!$stmt->execute()) {
        throw new Exception("Failed to insert appointment: " . $stmt->error);
    }
    $appointment_id = $conn->insert_id;
    $stmt->close();

    // Step 3: Generate appointment number
    $appointment_number = 'APP-' . date('Ymd') . '-' . str_pad($appointment_id, 4, '0', STR_PAD_LEFT);
    $update_number_sql = "UPDATE appointments SET appointment_number = ? WHERE appointment_id = ?";
    $stmt = $conn->prepare($update_number_sql);
    if (!$stmt) {
        throw new Exception("Prepare failed for number update: " . $conn->error);
    }
    $stmt->bind_param("si", $appointment_number, $appointment_id);
    $stmt->execute();
    $stmt->close();

    // Step 4: Update slot booking info
    $update_slot_sql = "UPDATE appointment_slots 
                        SET booked_patients = booked_patients + 1,
                            is_available = CASE WHEN booked_patients + 1 >= max_patients THEN 0 ELSE 1 END
                        WHERE slot_id = ?";
    $stmt = $conn->prepare($update_slot_sql);
    if (!$stmt) {
        throw new Exception("Prepare failed for slot update: " . $conn->error);
    }
    $stmt->bind_param("i", $slot_id);
    $stmt->execute();
    $stmt->close();

    // Commit all changes
    if (!$conn->commit()) {
        throw new Exception("Commit failed: " . $conn->error);
    }
    $inTransaction = false;  // NEW: Clear flag on success

    // Build success response
    $response = [
        'success' => true,
        'message' => 'Appointment booked successfully.',
        'appointment_id' => $appointment_id,
        'appointment_number' => $appointment_number
    ];

    // Notification Trigger (WhatsApp)
    try {
        $doc_sql = "SELECT u.full_name, u.phone_primary FROM doctors d JOIN users u ON d.user_id = u.user_id WHERE d.doctor_id = ?";
        $doc_stmt = $conn->prepare($doc_sql);
        $doc_stmt->bind_param("i", $doctor_id);
        $doc_stmt->execute();
        $doc_res = $doc_stmt->get_result()->fetch_assoc();

        $pat_sql = "SELECT u.full_name FROM patients p JOIN users u ON p.user_id = u.user_id WHERE p.patient_id = ?";
        $pat_stmt = $conn->prepare($pat_sql);
        $pat_stmt->bind_param("i", $patient_id);
        $pat_stmt->execute();
        $pat_res = $pat_stmt->get_result()->fetch_assoc();

        if ($doc_res && $pat_res) {
            $wa_path = __DIR__ . '/../includes/WhatsAppIntegration.php';
            if (file_exists($wa_path)) {
                require_once $wa_path;
                $wa = new WhatsAppIntegration($conn);
                $wa->sendAppointmentNotification(
                    $doc_res['phone_primary'],
                    $doc_res['full_name'],
                    $pat_res['full_name'],
                    $appointment_date,
                    $appointment_time
                );
            }
        }
    } catch (Exception $e) {
        // Don't fail the booking if notification fails, just log it
        error_log("Notification Error: " . $e->getMessage());
    }

} catch (Exception $e) {
    // Rollback if needed (FIXED: Use flag instead of in_transaction())
    if ($inTransaction && $conn) {
        $conn->rollback();
        $inTransaction = false;
    }

    $response['success'] = false;
    $response['message'] = $e->getMessage();
    $response['debug'][] = 'Exception at: ' . $e->getFile() . ':' . $e->getLine();  // Temp

    error_log("Booking error: " . $e->getMessage() . " | POST: " . json_encode($_POST ?? []));
} finally {
    if (isset($conn)) {
        $conn->close();
    }
}

// Clean buffer & output
ob_end_clean();
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
exit;
?>