<?php

declare(strict_types=1);

require_once dirname(__DIR__) . '/app/bootstrap.php';

use App\Services\BranchReadinessPolicy;
use App\Services\LegacyBatchBReadyScopeParityService;

$root = dirname(__DIR__);
$remote = (string)($_SERVER['REMOTE_ADDR'] ?? '');
$isLocal = in_array($remote, ['127.0.0.1', '::1', 'localhost', ''], true);
$providedToken = (string)($_GET['token'] ?? '');
$expectedToken = trim((string)env('DDB_QA_TOKEN', ''));
$tokenOk = $expectedToken !== '' && hash_equals($expectedToken, $providedToken);

if (!$isLocal && !$tokenOk) {
    http_response_code(403);
    header('Content-Type: application/json; charset=UTF-8');
    echo json_encode(['status' => 'FAIL', 'error' => 'Forbidden']);
    exit;
}

$year = filter_var($_GET['year'] ?? null, FILTER_VALIDATE_INT);
$compareYear = filter_var($_GET['compare_year'] ?? null, FILTER_VALIDATE_INT);
$fromDate = trim((string)($_GET['from_date'] ?? ''));
$toDate = trim((string)($_GET['to_date'] ?? ''));

if ($year === false || $year === null) {
    $year = (int)date('Y') - 1;
}
if ($compareYear === false || $compareYear === null) {
    $compareYear = (int)$year - 1;
}
if ($fromDate === '') {
    $fromDate = (string)$year . '-01-01';
}
if ($toDate === '') {
    $toDate = (string)$year . '-03-31';
}

$checks = [];
$add = static function (string $name, bool $ok, string $detail = '') use (&$checks): void {
    $checks[] = [
        'name' => $name,
        'status' => $ok ? 'PASS' : 'FAIL',
        'detail' => $detail,
    ];
};

$version = [];
if (is_file($root . '/DDB_VERSION.json')) {
    $decoded = json_decode((string)file_get_contents($root . '/DDB_VERSION.json'), true);
    $version = is_array($decoded) ? $decoded : [];
}

$serviceSource = is_file($root . '/app/Services/LegacyBatchBReadyScopeParityService.php')
    ? (string)file_get_contents($root . '/app/Services/LegacyBatchBReadyScopeParityService.php')
    : '';
$currentSource = is_file($root . '/app/Repositories/DiagnosticsRepository.php')
    ? (string)file_get_contents($root . '/app/Repositories/DiagnosticsRepository.php')
    : '';
$legacySource = is_file($root . '/app/Repositories/LegacyDiagnosticsRepository.php')
    ? (string)file_get_contents($root . '/app/Repositories/LegacyDiagnosticsRepository.php')
    : '';
$controllerSource = is_file($root . '/app/Controllers/LabRadiologyController.php')
    ? (string)file_get_contents($root . '/app/Controllers/LabRadiologyController.php')
    : '';
$contractSource = is_file($root . '/docs/legacy/H11_0_P9_LEGACY_BATCH_B_SOURCE_CONTRACT.md')
    ? (string)file_get_contents($root . '/docs/legacy/H11_0_P9_LEGACY_BATCH_B_SOURCE_CONTRACT.md')
    : '';

$release = (string)($version['release'] ?? '');
$combined = strtolower($serviceSource . "\n" . $currentSource . "\n" . $legacySource);
$writeDetected = preg_match(
    '/\b(insert\s+into|update\s+[a-z0-9_]+\s+set|delete\s+from|create\s+table|alter\s+table|drop\s+table|merge\s+into)\b/i',
    $combined
) === 1;

$add('target_release_11_0_9', $release === '11.0.9', $release);
$add(
    'two_function_batch_declared',
    strpos($serviceSource, "private const FUNCTIONS = ['plts', 'prts']") !== false,
    'plts + prts'
);
$add(
    'plts_independent_paths_present',
    strpos($legacySource, 'function monthlyLabTests') !== false
    && strpos($currentSource, 'function monthlyLabTests') !== false
    && strpos($legacySource, 'new DiagnosticsRepository') === false,
    'LegacyDiagnosticsRepository + DiagnosticsRepository'
);
$add(
    'prts_independent_paths_present',
    strpos($legacySource, 'function monthlyRadiologyTests') !== false
    && strpos($currentSource, 'function monthlyRadiologyTests') !== false
    && strpos($legacySource, 'new DiagnosticsRepository') === false,
    'LegacyDiagnosticsRepository + DiagnosticsRepository'
);
$add(
    'historical_plts_contract_preserved',
    stripos($contractSource, 'RCP_LAB_SERVICE_RESERVATION') !== false
    && stripos($contractSource, 'EXPECTEDDONEDATE <= SYSDATE') !== false,
    'get_lab_tests historical contract'
);
$add(
    'historical_prts_contract_preserved',
    stripos($contractSource, 'RCP_RAD_SERVICE_RESERVATION') !== false
    && stripos($contractSource, 'MACHINE_SCH_FROM <= SYSDATE') !== false,
    'get_rad_tests historical contract'
);
$add(
    'real_lab_radiology_page_integration_preserved',
    strpos($controllerSource, 'monthlyLabTests(') !== false
    && strpos($controllerSource, 'monthlyRadiologyTests(') !== false,
    'LabRadiologyController production path'
);
$add(
    'branch_readiness_policy_preserved',
    BranchReadinessPolicy::blockingQaBranches() === ['njch', 'mnh']
    && BranchReadinessPolicy::deferredBranches() === ['jckh'],
    'NJCH + MNH blocking; JCKH deferred'
);
$add(
    'no_new_page_specific_css_or_js',
    !is_file($root . '/public/assets/css/legacy-batch-b-p9.css')
    && !is_file($root . '/public/assets/js/legacy-batch-b-p9.js'),
    'No page-specific UI assets'
);
$add('oracle_write_operations_none', !$writeDetected, 'SELECT only');

$parity = null;
$liveError = '';

try {
    $parity = (new LegacyBatchBReadyScopeParityService())->run(
        (int)$year,
        (int)$compareYear,
        $fromDate,
        $toDate
    );

    $add(
        'live_functions_2_of_2',
        (int)($parity['function_count'] ?? 0) === 2,
        (string)($parity['function_count'] ?? 0) . '/2'
    );
    $add(
        'live_modes_2_of_2',
        (int)($parity['modes_checked'] ?? 0) === 2,
        (string)($parity['modes_checked'] ?? 0) . '/2'
    );
    $add(
        'live_dataset_checks_8_of_8',
        (int)($parity['dataset_checks'] ?? 0) === 8
        && (int)($parity['failed_datasets'] ?? 1) === 0,
        'datasets=' . (string)($parity['dataset_checks'] ?? 0)
        . '; failures=' . (string)($parity['failed_datasets'] ?? 0)
    );
    $add(
        'live_value_checks_192_of_192',
        (int)($parity['value_checks'] ?? 0) === 192,
        (string)($parity['value_checks'] ?? 0) . '/192'
    );
    $add(
        'live_identity_mismatches_zero',
        (int)($parity['identity_mismatches'] ?? 1) === 0,
        (string)($parity['identity_mismatches'] ?? 'missing')
    );
    $add(
        'live_max_difference_zero',
        (float)($parity['max_difference'] ?? -1) === 0.0,
        (string)($parity['max_difference'] ?? 'missing')
    );
    $add(
        'plts_ready_scope_pass',
        ($parity['function_results']['plts']['status'] ?? 'FAIL') === 'PASS'
        && (int)($parity['function_results']['plts']['value_checks'] ?? 0) === 96,
        json_encode($parity['function_results']['plts'] ?? [])
    );
    $add(
        'prts_ready_scope_pass',
        ($parity['function_results']['prts']['status'] ?? 'FAIL') === 'PASS'
        && (int)($parity['function_results']['prts']['value_checks'] ?? 0) === 96,
        json_encode($parity['function_results']['prts'] ?? [])
    );
    $add(
        'two_partial_deferred_branch_proofs',
        (int)($parity['ready_scope_contracts_proven'] ?? 0) === 2
        && (int)($parity['matched_promotions'] ?? -1) === 0,
        'ready_scope=' . (string)($parity['ready_scope_contracts_proven'] ?? 0)
        . '; matched_promotions=' . (string)($parity['matched_promotions'] ?? -1)
    );
    $add(
        'all_six_partial_functions_ready_scope_proven',
        (int)($parity['partial_ready_scope_proven_after_pass']['count'] ?? 0) === 6
        && count((array)($parity['remaining_partial_ready_scope_unproven_after_pass'] ?? [])) === 0,
        'proven=' . (string)($parity['partial_ready_scope_proven_after_pass']['count'] ?? 0)
        . '/6; remaining=' . (string)count((array)($parity['remaining_partial_ready_scope_unproven_after_pass'] ?? []))
    );
    $add(
        'legacy_progress_remains_honest_23_6_2',
        (int)($parity['baseline_after_live_pass']['matched'] ?? 0) === 23
        && (int)($parity['baseline_after_live_pass']['partial'] ?? 0) === 6
        && (int)($parity['baseline_after_live_pass']['missing'] ?? 0) === 2,
        'matched=' . (string)($parity['baseline_after_live_pass']['matched'] ?? 0)
        . '; partial=' . (string)($parity['baseline_after_live_pass']['partial'] ?? 0)
        . '; missing=' . (string)($parity['baseline_after_live_pass']['missing'] ?? 0)
    );
    $add(
        'live_read_only',
        ($parity['write_operations'] ?? '') === 'NONE',
        (string)($parity['write_operations'] ?? 'unknown')
    );
} catch (Throwable $error) {
    $liveError = $error->getMessage();

    $add('live_functions_2_of_2', false, 'Execution error');
    $add('live_modes_2_of_2', false, 'Execution error');
    $add('live_dataset_checks_8_of_8', false, 'Execution error');
    $add('live_value_checks_192_of_192', false, 'Execution error');
    $add('live_identity_mismatches_zero', false, 'Execution error');
    $add('live_max_difference_zero', false, 'Execution error');
    $add('plts_ready_scope_pass', false, 'Execution error');
    $add('prts_ready_scope_pass', false, 'Execution error');
    $add('two_partial_deferred_branch_proofs', false, 'Execution error');
    $add('all_six_partial_functions_ready_scope_proven', false, 'Execution error');
    $add('legacy_progress_remains_honest_23_6_2', true, 'No false MATCHED promotion');
    $add('live_read_only', true, 'NONE');
}

$failures = count(array_filter(
    $checks,
    static function (array $check): bool {
        return $check['status'] === 'FAIL';
    }
));

$result = [
    'schema_version' => '1.0',
    'phase' => 'H11.0-P9',
    'title' => 'Legacy Batch B — Lab & Radiology Ready-Scope Recovery',
    'functions' => ['plts', 'prts'],
    'year' => (int)$year,
    'compare_year' => (int)$compareYear,
    'from_date' => $fromDate,
    'to_date' => $toDate,
    'source_evidence_boundary' => 'FULL_HISTORICAL_FUNCTION_BODIES_RECOVERED',
    'branch_access_policy' => 'READY_BRANCHES_ONLY_JCKH_DEFERRED',
    'write_operations' => 'NONE',
    'checks' => $checks,
    'parity' => $parity,
    'live_error' => $liveError,
    'pass_gates' => count($checks) - $failures,
    'fail_gates' => $failures,
    'status' => $failures === 0 ? 'PASS' : 'FAIL',
];

header('Content-Type: application/json; charset=UTF-8');
echo json_encode(
    $result,
    JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
);
