<?php

declare(strict_types=1);

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

use App\Repositories\DoctorsRepository;
use App\Services\DoctorsParityService;

$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.13 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;
$rankingLimit = filter_var($_GET['max_v'] ?? null, FILTER_VALIDATE_INT);
$rankingLimit = $rankingLimit !== false && $rankingLimit !== null ? max(5, min(25, (int)$rankingLimit)) : 10;

$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/DoctorsController.php') ? (string)file_get_contents($root . '/app/Controllers/DoctorsController.php') : '';
$currentSource = is_file($root . '/app/Repositories/DoctorsRepository.php') ? (string)file_get_contents($root . '/app/Repositories/DoctorsRepository.php') : '';
$legacySource = is_file($root . '/app/Repositories/LegacyDoctorsRepository.php') ? (string)file_get_contents($root . '/app/Repositories/LegacyDoctorsRepository.php') : '';
$serviceSource = is_file($root . '/app/Services/DoctorsParityService.php') ? (string)file_get_contents($root . '/app/Services/DoctorsParityService.php') : '';
$viewSource = is_file($root . '/app/Views/doctors/index.php') ? (string)file_get_contents($root . '/app/Views/doctors/index.php') : '';
$layoutSource = is_file($root . '/app/Views/layouts/main.php') ? (string)file_get_contents($root . '/app/Views/layouts/main.php') : '';
$indexSource = is_file($root . '/public/index.php') ? (string)file_get_contents($root . '/public/index.php') : '';
$cssSource = is_file($root . '/public/assets/css/doctors-executive-parity.css') ? (string)file_get_contents($root . '/public/assets/css/doctors-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') : '';

$installedRelease = (string)($version['release'] ?? '');
$add('release_version_compatible', $installedRelease !== '' && version_compare($installedRelease, '10.13.0', '>='), $installedRelease !== '' ? $installedRelease : 'missing');
$add('doctor_route_uses_dedicated_controller', strpos($indexSource, 'DoctorsController') !== false && strpos($indexSource, "case 'doctors':") !== false, 'DoctorsController route');
$add('legacy_three_function_contract_mapped',
    strpos($legacySource, 'totalOutpatientVisits(') !== false
    && strpos($legacySource, 'totalAdmissions(') !== false
    && strpos($legacySource, 'doctorRevenueRanking(') !== false,
    'get_doc_rev + total_op_visits + total_admission');
$add('legacy_source_table_preserved', stripos($legacySource, 'KPI_DOCTOR_PERF_DETAIL_JOB') !== false && stripos($currentSource, 'KPI_DOCTOR_PERF_DETAIL_JOB') !== false, 'KPI_DOCTOR_PERF_DETAIL_JOB');
$add('independent_legacy_execution_path',
    strpos($legacySource, 'Database::fetchAll') !== false
    && strpos($legacySource, 'Database::fetchOne') !== false
    && strpos($legacySource, 'new DoctorsRepository') === false
    && strpos($legacySource, 'DoctorsRepository::') === false,
    'LegacyDoctorsRepository independent SQL path');
$add('current_annual_metric_contract', strpos($currentSource, 'annualMetricTotal(') !== false && strpos($currentSource, 'TOTAL_OP_VISITS') !== false && strpos($currentSource, 'TOTAL_INPAT_VISITS') !== false, 'annual totals');
$add('ranking_identity_and_value_contract', strpos($serviceSource, 'identity_match') !== false && strpos($serviceSource, 'top_n_doctor_ranking') !== false, 'rank identity + value');
$add('six_runtime_parity_checks', strpos($serviceSource, "'functions_checked' => count(\$all)") !== false && substr_count($serviceSource, 'compareScalar(') >= 2 && strpos($serviceSource, 'compareRanking(') !== false, '3 functions x 2 years');
$add('comparison_year_supported', strpos($controllerSource, 'compare_year') !== false && strpos($serviceSource, 'compare_year') !== false, 'current + comparison year');
$add('executive_ui_standard',
    strpos($cssSource, '--doctors1013-body: 16px') !== false
    && strpos($cssSource, '--doctors1013-body-ar: 17px') !== false
    && strpos($cssSource, '--doctors1013-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 returned an error') === false && strpos($viewSource, '$dataError') !== false, 'friendly executive state');
$add('two_chart_render_contract',
    strpos($viewSource, '__DDB_DOCTORS_CHART_GATE__') !== false
    && strpos($viewSource, 'gate.expected === 2') === false
    && strpos($viewSource, "expected: 2") !== false
    && strpos($viewSource, "['doctors', 'specialties']") !== false
    && strpos($layoutSource, 'doctors-executive-parity.css') !== false,
    'doctor ranking + specialty contribution');
$add('legacy_matrix_updated',
    strpos($matrixSource, 'get_doc_rev') !== false
    && strpos($matrixSource, 'IMPLEMENTED_PENDING_LIVE_GATE') !== false
    && strpos($matrixSource, 'total_op_visits') !== false
    && strpos($matrixSource, 'total_admission') !== false,
    'legacy matrix coverage');
$add('phase_10_15_finance_non_claim', strpos($serviceSource, 'moh_revn, drug_rev and net_rev remain reserved for Phase 10.15') !== false, 'finance scope preserved for 10.15');

$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)\b/i', $writeText) === 1;
$add('oracle_write_operations_none', !$hasWrite, 'SELECT only');

$parity = null;
$liveError = '';
$chartPayloads = [];
if ($runLive) {
    try {
        $parity = (new DoctorsParityService($hospital))->run($year, $compareYear, $rankingLimit);
        $currentFunctions = $parity['modes']['current_year']['functions'] ?? [];
        $compareFunctions = $parity['modes']['compare_year']['functions'] ?? [];
        $currentFailures = count(array_filter($currentFunctions, static function (array $r): bool { return ($r['status'] ?? '') !== 'PASS'; }));
        $compareFailures = count(array_filter($compareFunctions, static function (array $r): bool { return ($r['status'] ?? '') !== 'PASS'; }));
        $add('live_current_year_parity', count($currentFunctions) === 3 && $currentFailures === 0, count($currentFunctions) . '/3 functions; failures=' . $currentFailures);
        $add('live_compare_year_parity', count($compareFunctions) === 3 && $compareFailures === 0, count($compareFunctions) . '/3 functions; failures=' . $compareFailures);
        $add('live_parity_total_checks', (int)($parity['functions_checked'] ?? 0) === 6, (string)($parity['functions_checked'] ?? 0) . ' / 6');
        $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 DoctorsRepository($hospital);
        $topDoctors = $repo->topDoctors($year, 'TOT_REV', 10);
        $specialties = $repo->specialties($year, 'TOT_REV', 10);
        $toPayload = static function (string $title, array $rows): array {
            return [
                'title' => $title,
                'labels' => array_map(static function (array $row): string { return (string)($row['label'] ?? ''); }, $rows),
                'series' => [[
                    'label' => 'Total revenue',
                    'values' => array_map(static function (array $row): float { return (float)($row['value'] ?? 0); }, $rows),
                ]],
            ];
        };
        $chartPayloads = [
            'doctors' => $toPayload('Top performing doctors', $topDoctors),
            'specialties' => $toPayload('Contribution by specialty', $specialties),
        ];
        $add('live_two_chart_payloads_available', count($chartPayloads) === 2, count($chartPayloads) . ' / 2');
    } 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_total_checks', false, '0 / 6');
        $add('live_parity_max_difference_zero', false, 'Execution error');
        $add('live_parity_write_operations_none', true, 'NONE');
        $add('live_two_chart_payloads_available', false, '0 / 2');
    }
}

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="2" data-browser-rendered="0" data-browser-empty="0" data-browser-failed="0" data-browser-gate="PENDING">
<head>
    <meta charset="utf-8">
    <title>Phase 10.13 Doctors Browser Gate</title>
    <script src="assets/js/charts.js?v=phase10-13-doctors-legacy-parity"></script>
</head>
<body>
    <canvas id="doctors_browser_doctors" width="900" height="320"></canvas>
    <canvas id="doctors_browser_specialties" width="900" height="320"></canvas>
    <script>
    (function () {
        var payloads = <?= $safePayloads ?>;
        var gate = { expected: 2, rendered: 0, empty: 0, failed: 0, status: 'PENDING' };
        ['doctors', 'specialties'].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)); });
                });
                var hasData = values.some(function (value) { return value !== 0; });
                if (!hasData) {
                    gate.empty += 1;
                    return;
                }
                var result = window.renderBarCompareChart('doctors_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_DOCTORS_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.13',
    'target_release' => '10.13.0',
    'status' => $failures === 0 ? 'PASS' : 'FAIL',
    'generated_at' => gmdate('c'),
    'hospital' => strtoupper($hospital),
    'year' => $year,
    'compare_year' => $compareYear,
    'ranking_limit' => $rankingLimit,
    '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),
    '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.13 — Doctors Legacy Parity QA\n";
echo 'Result: ' . $result['status'] . "\n";
echo 'Hospital: ' . $result['hospital'] . "\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";
}
