<?php
declare(strict_types=1);

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

function open_bill_request_expects_json(): bool
{
    $accept = strtolower(trim((string) ($_SERVER['HTTP_ACCEPT'] ?? '')));
    $requestedWith = strtolower(trim((string) ($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '')));

    return str_contains($accept, 'application/json') || $requestedWith === 'xmlhttprequest';
}

function open_bill_json_response(int $statusCode, array $payload): void
{
    http_response_code($statusCode);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit();
}

function open_bill_json_message(string $th, string $en, array $replacements = array()): string
{
    return resolve_localized_flash_message(localized_flash_message($th, $en, $replacements));
}

$expectsJson = open_bill_request_expects_json();

if ($expectsJson && !is_logged_in($conn)) {
    $_SESSION['intended_url'] = (string) ($_SERVER['HTTP_REFERER'] ?? ($_SERVER['REQUEST_URI'] ?? ''));
    open_bill_json_response(401, array(
        'success' => false,
        'message' => open_bill_json_message('เซสชันหมดอายุ กรุณาเข้าสู่ระบบอีกครั้ง', 'Your session expired. Please login again.'),
        'field_errors' => array(),
        'redirect_url' => auth_page_path('login.php'),
        'error_code' => 'auth_required',
    ));
}

require_login($conn);

if (!can_access_open_bill($conn)) {
    if ($expectsJson) {
        open_bill_json_response(403, array(
            'success' => false,
            'message' => open_bill_json_message('คุณไม่มีสิทธิ์ใช้งานฟังก์ชันนี้', 'You do not have permission to access that function.'),
            'field_errors' => array(),
            'redirect_url' => auth_page_path(auth_preferred_landing_page($conn)),
            'error_code' => 'permission_denied',
        ));
    }

    redirect_with_flash(
        auth_page_path(auth_preferred_landing_page($conn)),
        'error',
        localized_flash_message('คุณไม่มีสิทธิ์ใช้งานฟังก์ชันนี้', 'You do not have permission to access that function.')
    );
}

process_post_only_or_redirect('../pages/open_bill.php');

$lookupQuery = trim((string) ($_POST['lookup_query'] ?? ''));
$customerName = trim((string) ($_POST['customer_name'] ?? ''));
$phone = trim((string) ($_POST['phone'] ?? ''));
$phoneDigits = normalize_phone($phone);
$plateNumber = normalize_plate((string) ($_POST['plate_number'] ?? ''));
$province = trim((string) ($_POST['province'] ?? ''));
$brand = trim((string) ($_POST['brand'] ?? ''));
$model = trim((string) ($_POST['model'] ?? ''));
$color = trim((string) ($_POST['color'] ?? ''));
$carPhotoFile = car_profile_uploaded_file_from_request('car_photo');

$redirectQuery = array('new' => '1');
if ($lookupQuery !== '') {
    $redirectQuery['q'] = $lookupQuery;
}
$redirectPath = '../pages/open_bill.php?' . http_build_query($redirectQuery);

$oldInput = array(
    'lookup_query' => $lookupQuery,
    'customer_name' => $customerName,
    'phone' => $phone,
    'plate_number' => $plateNumber,
    'province' => $province,
    'brand' => $brand,
    'model' => $model,
    'color' => $color,
);

if (!is_valid_csrf_token((string) ($_POST['csrf_token'] ?? ''), 'open_bill_customer_save')) {
    if ($expectsJson) {
        open_bill_json_response(419, array(
            'success' => false,
            'message' => open_bill_json_message('เซสชันหมดอายุ กรุณาลองใหม่อีกครั้ง', 'Your session expired. Please try again.'),
            'field_errors' => array(),
            'redirect_url' => $redirectPath,
            'error_code' => 'csrf_expired',
        ));
    }

    ensure_post_csrf_or_redirect('open_bill_customer_save', $redirectPath, $oldInput);
}

ensure_customer_group_column($conn);
ensure_car_profile_columns($conn);

if ($customerName === '' || $plateNumber === '') {
    if ($expectsJson) {
        $fieldErrors = array();
        if ($customerName === '') {
            $fieldErrors['customer_name'] = open_bill_json_message('กรุณาระบุชื่อลูกค้า', 'Customer name is required.');
        }
        if ($plateNumber === '') {
            $fieldErrors['plate_number'] = open_bill_json_message('กรุณาระบุทะเบียนรถ', 'Plate number is required.');
        }

        open_bill_json_response(422, array(
            'success' => false,
            'message' => open_bill_json_message('กรุณาระบุชื่อลูกค้าและทะเบียนรถ', 'Customer name and plate number are required.'),
            'field_errors' => $fieldErrors,
        ));
    }

    redirect_with_flash(
        $redirectPath,
        'error',
        localized_flash_message('กรุณาระบุชื่อลูกค้าและทะเบียนรถ', 'Customer name and plate number are required.'),
        $oldInput
    );
}

$conn->begin_transaction();
$storedPhoto = null;
$oldPhotoPathToDelete = '';
$transactionCommitted = false;

try {
    $customerId = 0;
    $carId = 0;
    $customerBefore = array();
    $customerAfter = array();
    $customerAction = '';
    $carBefore = array();
    $carAfter = array();
    $carAction = '';

    $carLookupStmt = db_prepare($conn, "
        SELECT car_id, customer_id
        FROM cars
        WHERE plate_number = ?
        LIMIT 1
    ");
    $carLookupStmt->bind_param('s', $plateNumber);
    $carLookupStmt->execute();
    $existingCar = $carLookupStmt->get_result()->fetch_assoc();
    $carLookupStmt->close();

    if ($existingCar) {
        $carId = (int) ($existingCar['car_id'] ?? 0);
        $customerId = (int) ($existingCar['customer_id'] ?? 0);

        if (!customer_lookup_has_branch_access($conn, $customerId)) {
            throw new RuntimeException(open_bill_json_message('คุณไม่มีสิทธิ์เข้าถึงข้อมูลลูกค้ารายนี้', 'You do not have access to this customer record.'));
        }

        $customerSnapshotStmt = db_prepare($conn, "
            SELECT customer_id, name, phone, customer_group
            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(
            'name' => (string) ($customerSnapshot['name'] ?? ''),
            'phone' => (string) ($customerSnapshot['phone'] ?? ''),
            'customer_group' => customer_group_key((string) ($customerSnapshot['customer_group'] ?? 'member')),
        );

        $carSnapshotStmt = db_prepare($conn, "
            SELECT
                car_id,
                plate_number,
                province,
                brand,
                model,
                color,
                profile_image_path,
                profile_image_name,
                profile_image_mime_type,
                profile_image_uploaded_at
            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'] ?? ''),
            'brand' => (string) ($carSnapshot['brand'] ?? ''),
            'model' => (string) ($carSnapshot['model'] ?? ''),
            'color' => (string) ($carSnapshot['color'] ?? ''),
            'profile_image_path' => (string) ($carSnapshot['profile_image_path'] ?? ''),
        );

        $existingProfileImagePath = (string) ($carSnapshot['profile_image_path'] ?? '');
        $existingProfileImageName = (string) ($carSnapshot['profile_image_name'] ?? '');
        $existingProfileImageMimeType = (string) ($carSnapshot['profile_image_mime_type'] ?? '');
        $existingProfileImageUploadedAt = (string) ($carSnapshot['profile_image_uploaded_at'] ?? '');

        $storedPhoto = store_car_profile_upload(is_array($carPhotoFile) ? $carPhotoFile : null, 'car-profile');
        $resolvedProfileImagePath = $storedPhoto['file_path'] ?? $existingProfileImagePath;
        $resolvedProfileImageName = $storedPhoto['file_name'] ?? $existingProfileImageName;
        $resolvedProfileImageMimeType = $storedPhoto['mime_type'] ?? $existingProfileImageMimeType;
        $resolvedProfileImageUploadedAt = $storedPhoto['uploaded_at'] ?? $existingProfileImageUploadedAt;

        $updateCustomerStmt = db_prepare($conn, "
            UPDATE customers
            SET name = ?, phone = ?, normalized_phone = ?, customer_group = 'member'
            WHERE customer_id = ?
        ");
        $updateCustomerStmt->bind_param('sssi', $customerName, $phone, $phoneDigits, $customerId);
        $updateCustomerStmt->execute();
        $updateCustomerStmt->close();

        $updateCarStmt = db_prepare($conn, "
            UPDATE cars
            SET
                province = ?,
                brand = ?,
                model = ?,
                color = ?,
                profile_image_path = ?,
                profile_image_name = ?,
                profile_image_mime_type = ?,
                profile_image_uploaded_at = NULLIF(?, '')
            WHERE car_id = ?
        ");
        $updateCarStmt->bind_param(
            'ssssssssi',
            $province,
            $brand,
            $model,
            $color,
            $resolvedProfileImagePath,
            $resolvedProfileImageName,
            $resolvedProfileImageMimeType,
            $resolvedProfileImageUploadedAt,
            $carId
        );
        $updateCarStmt->execute();
        $updateCarStmt->close();

        if ($storedPhoto !== null && $existingProfileImagePath !== '' && $existingProfileImagePath !== $resolvedProfileImagePath) {
            $oldPhotoPathToDelete = $existingProfileImagePath;
        }

        $customerAfter = array(
            'name' => $customerName,
            'phone' => $phone,
            'customer_group' => 'member',
        );
        $carAfter = array(
            'plate_number' => $plateNumber,
            'province' => $province,
            'brand' => $brand,
            'model' => $model,
            'color' => $color,
            'profile_image_path' => $resolvedProfileImagePath,
        );
        $customerAction = 'update';
        $carAction = 'update';
    } else {
        if ($phoneDigits !== '') {
            $customerLookupStmt = db_prepare($conn, "
                SELECT customer_id
                FROM customers
                WHERE normalized_phone = ?
                ORDER BY customer_id DESC
                LIMIT 1
            ");
            $customerLookupStmt->bind_param('s', $phoneDigits);
            $customerLookupStmt->execute();
            $existingCustomer = $customerLookupStmt->get_result()->fetch_assoc();
            $customerLookupStmt->close();

            if ($existingCustomer) {
                $customerId = (int) ($existingCustomer['customer_id'] ?? 0);

                if (!customer_lookup_has_branch_access($conn, $customerId)) {
                    throw new RuntimeException(open_bill_json_message('คุณไม่มีสิทธิ์เข้าถึงข้อมูลลูกค้ารายนี้', 'You do not have access to this customer record.'));
                }

                $customerSnapshotStmt = db_prepare($conn, "
                    SELECT customer_id, name, phone, customer_group
                    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(
                    'name' => (string) ($customerSnapshot['name'] ?? ''),
                    'phone' => (string) ($customerSnapshot['phone'] ?? ''),
                    'customer_group' => customer_group_key((string) ($customerSnapshot['customer_group'] ?? 'member')),
                );

                $updateCustomerStmt = db_prepare($conn, "
                    UPDATE customers
                    SET name = ?, phone = ?, normalized_phone = ?, customer_group = 'member'
                    WHERE customer_id = ?
                ");
                $updateCustomerStmt->bind_param('sssi', $customerName, $phone, $phoneDigits, $customerId);
                $updateCustomerStmt->execute();
                $updateCustomerStmt->close();

                $customerAfter = array(
                    'name' => $customerName,
                    'phone' => $phone,
                    'customer_group' => 'member',
                );
                $customerAction = 'update';
            }
        }

        if ($customerId === 0) {
            $insertCustomerStmt = db_prepare($conn, "
                INSERT INTO customers (name, phone, normalized_phone, customer_group)
                VALUES (?, ?, ?, 'member')
            ");
            $insertCustomerStmt->bind_param('sss', $customerName, $phone, $phoneDigits);
            $insertCustomerStmt->execute();
            $customerId = (int) $conn->insert_id;
            $insertCustomerStmt->close();

            $customerAfter = array(
                'name' => $customerName,
                'phone' => $phone,
                'customer_group' => 'member',
            );
            $customerAction = 'create';
        }

        $storedPhoto = store_car_profile_upload(is_array($carPhotoFile) ? $carPhotoFile : null, 'car-profile');
        $profileImagePath = (string) ($storedPhoto['file_path'] ?? '');
        $profileImageName = (string) ($storedPhoto['file_name'] ?? '');
        $profileImageMimeType = (string) ($storedPhoto['mime_type'] ?? '');
        $profileImageUploadedAt = (string) ($storedPhoto['uploaded_at'] ?? '');

        $insertCarStmt = db_prepare($conn, "
            INSERT INTO cars (
                customer_id,
                plate_number,
                province,
                vehicle_type,
                brand,
                model,
                color,
                profile_image_path,
                profile_image_name,
                profile_image_mime_type,
                profile_image_uploaded_at
            )
            VALUES (?, ?, ?, '', ?, ?, ?, ?, ?, ?, NULLIF(?, ''))
        ");
        $insertCarStmt->bind_param(
            'isssssssss',
            $customerId,
            $plateNumber,
            $province,
            $brand,
            $model,
            $color,
            $profileImagePath,
            $profileImageName,
            $profileImageMimeType,
            $profileImageUploadedAt
        );
        $insertCarStmt->execute();
        $carId = (int) $conn->insert_id;
        $insertCarStmt->close();

        $carAfter = array(
            'plate_number' => $plateNumber,
            'province' => $province,
            'brand' => $brand,
            'model' => $model,
            'color' => $color,
            'profile_image_path' => $profileImagePath,
        );
        $carAction = 'create';
    }

    if ($customerAction !== '') {
        $customerDiff = audit_diff_assoc($customerBefore, $customerAfter);
        $customerAuditAfter = $customerAction === 'create' ? $customerAfter : $customerDiff['after'];
        $customerAuditBefore = $customerAction === 'create' ? array() : $customerDiff['before'];

        if ($customerAction === 'create' || !empty($customerAuditAfter)) {
            audit_log($conn, array(
                'module_key' => 'open_bill',
                'action_key' => $customerAction,
                'entity_type' => 'customer',
                'entity_id' => $customerId,
                'customer_id' => $customerId,
                'car_id' => $carId > 0 ? $carId : null,
                'message' => $customerAction === 'create'
                    ? 'Customer created from Open Bill.'
                    : 'Customer updated from Open Bill.',
                'before' => $customerAuditBefore,
                'after' => $customerAuditAfter,
            ));
        }
    }

    if ($carAction !== '') {
        $carDiff = audit_diff_assoc($carBefore, $carAfter);
        $carAuditAfter = $carAction === 'create' ? $carAfter : $carDiff['after'];
        $carAuditBefore = $carAction === 'create' ? array() : $carDiff['before'];

        if ($carAction === 'create' || !empty($carAuditAfter)) {
            audit_log($conn, array(
                'module_key' => 'open_bill',
                'action_key' => $carAction,
                'entity_type' => 'car',
                'entity_id' => $carId,
                'customer_id' => $customerId,
                'car_id' => $carId,
                'message' => $carAction === 'create'
                    ? 'Vehicle created from Open Bill.'
                    : 'Vehicle updated from Open Bill.',
                'before' => $carAuditBefore,
                'after' => $carAuditAfter,
            ));
        }
    }

    $conn->commit();
    $transactionCommitted = true;

    if ($oldPhotoPathToDelete !== '') {
        delete_car_profile_file($oldPhotoPathToDelete);
    }

    $selectedContext = open_bill_view_selected_context($conn, $customerId, $carId);
    $selectedHtml = $selectedContext ? open_bill_render_selected_context_html($conn, $selectedContext) : '';
    $pageSuccessPath = 'open_bill.php?' . http_build_query(array(
        'customer_id' => $customerId,
        'car_id' => $carId,
        'q' => $plateNumber,
    ));
    $successPath = '../pages/open_bill.php?' . http_build_query(array(
        'customer_id' => $customerId,
        'car_id' => $carId,
        'q' => $plateNumber,
    ));

    if ($expectsJson) {
        open_bill_json_response(200, array(
            'success' => true,
            'message' => open_bill_json_message('บันทึกลูกค้าและรถเรียบร้อยแล้ว', 'Customer and vehicle saved.'),
            'success_url' => $pageSuccessPath,
            'search_query' => $plateNumber !== '' ? $plateNumber : $lookupQuery,
            'customer_id' => $customerId,
            'car_id' => $carId,
            'selected_html' => $selectedHtml,
        ));
    }

    redirect_with_flash(
        $successPath,
        'success',
        localized_flash_message('บันทึกลูกค้าและรถเรียบร้อยแล้ว', 'Customer and vehicle saved.')
    );
} catch (Throwable $exception) {
    if (!$transactionCommitted) {
        $conn->rollback();
    }

    if ($storedPhoto !== null && !empty($storedPhoto['file_path'])) {
        delete_car_profile_file((string) $storedPhoto['file_path']);
    }

    if ($expectsJson) {
        open_bill_json_response(500, array(
            'success' => false,
            'message' => $exception instanceof RuntimeException && trim($exception->getMessage()) !== ''
                ? $exception->getMessage()
                : open_bill_json_message('บันทึกลูกค้าและรถไม่สำเร็จ', 'Customer and vehicle were not saved.'),
            'field_errors' => array(),
        ));
    }

    process_handle_exception_and_redirect(
        $conn,
        $exception,
        'save_open_bill_customer',
        $redirectPath,
        localized_flash_message('บันทึกลูกค้าและรถไม่สำเร็จ', 'Customer and vehicle were not saved.'),
        array(
            'lookup_query' => $lookupQuery,
            'plate_number' => $plateNumber,
            'phone' => $phone,
        ),
        $oldInput,
        true
    );
}
