<?php

declare(strict_types=1);

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

use App\Repositories\BedsRepository;
use App\Services\BedsParityService;

$format = strtolower((string)($_GET['format'] ?? 'text'));
$runLive = (string)($_GET['run_live'] ?? '0') === '1';
$browserMode = (string)($_GET['browser'] ?? '0') === '1';
$hospital = strtolower(trim((string)($_GET['hospital'] ?? 'njch')));
$year = max(2014, (int)($_GET['year'] ?? ((int)date('Y') - 1)));
$fromDate = trim((string)($_GET['from_date'] ?? sprintf('%04d-01-01', $year)));
$toDate = trim((string)($_GET['to_date'] ?? sprintf('%04d-03-31', $year)));

if ($format === 'json') {
    ini_set('display_errors', '0');
}

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

$root = dirname(__DIR__);
$read = static function (string $relative) use ($root): string {
    $path = $root . '/' . ltrim($relative, '/');
    return is_file($path) ? (string)file_get_contents($path) : '';
};

$version = json_decode($read('DDB_VERSION.json'), true) ?: [];
$currentSource = $read('app/Repositories/BedsRepository.php');
$legacySource = $read('app/Repositories/LegacyBedsRepository.php');
$serviceSource = $read('app/Services/BedsParityService.php');
$controllerSource = $read('app/Controllers/BedsController.php');
$viewSource = $read('app/Views/beds/index.php');
$cssSource = $read('public/assets/css/beds-executive-parity.css');
$layoutSource = $read('app/Views/layouts/main.php');
$routeSource = $read('public/index.php');
$matrixSource = $read('docs/legacy/LEGACY_FUNCTION_MASTER_MATRIX.csv');

$release = (string)($version['release'] ?? '0.0.0');
$releaseOk = version_compare($release, '10.14.0', '>=');
$add('release_version_compatible', $releaseOk, $release);
$add('three_dispatcher_legacy_functions',
    strpos($legacySource, 'currentOccupancyRows') !== false
    && strpos($legacySource, 'unitEfficiencyRows') !== false
    && strpos($legacySource, 'bedEfficiencyRows') !== false,
    'bcor + get_units_effic + get_units_effic_b');
$add('independent_legacy_execution_path',
    strpos($legacySource, 'Database::fetchAll') !== false
    && strpos($legacySource, 'new BedsRepository') === false,
    'LegacyBedsRepository executes independent SQL');
$add('current_legacy_compatible_contracts',
    strpos($currentSource, 'legacyCompatibleCurrentOccupancyRows') !== false
    && strpos($currentSource, 'legacyCompatibleUnitEfficiencyRows') !== false
    && strpos($currentSource, 'legacyCompatibleBedEfficiencyRows') !== false,
    'current implementation exposes exact compatibility methods');
$add('five_runtime_parity_checks',
    strpos($serviceSource, '$checks = [$snapshot, $yearUnits, $rangeUnits, $yearBeds, $rangeBeds]') !== false
    && strpos($serviceSource, "'functions_checked' => count(\$checks)") !== false,
    'snapshot + 2 unit modes + 2 bed modes');
$add('snapshot_exclusions_preserved',
    strpos($legacySource, '7301') !== false
    && strpos($legacySource, '3112') !== false
    && strpos($legacySource, '215') !== false
    && strpos($legacySource, 'BABY_NORMAL_BED') !== false,
    'legacy current occupancy exclusions');
$add('legacy_period_math_preserved',
    strpos($legacySource, "TO_DATE(:period_end, 'YYYY-MM-DD') - TO_DATE(:period_start, 'YYYY-MM-DD')") !== false
    && strpos($currentSource, 'legacyPeriodContract') !== false,
    'legacy period-hours contract');
$add('ranking_identity_and_numeric_contract',
    strpos($serviceSource, 'identity_mismatches') !== false
    && strpos($serviceSource, 'max_difference') !== false
    && strpos($serviceSource, 'bed_ranking') !== false,
    'row identity/order + numeric difference');
$add('dedicated_beds_route',
    strpos($routeSource, "case 'beds':") !== false
    && strpos($routeSource, 'new BedsController') !== false,
    'BedsController dedicated route');
$add('executive_ui_standard',
    strpos($cssSource, '--beds1014-body:16px') !== false
    && strpos($cssSource, '--beds1014-body-ar:17px') !== false
    && strpos($cssSource, '--beds1014-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('two_chart_render_contract',
    strpos($viewSource, '__DDB_BEDS_CHART_GATE__') !== false
    && strpos($viewSource, "expected: 2") !== false
    && strpos($viewSource, "['units','beds']") !== false
    && strpos($layoutSource, 'beds-executive-parity.css') !== false,
    'unit efficiency + selected unit beds');
$add('legacy_matrix_updated',
    strpos($matrixSource, 'bcor,get_beds_current_occupancy_rate') !== false
    && strpos($matrixSource, 'get_units_effic,get_units_effic') !== false
    && strpos($matrixSource, 'get_units_effic_b,get_units_effic_b') !== false
    && substr_count($matrixSource, 'IMPLEMENTED_PENDING_LIVE_GATE') >= 3,
    '3 legacy 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 BedsParityService($hospital))->run($year, $fromDate, $toDate);
        $rows = $parity['checks'] ?? [];
        $failures = count(array_filter($rows, static function (array $row): bool { return ($row['status'] ?? '') !== 'PASS'; }));
        $add('live_parity_five_of_five', count($rows) === 5 && $failures === 0, count($rows) . '/5; failures=' . $failures);
        $add('live_parity_identity_mismatch_zero', (int)($parity['identity_mismatches'] ?? -1) === 0, (string)($parity['identity_mismatches'] ?? '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 BedsRepository($hospital);
        $units = $repo->legacyCompatibleUnitEfficiencyRows($year, null, null, 0);
        $unitId = (int)($parity['selected_unit_id'] ?? 0);
        $beds = $repo->legacyCompatibleBedEfficiencyRows($year, $unitId, null, null);
        $toPayload = static function (string $title, array $rows, string $labelKey): array {
            return [
                'title' => $title,
                'labels' => array_map(static function (array $row) use ($labelKey): string { return (string)($row[$labelKey] ?? ''); }, $rows),
                'series' => [[
                    'label' => 'Occupancy %',
                    'values' => array_map(static function (array $row): float { return (float)($row['bed_efficiency_percentage'] ?? 0); }, $rows),
                ]],
            ];
        };
        $chartPayloads = [
            'units' => $toPayload('Unit efficiency', $units, 'bed_floor'),
            'beds' => $toPayload('Bed efficiency', $beds, 'bed_name'),
        ];
        $add('live_two_chart_payloads_available', count($chartPayloads) === 2, count($chartPayloads) . ' / 2');
    } catch (Throwable $e) {
        $liveError = $e->getMessage();
        $add('live_parity_five_of_five', false, 'Execution error');
        $add('live_parity_identity_mismatch_zero', false, 'Execution error');
        $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.14 Beds Browser Gate</title>
    <script src="assets/js/charts.js?v=phase10-14-beds-units-legacy-parity"></script>
</head>
<body>
<canvas id="beds_browser_units" width="900" height="320"></canvas>
<canvas id="beds_browser_beds" width="900" height="320"></canvas>
<script>
(function () {
    var payloads = <?= $safePayloads ?>;
    var gate = { expected: 2, rendered: 0, empty: 0, failed: 0, status: 'PENDING' };
    ['units','beds'].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('beds_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_BEDS_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.14',
    'target_release' => '10.14.0',
    'status' => $failures === 0 ? 'PASS' : 'FAIL',
    'generated_at' => gmdate('c'),
    'hospital' => strtoupper($hospital),
    'year' => $year,
    'from_date' => $fromDate,
    'to_date' => $toDate,
    'run_live' => $runLive,
    'checks' => $checks,
    'pass_gates' => count($checks) - $failures,
    'fail_gates' => $failures,
    'functions_checked' => is_array($parity) ? (int)($parity['functions_checked'] ?? 0) : 0,
    'identity_mismatches' => is_array($parity) ? (int)($parity['identity_mismatches'] ?? 0) : 0,
    'max_difference' => is_array($parity) ? (float)($parity['max_difference'] ?? 0) : 0,
    'selected_unit_id' => is_array($parity) ? (int)($parity['selected_unit_id'] ?? 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.14 — Beds & Units Legacy Parity QA\n";
echo 'Result: ' . $result['status'] . "\n";
echo 'Functions checked: ' . $result['functions_checked'] . "\n";
echo 'Identity mismatches: ' . $result['identity_mismatches'] . "\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";
}
