<?php

declare(strict_types=1);

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

use App\Repositories\OperationsRepository;
use App\Services\ChartDataService;
use App\Services\OperationsParityService;

$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.11 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;
$fromDate = (string)($_GET['from_date'] ?? sprintf('%04d-01-01', $year));
$toDate = (string)($_GET['to_date'] ?? sprintf('%04d-03-31', $year));

$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/OperationsController.php') ? (string)file_get_contents($root . '/app/Controllers/OperationsController.php') : '';
$currentSource = is_file($root . '/app/Repositories/OperationsRepository.php') ? (string)file_get_contents($root . '/app/Repositories/OperationsRepository.php') : '';
$legacySource = is_file($root . '/app/Repositories/LegacyOperationsRepository.php') ? (string)file_get_contents($root . '/app/Repositories/LegacyOperationsRepository.php') : '';
$serviceSource = is_file($root . '/app/Services/OperationsParityService.php') ? (string)file_get_contents($root . '/app/Services/OperationsParityService.php') : '';
$viewSource = is_file($root . '/app/Views/operations/module.php') ? (string)file_get_contents($root . '/app/Views/operations/module.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/operations-executive-parity.css') ? (string)file_get_contents($root . '/public/assets/css/operations-executive-parity.css') : '';

$installedRelease = (string)($version['release'] ?? '');
$releaseCompatible = $installedRelease !== '' && version_compare($installedRelease, '10.11.0', '>=');
$add('release_version_compatible', $releaseCompatible, $installedRelease !== '' ? $installedRelease : 'missing');
$add('legacy_selected_branch_contract_mapped',
    strpos($legacySource, 'monthlyPatientOperations(') !== false
    && strpos($legacySource, "r.servstatus <> 'C'") !== false
    && strpos($legacySource, 'oper_operation_schedule') !== false,
    'popr_s selected-branch contract');
$add('independent_legacy_execution_path',
    strpos($legacySource, 'Database::fetchAll') !== false
    && strpos($legacySource, 'new OperationsRepository') === false
    && strpos($legacySource, 'OperationsRepository::') === false,
    'LegacyOperationsRepository');
$add('current_legacy_rule_preserved',
    strpos($currentSource, "return \"r.servstatus <> 'C'\"") !== false
    && strpos($currentSource, 'monthlyLegacyOperations(') !== false,
    "SERVSTATUS <> 'C'");
$add('year_and_range_modes_supported',
    strpos($viewSource, 'value="year"') !== false
    && strpos($viewSource, 'value="range"') !== false
    && strpos($controllerSource, "['visits', 'operations']") !== false,
    'year + custom date range');
$add('same_year_range_guard', strpos($controllerSource, "\$from->format('Y') !== \$to->format('Y')") !== false, 'same-year current range');
$add('compare_year_supported', strpos($controllerSource, 'compare_year') !== false && strpos($currentSource, 'compareYear') !== false, 'compare_year');
$add('branch_context_preserved', strpos($controllerSource, 'Auth::hospital()') !== false, 'active hospital context');
$add('operations_route_is_live',
    strpos($indexSource, "case 'operations':") !== false
    && preg_match("/\['page'\s*=>\s*'operations'[^\]]*'live'\s*=>\s*true/", $layoutSource) === 1,
    'route + navigation');
$add('executive_ui_standard',
    strpos($cssSource, '--operations1011-body: 16px') !== false
    && strpos($cssSource, '--operations1011-body-ar: 17px') !== false
    && strpos($cssSource, '--operations1011-section: clamp(24px, 2vw, 28px)') !== false,
    '16px EN / 17px AR / 24-28px sections');
$add('executive_period_strip', strpos($viewSource, 'operations1011-period-strip') !== false, 'mode + current + comparison + branch');
$operationsViewStart = strpos($viewSource, '<?php elseif ($isOperations): ?>');
$operationsViewEnd = strpos($viewSource, '<?php elseif ($isDoctors): ?>', $operationsViewStart !== false ? $operationsViewStart : 0);
$operationsViewScope = ($operationsViewStart !== false && $operationsViewEnd !== false) ? substr($viewSource, $operationsViewStart, $operationsViewEnd - $operationsViewStart) : '';
$add('executive_no_raw_technical_error',
    $operationsViewScope !== ''
    && strpos($operationsViewScope, '<pre>') === false
    && strpos($operationsViewScope, 'Oracle returned an error') === false
    && strpos($operationsViewScope, '$dataError') !== false,
    'friendly executive state, no raw exception output');
$add('three_chart_render_contract',
    strpos($viewSource, '__DDB_OPERATIONS_CHART_GATE__') !== false
    && strpos($viewSource, "gate.expected === 3") !== false
    && strpos($layoutSource, 'operations-executive-parity.css') !== false,
    'scheduled + performed + cancelled');
$add('executive_breakdowns_present',
    strpos($viewSource, "topSpecialties") !== false
    && strpos($viewSource, "topDoctors") !== false
    && strpos($viewSource, "topRooms") !== false,
    'specialty + doctor + OR capability');
$add('parity_service_two_checks',
    substr_count($serviceSource, "'popr_s'") >= 2
    && strpos($serviceSource, "'functions_checked' => 2") !== false,
    'popr_s x 2 modes');
$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 OperationsParityService($hospital))->run($year, $compareYear, $fromDate, $toDate);
        $yearFunctions = $parity['modes']['year']['functions'] ?? [];
        $rangeFunctions = $parity['modes']['date_range']['functions'] ?? [];
        $yearFailures = count(array_filter($yearFunctions, static function (array $r): bool { return ($r['status'] ?? '') !== 'PASS'; }));
        $rangeFailures = count(array_filter($rangeFunctions, static function (array $r): bool { return ($r['status'] ?? '') !== 'PASS'; }));
        $add('live_year_mode_parity', count($yearFunctions) === 1 && $yearFailures === 0, count($yearFunctions) . '/1 function; failures=' . $yearFailures);
        $add('live_date_range_parity', count($rangeFunctions) === 1 && $rangeFailures === 0, count($rangeFunctions) . '/1 function; failures=' . $rangeFailures);
        $add('live_parity_total_checks', (int)($parity['functions_checked'] ?? 0) === 2, (string)($parity['functions_checked'] ?? 0) . ' / 2');
        $add('live_parity_write_operations_none', ($parity['write_operations'] ?? '') === 'NONE', (string)($parity['write_operations'] ?? 'unknown'));

        $repo = new OperationsRepository($hospital);
        $chartService = new ChartDataService();
        $chartPayloads = [
            'scheduled' => $chartService->comparePayload($repo->monthlyLegacyOperations($year, $compareYear), 'Scheduled operations', (string)$year, (string)$compareYear),
            'performed' => $chartService->comparePayload($repo->monthlyPerformedOperations($year, $compareYear), 'Performed operations', (string)$year, (string)$compareYear),
            'cancelled' => $chartService->comparePayload($repo->monthlyCancelledOperations($year, $compareYear), 'Cancelled operations', (string)$year, (string)$compareYear),
        ];
        $add('live_three_chart_payloads_available', count($chartPayloads) === 3, count($chartPayloads) . ' / 3');
    } catch (Throwable $e) {
        $liveError = $e->getMessage();
        $add('live_year_mode_parity', false, 'Execution error');
        $add('live_date_range_parity', false, 'Execution error');
        $add('live_parity_total_checks', false, '0 / 2');
        $add('live_parity_write_operations_none', true, 'NONE');
        $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);
    ?>
<!doctype html>
<html lang="en" data-browser-gate="PENDING" data-browser-expected="3" data-browser-rendered="0" data-browser-failed="0">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Phase 10.11 Operations Browser Gate</title>
<style>body{font-family:Segoe UI,Tahoma,Arial;background:#f8fafc;margin:0;padding:20px}.grid{display:grid;gap:18px}.card{background:#fff;border:1px solid #e2e8f0;border-radius:18px;padding:16px}canvas{width:100%;min-height:300px}</style>
<script src="assets/js/charts.js?v=phase10-11-operations-recovery" defer></script>
</head>
<body>
<div class="grid">
<?php foreach ($chartPayloads as $key => $payload): ?>
    <div class="card"><canvas id="operations_qa_chart_<?= e($key) ?>" height="132" data-operations-qa-chart="<?= e($key) ?>" data-chart-rendered="false"></canvas></div>
<?php endforeach; ?>
</div>
<script id="operations_qa_payloads" type="application/json"><?= $safePayloads ?: '{}' ?></script>
<script>
window.addEventListener('DOMContentLoaded', function () {
    var gate = { expected: 3, rendered: 0, failed: 0 };
    try {
        var payloads = JSON.parse(document.getElementById('operations_qa_payloads').textContent || '{}');
        ['scheduled', 'performed', 'cancelled'].forEach(function (key) {
            try {
                var result = window.renderBarCompareChart('operations_qa_chart_' + key, payloads[key] || {});
                if (result && result.rendered) gate.rendered += 1; else gate.failed += 1;
            } catch (e) { gate.failed += 1; }
        });
    } catch (e) { gate.failed = 3; }
    var ok = gate.expected === 3 && gate.rendered === 3 && gate.failed === 0;
    document.documentElement.setAttribute('data-browser-expected', String(gate.expected));
    document.documentElement.setAttribute('data-browser-rendered', String(gate.rendered));
    document.documentElement.setAttribute('data-browser-failed', String(gate.failed));
    document.documentElement.setAttribute('data-browser-gate', ok ? 'PASS' : 'FAIL');
});
</script>
</body>
</html>
<?php
    exit;
}

$failures = count(array_filter($checks, static function (array $c): bool { return $c['status'] === 'FAIL'; }));
$result = [
    'schema_version' => '1.0',
    'phase' => '10.11',
    'title' => 'Operations Dashboard Recovery',
    'hospital' => strtoupper($hospital),
    'year' => $year,
    'compare_year' => $compareYear,
    'range_from' => $fromDate,
    'range_to' => $toDate,
    'run_live' => $runLive,
    'write_operations' => 'NONE',
    'checks' => $checks,
    'parity' => $parity,
    'live_error' => $liveError,
    'pass_gates' => count($checks) - $failures,
    'fail_gates' => $failures,
    'status' => $failures === 0 ? 'PASS' : 'FAIL',
];

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 "Operations Dashboard Recovery QA\n";
echo "Phase: 10.11 - Operations Dashboard Recovery\n";
echo 'Hospital: ' . strtoupper($hospital) . "\n";
echo "Executive standard: Executive Leadership UI Standard v1.0\n";
echo "Write operations: NONE\n\n";
echo "QA Gates:\n";
foreach ($checks as $check) {
    echo '[' . $check['status'] . '] ' . str_pad($check['name'], 52) . ' | ' . $check['detail'] . "\n";
}
if (is_array($parity)) {
    echo "\nParity Summary:\n";
    foreach (['year' => 'YEAR', 'date_range' => 'DATE RANGE'] as $modeKey => $modeLabel) {
        foreach (($parity['modes'][$modeKey]['functions'] ?? []) as $fn) {
            echo '[' . ($fn['status'] ?? 'FAIL') . '] ' . str_pad($modeLabel . ' / ' . (string)($fn['legacy_function'] ?? ''), 38)
                . ' | current diff=' . number_format((float)($fn['current_total_difference'] ?? 0), 0, '.', '')
                . ' | compare diff=' . number_format((float)($fn['compare_total_difference'] ?? 0), 0, '.', '')
                . "\n";
        }
    }
}
if ($liveError !== '') {
    echo "\nLive execution error: " . $liveError . "\n";
}
echo "\nQA result: " . $result['status'] . "\n";
echo 'PASS gates: ' . $result['pass_gates'] . "\n";
echo 'FAIL gates: ' . $result['fail_gates'] . "\n";
echo "QA is read-only. No Oracle, review, governance, or audit row is modified.\n";
