<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/bootstrap.php';

require_permission($conn, 'queue');
process_post_only_or_redirect('../pages/dashboard.php');

ensure_order_branch_column($conn);
ensure_order_return_column($conn);
ensure_order_slide_send_column($conn);
ensure_order_service_at_column($conn);
ensure_car_profile_columns($conn);

$orderId = filter_input(INPUT_POST, 'order_id', FILTER_VALIDATE_INT);
$orderRedirectPath = process_order_redirect_path($orderId);
ensure_post_csrf_or_redirect('job_info_update', $orderRedirectPath);

$phone = trim((string) ($_POST['phone'] ?? ''));
$normalizedPhone = normalize_phone($phone);
$plateNumber = normalize_plate((string) ($_POST['plate_number'] ?? ''));
$province = trim((string) ($_POST['province'] ?? ''));
$vehicleType = trim((string) ($_POST['vehicle_type'] ?? ''));
$hasVehicleTypeInput = array_key_exists('vehicle_type', $_POST);
$brand = trim((string) ($_POST['brand'] ?? ''));
$model = trim((string) ($_POST['model'] ?? ''));
$color = trim((string) ($_POST['color'] ?? ''));
$branchName = normalize_branch_name((string) ($_POST['branch_name'] ?? ''));
$scheduledAtDateRaw = trim((string) ($_POST['scheduled_at_date'] ?? ''));
$scheduledAtTimeRaw = trim((string) ($_POST['scheduled_at_time'] ?? ''));
$slideSendAtDateRaw = trim((string) ($_POST['slide_send_at_date'] ?? ''));
$slideSendAtTimeRaw = trim((string) ($_POST['slide_send_at_time'] ?? ''));
$serviceAtDateRaw = trim((string) ($_POST['service_at_date'] ?? ''));
$serviceAtTimeRaw = trim((string) ($_POST['service_at_time'] ?? ''));
$returnAtDateRaw = trim((string) ($_POST['return_at_date'] ?? ''));
$returnAtTimeRaw = trim((string) ($_POST['return_at_time'] ?? ''));
$scheduledAtRaw = trim((string) ($_POST['scheduled_at'] ?? ''));
$slideSendAtRaw = trim((string) ($_POST['slide_send_at'] ?? ''));
$serviceAtRaw = trim((string) ($_POST['service_at'] ?? ''));
$returnAtRaw = trim((string) ($_POST['return_at'] ?? ''));

if (!$orderId) {
    redirect_with_flash(
        '../pages/dashboard.php',
        'error',
        localized_flash_message('ไม่พบบิลที่ต้องการแก้ไข', 'Invalid job target.')
    );
}

if ($plateNumber === '') {
    redirect_with_flash(
        $orderRedirectPath,
        'error',
        localized_flash_message('กรุณาระบุเลขทะเบียนรถ', 'Plate number is required.')
    );
}

$order = process_load_order_context_or_redirect(
    $conn,
    $orderId,
    '../pages/dashboard.php',
    localized_flash_message('ไม่พบบิลงาน', 'Job was not found.'),
    array(
        'extra_columns' => array(
            'o.scheduled_at',
            'o.slide_send_at',
            'o.service_at',
            'o.return_at',
        ),
        'branch_redirect_path' => '../pages/dashboard.php',
        'branch_message' => localized_flash_message('คุณไม่มีสิทธิ์เข้าถึงสาขานี้', 'You do not have access to this branch.'),
    )
);

process_ensure_permission_or_redirect(
    $conn,
    'queue_edit_open',
    $orderRedirectPath,
    localized_flash_message('คุณไม่มีสิทธิ์แก้ไขข้อมูลงานคิว', 'You do not have permission to edit queue data.')
);

process_ensure_order_editable_or_redirect(
    $order,
    $orderRedirectPath,
    localized_flash_message('ข้อมูลบิลถูกล็อกแล้ว', 'Bill data is locked.')
);

$allowedBranches = authorized_order_branch_options($conn);
$currentOrderBranchName = normalize_branch_name((string) ($order['branch_name'] ?? ''));
if ($currentOrderBranchName !== '' && !in_array($currentOrderBranchName, $allowedBranches, true)) {
    $allowedBranches[] = $currentOrderBranchName;
}
if ($branchName === '' || !in_array($branchName, $allowedBranches, true)) {
    redirect_with_flash(
        $orderRedirectPath,
        'error',
        localized_flash_message('กรุณาเลือกสาขาที่ให้บริการ', 'Service branch is required.')
    );
}

$normalizeDateTime = static function (
    string $dateRaw,
    string $timeRaw,
    string $legacyRaw,
    string|array $missingMessage,
    string|array $invalidMessage
) use ($orderRedirectPath): ?string {
    $dateRaw = trim($dateRaw);
    $timeRaw = trim($timeRaw);
    $legacyRaw = trim($legacyRaw);

    if ($dateRaw === '' && $timeRaw === '' && $legacyRaw === '') {
        return null;
    }

    if ($dateRaw !== '' || $timeRaw !== '') {
        if ($dateRaw === '' || $timeRaw === '') {
            redirect_with_flash($orderRedirectPath, 'error', $missingMessage);
        }

        $timestamp = strtotime($dateRaw . ' ' . $timeRaw);
        if ($timestamp === false) {
            redirect_with_flash($orderRedirectPath, 'error', $invalidMessage);
        }

        return date('Y-m-d H:i:s', $timestamp);
    }

    $timestamp = strtotime($legacyRaw);
    if ($timestamp === false) {
        redirect_with_flash($orderRedirectPath, 'error', $invalidMessage);
    }

    return date('Y-m-d H:i:s', $timestamp);
};

$scheduledAt = $normalizeDateTime(
    $scheduledAtDateRaw,
    $scheduledAtTimeRaw,
    $scheduledAtRaw,
    localized_flash_message('กรุณาเลือกทั้งวันที่และเวลารับสไลด์', 'Please select both date and time for slide pickup.'),
    localized_flash_message('วันเวลารับสไลด์ไม่ถูกต้อง', 'Slide pickup date is invalid.')
);

$slideSendAt = $normalizeDateTime(
    $slideSendAtDateRaw,
    $slideSendAtTimeRaw,
    $slideSendAtRaw,
    localized_flash_message('กรุณาเลือกทั้งวันที่และเวลาส่งสไลด์', 'Please select both date and time for slide delivery.'),
    localized_flash_message('วันเวลาส่งสไลด์ไม่ถูกต้อง', 'Slide delivery date is invalid.')
);

$serviceAt = $normalizeDateTime(
    $serviceAtDateRaw,
    $serviceAtTimeRaw,
    $serviceAtRaw,
    localized_flash_message('กรุณาเลือกทั้งวันที่และเวลาเข้ารับบริการ', 'Please select both date and time for service usage.'),
    localized_flash_message('วันเวลารับบริการไม่ถูกต้อง', 'Service date is invalid.')
);

$returnAt = $normalizeDateTime(
    $returnAtDateRaw,
    $returnAtTimeRaw,
    $returnAtRaw,
    localized_flash_message('กรุณาเลือกทั้งวันที่และเวลารับรถ', 'Please select both date and time for vehicle pickup.'),
    localized_flash_message('วันเวลารับรถไม่ถูกต้อง', 'Vehicle pickup date is invalid.')
);

$carId = (int) ($order['car_id'] ?? 0);
$plateStmt = db_prepare($conn, "
    SELECT car_id
    FROM cars
    WHERE plate_number = ?
        AND car_id <> ?
    LIMIT 1
");
$plateStmt->bind_param('si', $plateNumber, $carId);
$plateStmt->execute();
$plateConflict = $plateStmt->get_result()->fetch_assoc();
$plateStmt->close();

if ($plateConflict) {
    redirect_with_flash(
        $orderRedirectPath,
        'error',
        localized_flash_message('เลขทะเบียนนี้ถูกใช้กับรถคันอื่นแล้ว', 'Plate number is already used by another vehicle.')
    );
}

$storedProfilePhoto = null;
$oldProfilePhotoPath = '';

$conn->begin_transaction();

try {
    $customerId = (int) ($order['customer_id'] ?? 0);
    $billNumber = (string) ($order['bill_number'] ?? '');

    $customerSnapshotStmt = db_prepare($conn, "
        SELECT name, phone
        FROM customers
        WHERE customer_id = ?
        LIMIT 1
    ");
    $customerSnapshotStmt->bind_param('i', $customerId);
    $customerSnapshotStmt->execute();
    $customerSnapshot = $customerSnapshotStmt->get_result()->fetch_assoc() ?: array();
    $customerSnapshotStmt->close();

    $customerBefore = array(
        'phone' => (string) ($customerSnapshot['phone'] ?? ''),
    );
    $customerAfter = array(
        'phone' => $phone,
    );

    $carSnapshotStmt = db_prepare($conn, "
        SELECT
            plate_number,
            province,
            vehicle_type,
            brand,
            model,
            color,
            profile_image_path,
            profile_image_name
        FROM cars
        WHERE car_id = ?
        LIMIT 1
    ");
    $carSnapshotStmt->bind_param('i', $carId);
    $carSnapshotStmt->execute();
    $carSnapshot = $carSnapshotStmt->get_result()->fetch_assoc() ?: array();
    $carSnapshotStmt->close();

    $carBefore = array(
        'plate_number' => (string) ($carSnapshot['plate_number'] ?? ''),
        'province' => (string) ($carSnapshot['province'] ?? ''),
        'vehicle_type' => (string) ($carSnapshot['vehicle_type'] ?? ''),
        'brand' => (string) ($carSnapshot['brand'] ?? ''),
        'model' => (string) ($carSnapshot['model'] ?? ''),
        'color' => (string) ($carSnapshot['color'] ?? ''),
        'profile_image_path' => (string) ($carSnapshot['profile_image_path'] ?? ''),
    );
    $oldProfilePhotoPath = (string) ($carSnapshot['profile_image_path'] ?? '');
    $storedProfilePhoto = store_car_profile_upload(car_profile_uploaded_file_from_request('car_profile_photo'), 'car-profile-' . $carId);
    $resolvedVehicleType = $hasVehicleTypeInput
        ? $vehicleType
        : (string) ($carSnapshot['vehicle_type'] ?? '');
    $carAfter = array(
        'plate_number' => $plateNumber,
        'province' => $province,
        'vehicle_type' => $resolvedVehicleType,
        'brand' => $brand,
        'model' => $model,
        'color' => $color,
        'profile_image_path' => $storedProfilePhoto ? (string) ($storedProfilePhoto['file_path'] ?? '') : $oldProfilePhotoPath,
    );

    $jobBefore = array(
        'branch_name' => (string) ($order['branch_name'] ?? ''),
        'slide_pickup_at' => $order['scheduled_at'] ? (string) $order['scheduled_at'] : null,
        'slide_delivery_at' => $order['slide_send_at'] ? (string) $order['slide_send_at'] : null,
        'service_at' => $order['service_at'] ? (string) $order['service_at'] : null,
        'vehicle_pickup_at' => $order['return_at'] ? (string) $order['return_at'] : null,
    );
    $jobAfter = array(
        'branch_name' => $branchName,
        'slide_pickup_at' => $scheduledAt,
        'slide_delivery_at' => $slideSendAt,
        'service_at' => $serviceAt,
        'vehicle_pickup_at' => $returnAt,
    );

    $customerStmt = db_prepare($conn, "
        UPDATE customers
        SET phone = ?,
            normalized_phone = ?
        WHERE customer_id = ?
    ");
    $customerStmt->bind_param('ssi', $phone, $normalizedPhone, $customerId);
    $customerStmt->execute();
    $customerStmt->close();

    $carStmt = db_prepare($conn, "
        UPDATE cars
        SET plate_number = ?,
            province = ?,
            vehicle_type = ?,
            brand = ?,
            model = ?,
            color = ?
        WHERE car_id = ?
    ");
    $carStmt->bind_param('ssssssi', $plateNumber, $province, $resolvedVehicleType, $brand, $model, $color, $carId);
    $carStmt->execute();
    $carStmt->close();

    if ($storedProfilePhoto) {
        $photoStmt = db_prepare($conn, "
            UPDATE cars
            SET profile_image_path = ?,
                profile_image_name = ?,
                profile_image_mime_type = ?,
                profile_image_uploaded_at = ?
            WHERE car_id = ?
        ");
        $photoStmt->bind_param(
            'ssssi',
            $storedProfilePhoto['file_path'],
            $storedProfilePhoto['file_name'],
            $storedProfilePhoto['mime_type'],
            $storedProfilePhoto['uploaded_at'],
            $carId
        );
        $photoStmt->execute();
        $photoStmt->close();
    }

    $orderUpdateStmt = db_prepare($conn, "
        UPDATE orders
        SET branch_name = ?,
            scheduled_at = ?,
            slide_send_at = ?,
            service_at = ?,
            return_at = ?
        WHERE order_id = ?
    ");
    $orderUpdateStmt->bind_param('sssssi', $branchName, $scheduledAt, $slideSendAt, $serviceAt, $returnAt, $orderId);
    $orderUpdateStmt->execute();
    $orderUpdateStmt->close();

    $customerDiff = audit_diff_assoc($customerBefore, $customerAfter);
    if (!empty($customerDiff['after'])) {
        audit_log($conn, array(
            'module_key' => 'customer',
            'action_key' => 'update',
            'entity_type' => 'customer',
            'entity_id' => $customerId,
            'order_id' => $orderId,
            'customer_id' => $customerId,
            'car_id' => $carId,
            'branch_name' => $branchName,
            'bill_number' => $billNumber,
            'message' => 'Customer updated from job information.',
            'before' => $customerDiff['before'],
            'after' => $customerDiff['after'],
        ));
    }

    $carDiff = audit_diff_assoc($carBefore, $carAfter);
    if (!empty($carDiff['after'])) {
        audit_log($conn, array(
            'module_key' => 'car',
            'action_key' => 'update',
            'entity_type' => 'car',
            'entity_id' => $carId,
            'order_id' => $orderId,
            'customer_id' => $customerId,
            'car_id' => $carId,
            'branch_name' => $branchName,
            'bill_number' => $billNumber,
            'message' => 'Vehicle updated from job information.',
            'before' => $carDiff['before'],
            'after' => $carDiff['after'],
        ));
    }

    $jobDiff = audit_diff_assoc($jobBefore, $jobAfter);
    if (!empty($jobDiff['after'])) {
        audit_log($conn, array(
            'module_key' => 'queue',
            'action_key' => 'update',
            'entity_type' => 'order',
            'entity_id' => $orderId,
            'order_id' => $orderId,
            'customer_id' => $customerId,
            'car_id' => $carId,
            'branch_name' => $branchName,
            'bill_number' => $billNumber,
            'message' => 'Job information updated.',
            'before' => $jobDiff['before'],
            'after' => $jobDiff['after'],
        ));
    }

    $conn->commit();
    $_SESSION['booking_branch_name'] = $branchName;

    if ($storedProfilePhoto && $oldProfilePhotoPath !== '' && $oldProfilePhotoPath !== (string) ($storedProfilePhoto['file_path'] ?? '')) {
        delete_car_profile_file($oldProfilePhotoPath);
    }

    redirect_with_flash(
        $orderRedirectPath,
        'success',
        localized_flash_message('อัปเดตข้อมูลงานเรียบร้อยแล้ว', 'Job information updated.')
    );
} catch (Throwable $exception) {
    process_handle_exception_and_redirect(
        $conn,
        $exception,
        'update_job_info',
        $orderRedirectPath,
        localized_flash_message('บันทึกข้อมูลงานไม่สำเร็จ', 'Job information was not saved.'),
        array(
            'order_id' => $orderId,
            'customer_id' => (int) ($order['customer_id'] ?? 0),
            'car_id' => $carId,
            'branch_name' => $branchName,
            'plate_number' => $plateNumber,
        ),
        array(),
        false,
        static function () use ($storedProfilePhoto): void {
            if (is_array($storedProfilePhoto) && !empty($storedProfilePhoto['absolute_path']) && is_file((string) $storedProfilePhoto['absolute_path'])) {
                @unlink((string) $storedProfilePhoto['absolute_path']);
            }
        }
    );
}
