<?php
require_once __DIR__ . '/../classes/MraEisCompliance.php';

$failures = [];
$check = static function ($condition, $message) use (&$failures) {
    if (!$condition) {
        $failures[] = $message;
    }
};

$reflection = new ReflectionClass(MraEisCompliance::class);
$service = $reflection->newInstanceWithoutConstructor();
$vatProperty = $reflection->getProperty('vatPercentage');
$vatProperty->setAccessible(true);
$vatProperty->setValue($service, 16.5);
$settingsProperty = $reflection->getProperty('settings');
$settingsProperty->setAccessible(true);
$settingsProperty->setValue($service, new class {
    public function eisZeroRatedTaxIds() {
        return ['B', 'E', 'VAT_ZERO', 'ZERO', 'ZERO_RATED', 'EXEMPT'];
    }
    public function eisDefaultPaymentMethod() {
        return 'CASH';
    }
});

$invoke = static function ($name, array $arguments) use ($reflection, $service) {
    $method = $reflection->getMethod($name);
    $method->setAccessible(true);
    return $method->invokeArgs($service, $arguments);
};

$check($invoke('vatComponent', [116.5, 'A', []]) === 16.5, 'Standard VAT must be 16.5 on MWK 116.50.');
$check($invoke('vatComponent', [100, 'B', []]) === 0.0, 'Tax group B must be zero rated.');
$check($invoke('vatComponent', [100, 'E', []]) === 0.0, 'Tax group E must be exempt.');
$check($invoke('levyComponent', [105, 'LEVY_5', []]) === 5.0, 'Inclusive 5% levy must be MWK 5.00 on MWK 105.00.');

$payload = $invoke('normalizeSaleSubmissionPayload', [[
    'invoiceHeader' => [
        'isExport' => 'false',
        'isReliefSupply' => 'true',
        'paymentMethod' => 'cash',
    ],
    'invoiceSummary' => [
        'taxBreakDown' => [['rateId' => 'A', 'taxableAmount' => 100.005, 'taxAmount' => 16.505]],
        'levyBreakDown' => [['rateId' => 'LEVY_5', 'taxableAmount' => 100.005, 'taxAmount' => 5.005]],
    ],
    'invoiceLineItems' => [],
]]);
$check($payload['invoiceHeader']['isExport'] === false, 'String false must normalize to boolean false.');
$check($payload['invoiceHeader']['isReliefSupply'] === true, 'String true must normalize to boolean true.');
$check($payload['invoiceSummary']['levyBreakDown'][0]['taxAmount'] === 5.01, 'Levy breakdown must round to two decimals.');

$threshold = MraEisOfflineThreshold::thresholdFromTerminalConfiguration([
    'offlineLimit' => ['maxTransactionAgeInHours' => 2.5],
]);
$check($threshold === 2.5, 'MRA maxTransactionAgeInHours must map to the normalized hours threshold.');
$check(
    MraEisOfflineThreshold::thresholdFromTerminalConfiguration(['offlineLimit' => []]) === null,
    'A missing offline threshold must be invalid.'
);
$beforeExpiry = MraEisOfflineThreshold::calculateWindow(2, '2026-07-15T08:00:00+02:00', '2026-07-15T07:59:59Z');
$atExpiry = MraEisOfflineThreshold::calculateWindow(2, '2026-07-15T08:00:00+02:00', '2026-07-15T08:00:00Z');
$afterExpiry = MraEisOfflineThreshold::calculateWindow(2, '2026-07-15T08:00:00+02:00', '2026-07-15T08:00:01Z');
$check($beforeExpiry['remaining_seconds'] === 1 && !$beforeExpiry['expired'], 'Offline sale must be allowed one second before expiry.');
$check($atExpiry['expired'], 'Offline sale must be blocked exactly at expiry.');
$check($afterExpiry['expired'], 'Offline sale must be blocked after expiry.');
$check(MraEisOfflineThreshold::calculateWindow(0, '2026-07-15T08:00:00Z')['expired'], 'Zero threshold must block offline sales.');
$check(MraEisOfflineThreshold::calculateWindow(null, null)['expired'], 'Missing threshold/start time must block offline sales.');
foreach ([0, 408, 500, 502, 503, 504] as $status) {
    $check(MraEisOfflineThreshold::isConnectivityFailure(['status' => $status]), 'Connectivity status ' . $status . ' must start offline mode.');
}
foreach ([200, 400, 401, 404, 422, 429] as $status) {
    $check(!MraEisOfflineThreshold::isConnectivityFailure(['status' => $status]), 'Business/auth status ' . $status . ' must not start offline mode.');
}

$complianceSource = file_get_contents(__DIR__ . '/../classes/MraEisCompliance.php');
$thresholdSource = file_get_contents(__DIR__ . '/../classes/MraEisOfflineThreshold.php');
$saleSource = file_get_contents(__DIR__ . '/../views/sales/create_sale.php');
$check(strpos($thresholdSource, 'COALESCE(offline_started_at, UTC_TIMESTAMP())') !== false, 'Repeated failures must preserve the original offline start.');
$check(strpos($complianceSource, "ORDER BY created_at, id") !== false, 'Pending synchronization must be chronological.');
$check(strpos($complianceSource, "status = 'processing', lock_token") !== false, 'Synchronization must claim outbox rows atomically.');
$check(substr_count($saleSource, 'assertOfflineSaleAllowed(') >= 2, 'Backend sale transaction must repeat threshold enforcement.');

if ($failures) {
    foreach ($failures as $failure) {
        fwrite(STDERR, 'FAIL: ' . $failure . PHP_EOL);
    }
    exit(1);
}

echo 'PASS: EIS pure compliance regression checks' . PHP_EOL;
