<?php
// csr/ajax/update_request_status.php
require_once '../../config/database.php';
session_start();

require_once 'csr_request_lock_helper.php';
require_once '../../includes/chat_helper.php';
require_once '../../includes/app_helpers.php';

header('Content-Type: application/json');
ob_start();

if (!isset($_SESSION['csr_id'])) {
    echo json_encode([
        'success' => false,
        'message' => 'Unauthorized'
    ]);
    exit();
}

$request_id = isset($_POST['request_id']) ? (int)$_POST['request_id'] : 0;
$job_status_id = isset($_POST['job_status_id']) ? (int)$_POST['job_status_id'] : 0;
$status_notes = isset($_POST['status_notes']) ? trim($_POST['status_notes']) : '';

if (!$request_id || !$job_status_id) {
    echo json_encode([
        'success' => false,
        'message' => 'Invalid request. Missing request ID or status.'
    ]);
    exit();
}

if ($job_status_id < 1 || $job_status_id > 5) {
    echo json_encode([
        'success' => false,
        'message' => 'Invalid status value.'
    ]);
    exit();
}

try {
    $database = new Database();
    $db = $database->getConnection();

    ensureRequestLockTable($db);
    ensureChatTables($db);
    ensureOperationalTables($db);
    ensureUnifiedTicketWorkflow($db);
    ensureCsrTeamTables($db);
    requireCsrRequestAccessJson($db, (int)$_SESSION['csr_id'], $request_id);

    /*
        IMPORTANT:
        We only commit/rollback if PDO still has an active transaction.
        This prevents the false error:
        "There is no active transaction"
    */
    if (!$db->inTransaction()) {
        $db->beginTransaction();
    }

    // Get current request status
    $query = "
        SELECT 
            job_status_id, 
            request_number, 
            customer_id 
        FROM service_requests 
        WHERE id = :request_id
        LIMIT 1
    ";

    $stmt = $db->prepare($query);
    $stmt->execute([
        ':request_id' => $request_id
    ]);

    $current = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$current) {
        if ($db->inTransaction()) {
            $db->rollBack();
        }

        echo json_encode([
            'success' => false,
            'message' => 'Request not found.'
        ]);
        exit();
    }

    if ((int)$current['job_status_id'] === $job_status_id) {
        if ($db->inTransaction()) {
            $db->rollBack();
        }

        echo json_encode([
            'success' => false,
            'message' => 'Status is already set to this value.'
        ]);
        exit();
    }

    // Get CSR name
    $query = "
        SELECT CONCAT(first_name, ' ', last_name) AS csr_name
        FROM csr_users
        WHERE id = :csr_id
        LIMIT 1
    ";

    $stmt = $db->prepare($query);
    $stmt->execute([
        ':csr_id' => $_SESSION['csr_id']
    ]);

    $csr = $stmt->fetch(PDO::FETCH_ASSOC);
    $csr_name = $csr ? $csr['csr_name'] : 'CSR';

    // Acquire request lock
    $lockResult = acquireRequestLock($db, $request_id, $_SESSION['csr_id'], $csr_name);

    if (!$lockResult['success']) {
        if ($db->inTransaction()) {
            $db->rollBack();
        }

        echo json_encode($lockResult);
        exit();
    }

    // Update request status
    $query = "
        UPDATE service_requests 
        SET job_status_id = :status_id,
            last_updated_at = NOW(),
            in_progress_started_at = CASE WHEN :status_id_case = 3 AND in_progress_started_at IS NULL THEN NOW() ELSE in_progress_started_at END
        WHERE id = :request_id
    ";

    $stmt = $db->prepare($query);
    $stmt->execute([
        ':status_id' => $job_status_id,
        ':status_id_case' => $job_status_id,
        ':request_id' => $request_id
    ]);

    // If Repair Completed
    if ($job_status_id === 4) {
        $query = "
            UPDATE service_requests 
            SET completed_date = CURDATE()
            WHERE id = :request_id
        ";

        $stmt = $db->prepare($query);
        $stmt->execute([
            ':request_id' => $request_id
        ]);

        $query = "
            UPDATE service_assignments
            SET 
                status = 'completed',
                completion_time = NOW()
            WHERE request_id = :request_id
            AND status IN ('assigned', 'en_route', 'on_site')
        ";

        $stmt = $db->prepare($query);
        $stmt->execute([
            ':request_id' => $request_id
        ]);

        $query = "
            UPDATE technicians t
            SET t.status_id = 1
            WHERE t.id IN (
                SELECT technician_id FROM (
                    SELECT sa.technician_id
                    FROM service_assignments sa
                    WHERE sa.request_id = :request_id
                ) assigned_techs
            )
            AND NOT EXISTS (
                SELECT 1 
                FROM service_assignments active_sa
                WHERE active_sa.technician_id = t.id
                AND active_sa.status IN ('assigned', 'en_route', 'on_site')
            )
        ";

        $stmt = $db->prepare($query);
        $stmt->execute([
            ':request_id' => $request_id
        ]);
    }

    // If Cancelled
    if ($job_status_id === 5) {
        $query = "
            UPDATE service_assignments
            SET status = 'cancelled'
            WHERE request_id = :request_id
            AND status IN ('assigned', 'en_route', 'on_site')
        ";

        $stmt = $db->prepare($query);
        $stmt->execute([
            ':request_id' => $request_id
        ]);

        $query = "
            UPDATE technicians t
            SET t.status_id = 1
            WHERE t.id IN (
                SELECT technician_id FROM (
                    SELECT sa.technician_id
                    FROM service_assignments sa
                    WHERE sa.request_id = :request_id
                ) assigned_techs
            )
            AND NOT EXISTS (
                SELECT 1 
                FROM service_assignments active_sa
                WHERE active_sa.technician_id = t.id
                AND active_sa.status IN ('assigned', 'en_route', 'on_site')
            )
        ";

        $stmt = $db->prepare($query);
        $stmt->execute([
            ':request_id' => $request_id
        ]);

        if (empty($status_notes)) {
            $status_notes = "Request cancelled by CSR.";
        }
    }

    // Get status name
    $query = "
        SELECT status_name 
        FROM job_statuses 
        WHERE id = :status_id
        LIMIT 1
    ";

    $stmt = $db->prepare($query);
    $stmt->execute([
        ':status_id' => $job_status_id
    ]);

    $status = $stmt->fetch(PDO::FETCH_ASSOC);
    $status_name = $status ? $status['status_name'] : 'Unknown';

    // Log request action
    try {
        logRequestAction(
            $db,
            $request_id,
            $_SESSION['csr_id'],
            'csr',
            'status_change',
            $current['job_status_id'],
            $job_status_id,
            $status_notes
        );
    } catch (Exception $e) {
        error_log('logRequestAction warning: ' . $e->getMessage());
    }

    // Log CSR activity
    try {
        logCSRActivity(
            $db,
            $_SESSION['csr_id'],
            'status_change',
            $request_id,
            'Changed request status to ' . $job_status_id
        );
    } catch (Exception $e) {
        error_log('logCSRActivity warning: ' . $e->getMessage());
    }

    // Add status history
    $history_notes = "Status changed to: {$status_name}";

    if (!empty($status_notes)) {
        $history_notes .= " - Notes: {$status_notes}";
    }

    $query = "
        INSERT INTO request_status_history
            (request_id, job_status_id, notes, changed_by, changed_at)
        VALUES
            (:request_id, :status_id, :notes, :changed_by, NOW())
    ";

    $stmt = $db->prepare($query);
    $stmt->execute([
        ':request_id' => $request_id,
        ':status_id' => $job_status_id,
        ':notes' => $history_notes,
        ':changed_by' => $csr_name
    ]);

    // Add request note
    $note_content = "Status updated to: {$status_name}";

    if (!empty($status_notes)) {
        $note_content .= "\n\nNotes: {$status_notes}";
    }

    $query = "
        INSERT INTO request_notes
            (request_id, csr_id, note_type, note_content, created_at)
        VALUES
            (:request_id, :csr_id, 'internal', :note_content, NOW())
    ";

    $stmt = $db->prepare($query);
    $stmt->execute([
        ':request_id' => $request_id,
        ':csr_id' => $_SESSION['csr_id'],
        ':note_content' => $note_content
    ]);

    // If set to Assigned but no technician exists
    if ($job_status_id === 2) {
        $query = "
            SELECT COUNT(*) AS count
            FROM service_assignments
            WHERE request_id = :request_id
            AND status IN ('assigned', 'en_route', 'on_site')
        ";

        $stmt = $db->prepare($query);
        $stmt->execute([
            ':request_id' => $request_id
        ]);

        $assignments = $stmt->fetch(PDO::FETCH_ASSOC);

        if ((int)$assignments['count'] === 0) {
            $note_content = "Status set to 'Assigned' but no technician has been assigned yet. Please assign a technician.";

            $query = "
                INSERT INTO request_notes
                    (request_id, csr_id, note_type, note_content, created_at)
                VALUES
                    (:request_id, :csr_id, 'internal', :note_content, NOW())
            ";

            $stmt = $db->prepare($query);
            $stmt->execute([
                ':request_id' => $request_id,
                ':csr_id' => $_SESSION['csr_id'],
                ':note_content' => $note_content
            ]);
        }
    }

    // Auto chat message and customer notification
    if (!empty($current['customer_id'])) {
        try {
            $customerMsg = "Your repair request #{$current['request_number']} status is now: {$status_name}.";

            if (!empty($status_notes)) {
                $customerMsg .= "\n\nNotes: {$status_notes}";
            }

            addSystemChatMessageForRequest($db, $request_id, $customerMsg, 'status');
            createCustomerNotification($db, $request_id, 'Request Status Updated', $customerMsg, 'info');

        } catch (Exception $chatEx) {
            error_log('Status chat/notification warning: ' . $chatEx->getMessage());
        }
    }

    // Activity log
    try {
        $activity = $csr_name . " changed status of Ticket #" . $current['request_number'] . " to " . $status_name;

        $logQuery = "
            INSERT INTO csr_activity_logs 
                (csr_id, request_id, activity) 
            VALUES 
                (:csr_id, :request_id, :activity)
        ";

        $logStmt = $db->prepare($logQuery);
        $logStmt->execute([
            ':csr_id' => $_SESSION['csr_id'],
            ':request_id' => $request_id,
            ':activity' => $activity
        ]);

    } catch (Exception $e) {
        error_log('CSR activity log warning: ' . $e->getMessage());
    }

    /*
        Safe commit.
        This is the main fix.
        If a helper already closed the transaction,
        we do not call commit again.
    */
    if ($db->inTransaction()) {
        $db->commit();
    }

    if (ob_get_length()) {
        ob_clean();
    }

    echo json_encode([
        'success' => true,
        'message' => 'Status updated successfully!',
        'new_status_id' => $job_status_id,
        'new_status_name' => $status_name
    ]);
    exit();

} catch (Exception $e) {
    if (isset($db) && $db instanceof PDO && $db->inTransaction()) {
        $db->rollBack();
    }

    if (ob_get_length()) {
        ob_clean();
    }

    echo json_encode([
        'success' => false,
        'message' => 'Failed to update status: ' . $e->getMessage()
    ]);
    exit();
}
?>