<?php
declare(strict_types=1);

function quick_service_payment_methods(): array
{
    return array(
        'cash' => localized_text_value('เงินสด', 'Cash'),
        'transfer' => localized_text_value('โอนเงิน', 'Transfer'),
        'qr' => 'QR',
        'card' => localized_text_value('บัตร', 'Card'),
    );
}

function quick_service_payment_method_label(string $paymentMethod): string
{
    $methods = quick_service_payment_methods();

    return $methods[$paymentMethod] ?? ucfirst($paymentMethod);
}

function quick_service_qr_scopes(): array
{
    return array(
        'quick_service' => localized_text_value('ควิกเซอร์วิส', 'Quick Service'),
        'queue_payment' => localized_text_value('รับชำระคิวงาน', 'Queue payment'),
        'booking_deposit_admin' => localized_text_value('มัดจำ @Admin', 'Deposit @Admin'),
        'booking_deposit_branch' => localized_text_value('มัดจำ @Branch', 'Deposit @Branch'),
    );
}

function quick_service_qr_scope_label(string $scopeKey): string
{
    $scopes = quick_service_qr_scopes();

    return $scopes[$scopeKey] ?? $scopeKey;
}

function quick_service_payment_default_config(): array
{
    return array(
        'branch_name' => '',
        'scope_key' => 'quick_service',
        'promptpay_id' => '',
        'merchant_name' => 'CCW Car Care',
        'merchant_city' => 'Bangkok',
        'qr_image_url' => '',
    );
}

function quick_service_payment_storage_path(): string
{
    return dirname(__DIR__) . '/storage/settings/quick_service_payment.json';
}

function quick_service_payment_profile_key(string $branchName = '', string $scopeKey = 'quick_service'): string
{
    $scopeKey = array_key_exists($scopeKey, quick_service_qr_scopes()) ? $scopeKey : 'quick_service';
    $branchName = function_exists('normalize_branch_name')
        ? normalize_branch_name($branchName)
        : trim($branchName);

    return $scopeKey . '|' . $branchName;
}

function quick_service_payment_legacy_config(): array
{
    static $config = null;

    if (is_array($config)) {
        return $config;
    }

    $config = quick_service_payment_default_config();

    $configPath = __DIR__ . '/quick_service_payment.php';
    if (is_file($configPath)) {
        $loadedConfig = require $configPath;

        if (is_array($loadedConfig)) {
            $config = array_merge($config, $loadedConfig);
        }
    }

    $storageConfigPath = quick_service_payment_storage_path();
    if (is_file($storageConfigPath)) {
        $loadedJson = file_get_contents($storageConfigPath);
        $decodedJson = is_string($loadedJson) ? json_decode($loadedJson, true) : null;

        if (
            is_array($decodedJson)
            && !isset($decodedJson['profiles'])
            && (
                array_key_exists('promptpay_id', $decodedJson)
                || array_key_exists('merchant_name', $decodedJson)
                || array_key_exists('merchant_city', $decodedJson)
                || array_key_exists('qr_image_url', $decodedJson)
            )
        ) {
            $config = array_merge($config, $decodedJson);
        }
    }

    foreach ($config as $key => $value) {
        $config[$key] = is_string($value) ? trim($value) : '';
    }

    return $config;
}

function quick_service_payment_profiles(): array
{
    static $profiles = null;

    if (is_array($profiles)) {
        return $profiles;
    }

    $profiles = array();
    $storageConfigPath = quick_service_payment_storage_path();

    if (!is_file($storageConfigPath)) {
        return $profiles;
    }

    $loadedJson = file_get_contents($storageConfigPath);
    $decodedJson = is_string($loadedJson) ? json_decode($loadedJson, true) : null;

    if (!is_array($decodedJson)) {
        return $profiles;
    }

    $defaultConfig = quick_service_payment_default_config();
    $scopeKeys = array_keys(quick_service_qr_scopes());
    $rawProfiles = array();

    if (isset($decodedJson['profiles']) && is_array($decodedJson['profiles'])) {
        $rawProfiles = $decodedJson['profiles'];
    } elseif (
        array_key_exists('promptpay_id', $decodedJson)
        || array_key_exists('merchant_name', $decodedJson)
        || array_key_exists('merchant_city', $decodedJson)
        || array_key_exists('qr_image_url', $decodedJson)
    ) {
        $rawProfiles = array(
            quick_service_payment_profile_key('', 'quick_service') => array_merge(
                $defaultConfig,
                $decodedJson,
                array(
                    'branch_name' => '',
                    'scope_key' => 'quick_service',
                )
            ),
        );
    }

    foreach ($rawProfiles as $profileKey => $profileRow) {
        if (!is_array($profileRow)) {
            continue;
        }

        $scopeKey = trim((string) ($profileRow['scope_key'] ?? 'quick_service'));
        if (!in_array($scopeKey, $scopeKeys, true)) {
            $scopeKey = 'quick_service';
        }

        $branchName = trim((string) ($profileRow['branch_name'] ?? ''));
        if (function_exists('normalize_branch_name')) {
            $branchName = normalize_branch_name($branchName);
        }

        $normalizedProfile = array_merge(
            $defaultConfig,
            $profileRow,
            array(
                'scope_key' => $scopeKey,
                'branch_name' => $branchName,
            )
        );

        foreach ($normalizedProfile as $key => $value) {
            $normalizedProfile[$key] = is_string($value) ? trim($value) : '';
        }

        $profiles[quick_service_payment_profile_key($branchName, $scopeKey)] = $normalizedProfile;
    }

    return $profiles;
}

function quick_service_payment_profile_exact(string $branchName = '', string $scopeKey = 'quick_service'): ?array
{
    $profiles = quick_service_payment_profiles();
    $profileKey = quick_service_payment_profile_key($branchName, $scopeKey);

    return $profiles[$profileKey] ?? null;
}

function quick_service_payment_resolve_config(string $branchName = '', string $scopeKey = 'quick_service'): array
{
    $scopeKey = array_key_exists($scopeKey, quick_service_qr_scopes()) ? $scopeKey : 'quick_service';
    $branchName = function_exists('normalize_branch_name')
        ? normalize_branch_name($branchName)
        : trim($branchName);

    $baseConfig = quick_service_payment_legacy_config();
    $candidates = array(
        array($scopeKey, $branchName),
        array($scopeKey, ''),
    );

    if ($scopeKey !== 'quick_service') {
        $candidates[] = array('quick_service', $branchName);
        $candidates[] = array('quick_service', '');
    }

    foreach ($candidates as $candidate) {
        [$candidateScope, $candidateBranch] = $candidate;
        $profile = quick_service_payment_profile_exact($candidateBranch, $candidateScope);

        if ($profile === null) {
            continue;
        }

        return array_merge(
            $baseConfig,
            $profile,
            array(
                'requested_branch_name' => $branchName,
                'requested_scope_key' => $scopeKey,
                'resolved_branch_name' => $candidateBranch,
                'resolved_scope_key' => $candidateScope,
                'has_specific_profile' => true,
            )
        );
    }

    return array_merge(
        $baseConfig,
        array(
            'branch_name' => '',
            'scope_key' => $scopeKey,
            'requested_branch_name' => $branchName,
            'requested_scope_key' => $scopeKey,
            'resolved_branch_name' => '',
            'resolved_scope_key' => 'quick_service',
            'has_specific_profile' => false,
        )
    );
}

function quick_service_payment_config(): array
{
    return quick_service_payment_resolve_config('', 'quick_service');
}

function quick_service_qr_available(string $branchName = '', string $scopeKey = 'quick_service'): bool
{
    $config = quick_service_payment_resolve_config($branchName, $scopeKey);

    return $config['qr_image_url'] !== '' || $config['promptpay_id'] !== '';
}

function quick_service_tlv(string $id, string $value): string
{
    return $id . sprintf('%02d', strlen($value)) . $value;
}

function quick_service_promptpay_crc16(string $payload): string
{
    $crc = 0xFFFF;
    $length = strlen($payload);

    for ($offset = 0; $offset < $length; $offset++) {
        $crc ^= ord($payload[$offset]) << 8;

        for ($bit = 0; $bit < 8; $bit++) {
            if (($crc & 0x8000) !== 0) {
                $crc = (($crc << 1) ^ 0x1021) & 0xFFFF;
            } else {
                $crc = ($crc << 1) & 0xFFFF;
            }
        }
    }

    return strtoupper(str_pad(dechex($crc), 4, '0', STR_PAD_LEFT));
}

function quick_service_promptpay_target(string $promptpayId): array
{
    $digits = preg_replace('/\D+/', '', trim($promptpayId));
    $digits = is_string($digits) ? $digits : '';

    if ($digits !== '') {
        if (str_starts_with($digits, '0066') && strlen($digits) === 13) {
            return array('field_id' => '01', 'value' => $digits);
        }

        if (str_starts_with($digits, '66') && strlen($digits) === 11) {
            return array('field_id' => '01', 'value' => '00' . $digits);
        }

        if (str_starts_with($digits, '0') && strlen($digits) === 10) {
            return array('field_id' => '01', 'value' => '0066' . substr($digits, 1));
        }

        if (strlen($digits) === 13) {
            return array('field_id' => '02', 'value' => $digits);
        }
    }

    $normalized = trim($promptpayId);

    return array(
        'field_id' => '01',
        'value' => $normalized,
    );
}

function quick_service_promptpay_payload(
    string $promptpayId,
    float $amount = 0.0,
    string $merchantName = 'CCW Car Care',
    string $merchantCity = 'Bangkok'
): string {
    $target = quick_service_promptpay_target($promptpayId);
    $merchantInfo = quick_service_tlv('00', 'A000000677010111')
        . quick_service_tlv($target['field_id'], $target['value']);

    $merchantName = strtoupper((string) preg_replace('/[^A-Z0-9 .&-]/i', '', trim($merchantName)));
    $merchantCity = strtoupper((string) preg_replace('/[^A-Z0-9 .&-]/i', '', trim($merchantCity)));

    $payload = quick_service_tlv('00', '01')
        . quick_service_tlv('01', $amount > 0.0 ? '12' : '11')
        . quick_service_tlv('29', $merchantInfo)
        . quick_service_tlv('53', '764');

    if ($amount > 0.0) {
        $payload .= quick_service_tlv('54', number_format($amount, 2, '.', ''));
    }

    $payload .= quick_service_tlv('58', 'TH');

    if ($merchantName !== '') {
        $payload .= quick_service_tlv('59', substr($merchantName, 0, 25));
    }

    if ($merchantCity !== '') {
        $payload .= quick_service_tlv('60', substr($merchantCity, 0, 15));
    }

    $payloadForCrc = $payload . '6304';

    return $payloadForCrc . quick_service_promptpay_crc16($payloadForCrc);
}

function quick_service_qr_preview(float $amount = 0.0, string $branchName = '', string $scopeKey = 'quick_service'): array
{
    $config = quick_service_payment_resolve_config($branchName, $scopeKey);

    if ($config['qr_image_url'] !== '') {
        return array(
            'type' => 'image',
            'src' => $config['qr_image_url'],
            'promptpay_id' => $config['promptpay_id'],
            'payload' => '',
            'amount' => max(0.0, $amount),
            'branch_name' => $config['resolved_branch_name'] ?? '',
            'scope_key' => $config['resolved_scope_key'] ?? $scopeKey,
        );
    }

    if ($config['promptpay_id'] === '') {
        return array(
            'type' => 'none',
            'src' => '',
            'promptpay_id' => '',
            'payload' => '',
            'amount' => max(0.0, $amount),
            'branch_name' => $config['resolved_branch_name'] ?? '',
            'scope_key' => $config['resolved_scope_key'] ?? $scopeKey,
        );
    }

    $payload = quick_service_promptpay_payload(
        $config['promptpay_id'],
        $amount,
        $config['merchant_name'],
        $config['merchant_city']
    );

    return array(
        'type' => 'promptpay',
        'src' => 'https://api.qrserver.com/v1/create-qr-code/?size=280x280&margin=10&data=' . rawurlencode($payload),
        'promptpay_id' => $config['promptpay_id'],
        'payload' => $payload,
        'amount' => max(0.0, $amount),
        'branch_name' => $config['resolved_branch_name'] ?? '',
        'scope_key' => $config['resolved_scope_key'] ?? $scopeKey,
    );
}

function quick_service_profile_name(string $branchName): string
{
    $branchName = trim($branchName);

    return $branchName !== ''
        ? 'Quick Service ' . $branchName
        : 'Quick Service Walk-in';
}

function quick_service_profile_plate(string $branchName): string
{
    $branchToken = branch_code($branchName);

    if ($branchToken === '') {
        $branchToken = strtoupper((string) preg_replace('/[^A-Z0-9]+/', '', trim($branchName)));
    }

    if ($branchToken === '') {
        $branchToken = 'GEN';
    }

    return substr('QS-' . $branchToken, 0, 30);
}

function ensure_quick_service_customer_car(mysqli $conn, string $branchName): array
{
    ensure_customer_group_column($conn);

    $plateNumber = quick_service_profile_plate($branchName);
    $customerName = quick_service_profile_name($branchName);

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

    if ($existingCar) {
        return array(
            'customer_id' => (int) ($existingCar['customer_id'] ?? 0),
            'car_id' => (int) ($existingCar['car_id'] ?? 0),
            'customer_name' => $customerName,
            'plate_number' => $plateNumber,
        );
    }

    $insertCustomerStmt = db_prepare($conn, "
        INSERT INTO customers (name, phone, normalized_phone, customer_group)
        VALUES (?, '', '', 'guest')
    ");
    $insertCustomerStmt->bind_param('s', $customerName);
    $insertCustomerStmt->execute();
    $customerId = (int) $conn->insert_id;
    $insertCustomerStmt->close();

    $vehicleType = '';
    $brand = '';
    $model = '';
    $color = '';
    $province = '';

    $insertCarStmt = db_prepare($conn, "
        INSERT INTO cars (customer_id, plate_number, province, vehicle_type, brand, model, color)
        VALUES (?, ?, ?, ?, ?, ?, ?)
    ");
    $insertCarStmt->bind_param('issssss', $customerId, $plateNumber, $province, $vehicleType, $brand, $model, $color);
    $insertCarStmt->execute();
    $carId = (int) $conn->insert_id;
    $insertCarStmt->close();

    return array(
        'customer_id' => $customerId,
        'car_id' => $carId,
        'customer_name' => $customerName,
        'plate_number' => $plateNumber,
    );
}
