<?php

declare(strict_types=1);

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

use App\Services\BranchReadinessPolicy;
use App\Services\LegacyBatchAReadyScopeParityService;

$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;
}

/*
 * H11.0-P10.3-R2 QA execution budget alignment.
 *
 * Evidence showed the PowerShell gate waits up to 420 seconds while this PHP
 * endpoint was still terminated by the inherited 120-second execution ceiling.
 * Keep the endpoint below the client timeout and do not alter production code.
 */
$qaExecutionBudgetSeconds = 360;
$setTimeLimitApplied = false;

@ini_set('max_execution_time', (string)$qaExecutionBudgetSeconds);

if (function_exists('set_time_limit')) {
    $setTimeLimitApplied = @set_time_limit($qaExecutionBudgetSeconds) !== false;
}

$effectiveMaxExecutionSeconds = (int)ini_get('max_execution_time');

$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/LegacyBatchAReadyScopeParityService.php')
    ? (string)file_get_contents($root . '/app/Services/LegacyBatchAReadyScopeParityService.php')
    : '';
$visitsSource = is_file($root . '/app/Repositories/VisitsRepository.php')
    ? (string)file_get_contents($root . '/app/Repositories/VisitsRepository.php')
    : '';
$legacyPatientSource = is_file($root . '/app/Repositories/LegacyPatientActivityRepository.php')
    ? (string)file_get_contents($root . '/app/Repositories/LegacyPatientActivityRepository.php')
    : '';
$operationsSource = is_file($root . '/app/Repositories/OperationsRepository.php')
    ? (string)file_get_contents($root . '/app/Repositories/OperationsRepository.php')
    : '';
$legacyOperationsSource = is_file($root . '/app/Repositories/LegacyOperationsRepository.php')
    ? (string)file_get_contents($root . '/app/Repositories/LegacyOperationsRepository.php')
    : '';
$controllerSource = is_file($root . '/app/Controllers/OperationsController.php')
    ? (string)file_get_contents($root . '/app/Controllers/OperationsController.php')
    : '';
$contractSource = is_file($root . '/docs/legacy/H11_0_P8_LEGACY_BATCH_A_SOURCE_CONTRACT.md')
    ? (string)file_get_contents($root . '/docs/legacy/H11_0_P8_LEGACY_BATCH_A_SOURCE_CONTRACT.md')
    : '';

$release = (string)($version['release'] ?? '');
$combined = strtolower(
    $serviceSource . "\n"
    . $visitsSource . "\n"
    . $legacyPatientSource . "\n"
    . $operationsSource . "\n"
    . $legacyOperationsSource
);
$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('release_11_0_8_or_later', $release !== '' && version_compare($release, '11.0.8', '>='), $release);
$add(
    'three_function_batch_declared',
    strpos($serviceSource, "private const FUNCTIONS = ['padm', 'perv', 'popr']") !== false,
    'padm + perv + popr'
);
$add(
    'padm_independent_paths_present',
    strpos($legacyPatientSource, 'function monthlyAdmissions') !== false
    && strpos($visitsSource, 'function monthlyAdmissions') !== false,
    'LegacyPatientActivityRepository + VisitsRepository'
);
$add(
    'perv_independent_paths_present',
    strpos($legacyPatientSource, 'function monthlyEmergencyVisits') !== false
    && strpos($visitsSource, 'function monthlyEmergencyVisits') !== false,
    'LegacyPatientActivityRepository + VisitsRepository'
);
$add(
    'popr_independent_paths_present',
    strpos($legacyOperationsSource, 'function monthlyPatientOperations') !== false
    && strpos($operationsSource, 'function monthlyLegacyOperations') !== false,
    'LegacyOperationsRepository + OperationsRepository'
);
$add(
    'historical_source_contracts_documented',
    strpos($contractSource, '`padm`') !== false
    && strpos($contractSource, '`perv`') !== false
    && strpos($contractSource, '`popr`') !== false
    && strpos($contractSource, 'RCP_ENTRYEXIT') !== false
    && strpos($contractSource, 'OUTPTA_EMERGENCY_TYPE') !== false
    && strpos($contractSource, 'OPER_OPERATION_SCHEDULE') !== false,
    'Full historical function bodies recovered'
);
$add(
    'real_page_integration_preserved',
    strpos($controllerSource, 'monthlyAdmissions(') !== false
    && strpos($controllerSource, 'monthlyEmergencyVisits(') !== false
    && strpos($controllerSource, 'monthlyLegacyOperations(') !== false,
    'Visits + Operations real production controller paths'
);
$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-a-p8.css')
    && !is_file($root . '/public/assets/js/legacy-batch-a-p8.js'),
    'No page-specific UI assets'
);
$add('oracle_write_operations_none', !$writeDetected, 'SELECT only');

$executionBudgetAligned = (
    $setTimeLimitApplied
    || $effectiveMaxExecutionSeconds === 0
    || $effectiveMaxExecutionSeconds >= $qaExecutionBudgetSeconds
);

$add(
    'qa_execution_budget_aligned_with_420_second_client_timeout',
    $executionBudgetAligned,
    'configured=' . (string)$qaExecutionBudgetSeconds
    . '; effective=' . (string)$effectiveMaxExecutionSeconds
    . '; set_time_limit=' . ($setTimeLimitApplied ? 'true' : 'false')
);

$parity = null;
$liveError = '';

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

    $add(
        'live_functions_3_of_3',
        (int)($parity['function_count'] ?? 0) === 3,
        (string)($parity['function_count'] ?? 0) . '/3'
    );
    $add(
        'live_modes_2_of_2',
        (int)($parity['modes_checked'] ?? 0) === 2,
        (string)($parity['modes_checked'] ?? 0) . '/2'
    );
    $add(
        'live_dataset_checks_12_of_12',
        (int)($parity['dataset_checks'] ?? 0) === 12
        && (int)($parity['failed_datasets'] ?? 1) === 0,
        'datasets=' . (string)($parity['dataset_checks'] ?? 0)
        . '; failures=' . (string)($parity['failed_datasets'] ?? 0)
    );
    $add(
        'live_value_checks_288_of_288',
        (int)($parity['value_checks'] ?? 0) === 288,
        (string)($parity['value_checks'] ?? 0) . '/288'
    );
    $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(
        'padm_ready_scope_pass',
        ($parity['function_results']['padm']['status'] ?? 'FAIL') === 'PASS'
        && (int)($parity['function_results']['padm']['value_checks'] ?? 0) === 96,
        json_encode($parity['function_results']['padm'] ?? [])
    );
    $add(
        'perv_ready_scope_pass',
        ($parity['function_results']['perv']['status'] ?? 'FAIL') === 'PASS'
        && (int)($parity['function_results']['perv']['value_checks'] ?? 0) === 96,
        json_encode($parity['function_results']['perv'] ?? [])
    );
    $add(
        'popr_ready_scope_pass',
        ($parity['function_results']['popr']['status'] ?? 'FAIL') === 'PASS'
        && (int)($parity['function_results']['popr']['value_checks'] ?? 0) === 96,
        json_encode($parity['function_results']['popr'] ?? [])
    );
    $add(
        'three_partial_deferred_branch_promotions',
        (int)($parity['ready_scope_contracts_proven'] ?? 0) === 3
        && (int)($parity['matched_promotions'] ?? -1) === 0,
        'ready_scope=' . (string)($parity['ready_scope_contracts_proven'] ?? 0)
        . '; matched_promotions=' . (string)($parity['matched_promotions'] ?? -1)
    );
    $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_3_of_3', false, 'Execution error');
    $add('live_modes_2_of_2', false, 'Execution error');
    $add('live_dataset_checks_12_of_12', false, 'Execution error');
    $add('live_value_checks_288_of_288', false, 'Execution error');
    $add('live_identity_mismatches_zero', false, 'Execution error');
    $add('live_max_difference_zero', false, 'Execution error');
    $add('padm_ready_scope_pass', false, 'Execution error');
    $add('perv_ready_scope_pass', false, 'Execution error');
    $add('popr_ready_scope_pass', false, 'Execution error');
    $add('three_partial_deferred_branch_promotions', 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-P8',
    'title' => 'Legacy Batch A — Patient Flow and Operations Ready-Scope Recovery',
    'functions' => ['padm', 'perv', 'popr'],
    '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',
    'qa_execution_budget_seconds' => $qaExecutionBudgetSeconds,
    'effective_max_execution_seconds' => $effectiveMaxExecutionSeconds,
    'set_time_limit_applied' => $setTimeLimitApplied,
    'powershell_http_timeout_seconds' => 420,
    '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
);
