<?php

declare(strict_types=1);

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

use App\Repositories\SpecialtyFinanceRepository;
use App\Services\SpecialtyFinanceParityService;

$root = dirname(__DIR__);
$format = strtolower((string)($_GET['format'] ?? 'text'));
$browserMode = (string)($_GET['browser'] ?? '0') === '1';
$runLive = (string)($_GET['run_live'] ?? '1') !== '0';
if ($format === 'json' || $browserMode) {
    ini_set('display_errors', '0');
}

$hospital = strtolower(trim((string)($_GET['hospital'] ?? 'njch')));
$hospitals = config('hospitals', []);
if (!is_array($hospitals) || !array_key_exists($hospital, $hospitals)) {
    $hospital = 'njch';
}

$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: text/plain; charset=UTF-8');
    echo "Forbidden. Phase 10.15 QA is local-only unless DDB_QA_TOKEN is configured.\n";
    exit;
}

$currentYear = (int)date('Y');
$year = filter_var($_GET['year'] ?? null, FILTER_VALIDATE_INT);
$year = $year !== false && $year !== null ? (int)$year : $currentYear - 1;
$compareYear = filter_var($_GET['compare_year'] ?? null, FILTER_VALIDATE_INT);
$compareYear = $compareYear !== false && $compareYear !== null ? (int)$compareYear : $year - 1;

$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 : [];
}

$controllerSource = is_file($root . '/app/Controllers/SpecialtyFinanceController.php') ? (string)file_get_contents($root . '/app/Controllers/SpecialtyFinanceController.php') : '';
$currentSource = is_file($root . '/app/Repositories/SpecialtyFinanceRepository.php') ? (string)file_get_contents($root . '/app/Repositories/SpecialtyFinanceRepository.php') : '';
$legacySource = is_file($root . '/app/Repositories/LegacySpecialtyFinanceRepository.php') ? (string)file_get_contents($root . '/app/Repositories/LegacySpecialtyFinanceRepository.php') : '';
$serviceSource = is_file($root . '/app/Services/SpecialtyFinanceParityService.php') ? (string)file_get_contents($root . '/app/Services/SpecialtyFinanceParityService.php') : '';
$viewSource = is_file($root . '/app/Views/specialty_finance/index.php') ? (string)file_get_contents($root . '/app/Views/specialty_finance/index.php') : '';
$layoutSource = is_file($root . '/app/Views/layouts/main.php') ? (string)file_get_contents($root . '/app/Views/layouts/main.php') : '';
$routeSource = is_file($root . '/public/index.php') ? (string)file_get_contents($root . '/public/index.php') : '';
$cssSource = is_file($root . '/public/assets/css/specialty-finance-executive-parity.css') ? (string)file_get_contents($root . '/public/assets/css/specialty-finance-executive-parity.css') : '';
$matrixSource = is_file($root . '/docs/legacy/LEGACY_FUNCTION_MASTER_MATRIX.csv') ? (string)file_get_contents($root . '/docs/legacy/LEGACY_FUNCTION_MASTER_MATRIX.csv') : '';
$contractSource = is_file($root . '/docs/legacy/SPECIALTY_FINANCE_PARITY_CONTRACT.md') ? (string)file_get_contents($root . '/docs/legacy/SPECIALTY_FINANCE_PARITY_CONTRACT.md') : '';

$installedRelease = (string)($version['release'] ?? '');
$add('release_version_compatible', $installedRelease !== '' && version_compare($installedRelease, '10.15.0', '>='), $installedRelease !== '' ? $installedRelease : 'missing');
$add('dedicated_specialty_finance_route', strpos($routeSource, "case 'specialty-finance':") !== false && strpos($routeSource, 'SpecialtyFinanceController') !== false, 'SpecialtyFinanceController route');
$add('revenue_permission_enforced', strpos($controllerSource, 'dashboard_role_revenue') !== false && strpos($controllerSource, 'http_response_code(403)') !== false, 'same finance permission boundary as Revenue');
$add('three_dispatcher_confirmed_functions_mapped', strpos($legacySource, 'mohRevenue(') !== false && strpos($legacySource, 'drugRevenue(') !== false && strpos($legacySource, 'netRevenue(') !== false, 'moh_revn + drug_rev + net_rev');
$add('established_kpi_source_preserved', stripos($legacySource, 'KPI_DOCTOR_PERF_DETAIL_JOB') !== false && stripos($currentSource, 'KPI_DOCTOR_PERF_DETAIL_JOB') !== false, 'KPI_DOCTOR_PERF_DETAIL_JOB');
$add('independent_reconstructed_legacy_path', strpos($legacySource, 'Database::fetchOne') !== false && strpos($legacySource, 'new SpecialtyFinanceRepository') === false && strpos($legacySource, 'SpecialtyFinanceRepository::') === false, 'independent SQL execution path');
$add('three_finance_metrics_supported', strpos($currentSource, "'MOH'") !== false && strpos($currentSource, "'DRUG_REV'") !== false && strpos($currentSource, "'NET_REV_AFTER_DRUG_MOH'") !== false, 'MOH + drug + net');
$add('six_runtime_parity_checks', substr_count($serviceSource, 'compareScalar(') >= 3 && strpos($serviceSource, "'functions_checked' => count(\$all)") !== false && strpos($serviceSource, 'count($all) === 6') !== false, '3 functions x 2 years');
$add('zero_difference_contract', strpos($serviceSource, "'max_difference'") !== false && strpos($serviceSource, '$difference === 0.0') !== false, 'strict zero numeric difference');
$add('source_evidence_boundary_explicit', strpos($serviceSource, 'source_evidence_boundary') !== false && strpos($contractSource, 'does not claim source-code identity') !== false, 'missing historical bodies are not hidden');
$add('source_blocked_functions_not_falsely_closed', strpos($matrixSource, 'special_prof,get_special_prof') !== false && strpos($matrixSource, 'special_net_rev,get_net_rev') !== false && substr_count($matrixSource, 'BLOCKED_SOURCE_MISSING') >= 2, 'special_prof + special_net_rev remain blocked');
$add('executive_ui_standard', strpos($cssSource, '--sf1015-body:16px') !== false && strpos($cssSource, '--sf1015-body-ar:17px') !== false && strpos($cssSource, '--sf1015-section:clamp(24px,2vw,28px)') !== false, '16px EN / 17px AR / 24-28px sections');
$add('executive_no_raw_technical_error', strpos($viewSource, '<pre>') === false && strpos($viewSource, 'Oracle Error') === false && strpos($viewSource, 'SQL Exception') === false, 'friendly executive states only');
$add('three_chart_render_contract', strpos($viewSource, '__DDB_SPECIALTY_FINANCE_CHART_GATE__') !== false && strpos($viewSource, 'expected: 3') !== false && strpos($viewSource, "['moh','drug','net']") !== false && strpos($layoutSource, 'specialty-finance-executive-parity.css') !== false, 'MOH + drug + net specialty charts');
$add('legacy_matrix_updated', strpos($matrixSource, 'moh_revn,get_moh_revn') !== false && strpos($matrixSource, 'drug_rev,get_drug_rev') !== false && strpos($matrixSource, 'net_rev,get_net_rev') !== false && substr_count($matrixSource, 'IMPLEMENTED_PENDING_LIVE_GATE') >= 3, 'three functions pending live proof');

$writeText = strtolower($currentSource . "\n" . $legacySource . "\n" . $serviceSource);
$hasWrite = preg_match('/\b(insert\s+into|update\s+[a-z0-9_]+\s+set|delete\s+from|create\s+table|alter\s+table|merge\s+into)\b/i', $writeText) === 1;
$add('oracle_write_operations_none', !$hasWrite, 'SELECT only');

$parity = null;
$liveError = '';
$chartPayloads = [];
if ($runLive) {
    try {
        $parity = (new SpecialtyFinanceParityService($hospital))->run($year, $compareYear);
        $currentFunctions = $parity['modes']['current_year']['functions'] ?? [];
        $compareFunctions = $parity['modes']['compare_year']['functions'] ?? [];
        $currentFailures = count(array_filter($currentFunctions, static function (array $row): bool { return ($row['status'] ?? '') !== 'PASS'; }));
        $compareFailures = count(array_filter($compareFunctions, static function (array $row): bool { return ($row['status'] ?? '') !== 'PASS'; }));
        $add('live_current_year_parity', count($currentFunctions) === 3 && $currentFailures === 0, count($currentFunctions) . '/3; failures=' . $currentFailures);
        $add('live_compare_year_parity', count($compareFunctions) === 3 && $compareFailures === 0, count($compareFunctions) . '/3; failures=' . $compareFailures);
        $add('live_parity_six_of_six', (int)($parity['functions_checked'] ?? 0) === 6 && (int)($parity['failures'] ?? 1) === 0, (string)($parity['functions_checked'] ?? 0) . '/6; failures=' . (string)($parity['failures'] ?? 'missing'));
        $add('live_parity_max_difference_zero', (float)($parity['max_difference'] ?? -1) === 0.0, (string)($parity['max_difference'] ?? 'missing'));
        $add('live_parity_write_operations_none', ($parity['write_operations'] ?? '') === 'NONE', (string)($parity['write_operations'] ?? 'unknown'));

        $repo = new SpecialtyFinanceRepository($hospital);
        $availableMetricRows = $repo->availableMetrics();
        $availableMetricKeys = array_map(static function (array $row): string {
            return strtoupper((string)($row['key'] ?? ''));
        }, $availableMetricRows);
        $requiredMetricKeys = ['MOH', 'DRUG_REV', 'NET_REV_AFTER_DRUG_MOH'];
        $missingMetricKeys = array_values(array_diff($requiredMetricKeys, $availableMetricKeys));
        $add(
            'live_required_metric_columns_available',
            count($missingMetricKeys) === 0,
            count($missingMetricKeys) === 0 ? 'MOH + DRUG_REV + NET_REV_AFTER_DRUG_MOH' : 'Missing: ' . implode(', ', $missingMetricKeys)
        );

        $makePayload = static function (string $title, array $rows, string $label): array {
            return [
                'title' => $title,
                'labels' => array_map(static function (array $row): string { return (string)($row['label'] ?? ''); }, $rows),
                'series' => [[
                    'label' => $label,
                    'values' => array_map(static function (array $row): float { return (float)($row['value'] ?? 0); }, $rows),
                ]],
            ];
        };
        $chartPayloads = [
            'moh' => $makePayload('MOH contribution by specialty', $repo->specialtyRanking($year, 'MOH', 10), 'MOH revenue'),
            'drug' => $makePayload('Drug revenue by specialty', $repo->specialtyRanking($year, 'DRUG_REV', 10), 'Drug revenue'),
            'net' => $makePayload('Net revenue by specialty', $repo->specialtyRanking($year, 'NET_REV_AFTER_DRUG_MOH', 10), 'Net revenue'),
        ];
        $add('live_three_chart_payloads_available', count($chartPayloads) === 3, count($chartPayloads) . ' / 3');
    } catch (Throwable $e) {
        $liveError = $e->getMessage();
        $add('live_current_year_parity', false, 'Execution error');
        $add('live_compare_year_parity', false, 'Execution error');
        $add('live_parity_six_of_six', false, '0 / 6');
        $add('live_parity_max_difference_zero', false, 'Execution error');
        $add('live_parity_write_operations_none', true, 'NONE');
        $add('live_required_metric_columns_available', false, 'Execution error');
        $add('live_three_chart_payloads_available', false, '0 / 3');
    }
}

if ($browserMode) {
    header('Content-Type: text/html; charset=UTF-8');
    $safePayloads = json_encode($chartPayloads, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
    if (!is_string($safePayloads)) { $safePayloads = '{}'; }
    ?>
<!doctype html>
<html lang="en" data-browser-expected="3" data-browser-rendered="0" data-browser-empty="0" data-browser-failed="0" data-browser-gate="PENDING">
<head>
    <meta charset="utf-8">
    <title>Phase 10.15 Specialty Finance Browser Gate</title>
    <script src="assets/js/charts.js?v=phase10-15-specialty-finance-recovery"></script>
</head>
<body>
<canvas id="sf_browser_moh" width="900" height="320"></canvas>
<canvas id="sf_browser_drug" width="900" height="320"></canvas>
<canvas id="sf_browser_net" width="900" height="320"></canvas>
<script>
(function () {
    var payloads = <?= $safePayloads ?>;
    var gate = { expected: 3, rendered: 0, empty: 0, failed: 0, status: 'PENDING' };
    ['moh','drug','net'].forEach(function (key) {
        try {
            var payload = payloads[key] || {};
            var values = [];
            (payload.series || []).forEach(function (series) { (series.values || []).forEach(function (value) { values.push(Number(value || 0)); }); });
            if (!values.some(function (value) { return value !== 0; })) { gate.empty += 1; return; }
            var result = window.renderBarCompareChart('sf_browser_' + key, payload);
            if (result && result.rendered) { gate.rendered += 1; } else { gate.failed += 1; }
        } catch (error) { gate.failed += 1; }
    });
    gate.status = gate.failed === 0 && (gate.rendered + gate.empty) === gate.expected ? 'PASS' : 'FAIL';
    window.__DDB_SPECIALTY_FINANCE_BROWSER_GATE__ = gate;
    document.documentElement.setAttribute('data-browser-rendered', String(gate.rendered));
    document.documentElement.setAttribute('data-browser-empty', String(gate.empty));
    document.documentElement.setAttribute('data-browser-failed', String(gate.failed));
    document.documentElement.setAttribute('data-browser-gate', gate.status);
    document.body.setAttribute('data-gate-complete', 'true');
})();
</script>
</body>
</html>
    <?php
    exit;
}

$failures = count(array_filter($checks, static function (array $row): bool { return ($row['status'] ?? '') === 'FAIL'; }));
$result = [
    'schema_version' => '1.0',
    'phase' => '10.15',
    'target_release' => '10.15.0',
    'status' => $failures === 0 ? 'PASS' : 'FAIL',
    'generated_at' => gmdate('c'),
    'hospital' => strtoupper($hospital),
    'year' => $year,
    'compare_year' => $compareYear,
    'run_live' => $runLive,
    'checks' => $checks,
    'pass_gates' => count($checks) - $failures,
    'fail_gates' => $failures,
    'functions_checked' => is_array($parity) ? (int)($parity['functions_checked'] ?? 0) : 0,
    'max_difference' => is_array($parity) ? (float)($parity['max_difference'] ?? 0) : 0,
    'write_operations' => 'NONE',
    'parity' => $parity,
    'chart_payload_count' => count($chartPayloads),
    'source_evidence_boundary' => 'Historical function bodies are missing; parity is between independent reconstructed SQL paths on the established KPI source.',
    'live_error' => $liveError !== '' ? 'Execution error recorded; see server log.' : '',
];

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

header('Content-Type: text/plain; charset=UTF-8');
echo "Phase 10.15 — Specialty Finance Recovery QA\n";
echo 'Result: ' . $result['status'] . "\n";
echo 'Functions checked: ' . $result['functions_checked'] . "\n";
echo 'Max difference: ' . $result['max_difference'] . "\n";
echo "Write operations: NONE\n\n";
foreach ($checks as $check) {
    echo '[' . $check['status'] . '] ' . $check['name'] . ' | ' . $check['detail'] . "\n";
}
