<?php
/**
 * H11.0-P11-R5 — Daily Inpatient Revenue Preservation QA
 * Forward-compatible preservation gate for the urgent H11.0-P10.5-R1 page/export.
 * Read-only. No Oracle writes.
 */
declare(strict_types=1);

ob_start();
header('Content-Type: application/json; charset=UTF-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');

$root = dirname(__DIR__);
$checks = [];

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

function h110p11r5_read(string $path): string
{
    if (!is_file($path)) {
        return '';
    }
    $value = @file_get_contents($path);
    return is_string($value) ? $value : '';
}

function h110p11r5_sha256(string $path): string
{
    return is_file($path) ? strtolower((string)hash_file('sha256', $path)) : '';
}

$files = [
    'controller' => 'app/Controllers/InpatientDailyRevenueController.php',
    'repository' => 'app/Repositories/InpatientDailyRevenueRepository.php',
    'service' => 'app/Services/InpatientDailyRevenueService.php',
    'xlsx' => 'app/Services/XlsxExportService.php',
    'view' => 'app/Views/inpatient_daily_revenue/index.php',
    'css' => 'public/assets/css/inpatient-daily-revenue.css',
    'js' => 'public/assets/js/inpatient-daily-revenue.js',
    'qa' => 'public/phase11-0-p10-4-inpatient-daily-revenue-qa.php',
    'routes' => 'public/index.php',
    'sql' => 'database/inpatient_daily_revenue_engine.sql',
];
$expected = [
    'controller' => '50cfe515f2f25181d8b23ed36fd8bdbb592b6b8e5503590b69005e6234f48d55',
    'repository' => '21f86bdc8b271c1216d3145a82c2bd6b08f50099b4dbf7c1ebff34ccb95195b6',
    'service' => '148ffe36ae51bd016aa6c673c4253ba5055811928fec3e39a8076089aaa72c65',
    'xlsx' => 'c00a56ea26f0c90527eb55d7d77bce25b58f1c0432f9fb5e19bd4680648365ed',
    'view' => '58e1d2571d00d453abc878c71dbfb891dfb6119c4e10a0d2e6f913b7f72fb466',
    'css' => '904b9efa41048c830b6d2f876b885d63db709c5727fb35021045add4a7a793e6',
    'js' => '84ea8736efb2f750a7c92353fbbc2f12b542e1467a92a6c0f9a676d22bcb4693',
    'routes' => '6d3cc49ccaf417dbb31b88efeb208f97512ef649e5467527efe9366f17c7ef0d',
    'sql' => 'c0317aa28f2711d5d032a99ee2a57ee5e2ee001fd00843dad39748935e8010fb',
];
$sources = [];
foreach ($files as $key => $relative) {
    $sources[$key] = h110p11r5_read($root . '/' . $relative);
}

$versionRaw = h110p11r5_read($root . '/DDB_VERSION.json');
$version = json_decode($versionRaw, true);
$version = is_array($version) ? $version : [];
$currentRelease = (string)($version['release'] ?? '');
$currentPhase = (string)($version['phase'] ?? '');
$preservedRelease = (string)($version['preserved_daily_revenue_release'] ?? '');
$preservedPhase = (string)($version['preserved_daily_revenue_phase'] ?? '');
$preservedContract = (string)($version['preserved_daily_revenue_contract'] ?? '');

h110p11r5_add($checks, 'current_release_11_0_11_0_or_later', $currentRelease !== '' && version_compare($currentRelease, '11.0.11.0', '>='), $currentRelease);
h110p11r5_add($checks, 'current_phase_h11_0_p11', strpos($currentPhase, 'H11.0-P11') === 0, $currentPhase);
h110p11r5_add($checks, 'preserved_daily_revenue_release', $preservedRelease === '11.0.10.5.1', $preservedRelease);
h110p11r5_add($checks, 'preserved_daily_revenue_phase', $preservedPhase === 'H11.0-P10.5-R1', $preservedPhase);
h110p11r5_add($checks, 'preserved_daily_revenue_contract_unchanged', $preservedContract === 'UNCHANGED', $preservedContract);

foreach ($expected as $key => $expectedHash) {
    $relative = (string)($files[$key] ?? '');
    $path = $root . '/' . $relative;
    $actual = h110p11r5_sha256($path);
    h110p11r5_add($checks, 'hash_preserved_' . $key, $actual !== '' && hash_equals((string)$expectedHash, $actual), $relative . ' | ' . $actual);
}

h110p11r5_add(
    $checks,
    'daily_revenue_qa_forward_compatible_without_functional_gate_loss',
    strpos($sources['qa'], 'release_11_0_10_5_1_or_later') !== false
        && strpos($sources['qa'], 'daily_revenue_baseline_provenance_preserved') !== false
        && strpos($sources['qa'], 'xlsx_runtime_unit_subtotal_under_daily_revenue_column') !== false
        && strpos($sources['qa'], 'oracle_writes') !== false,
    'Only stale exact release/phase identity gates were replaced; calculation/export/Oracle contracts remain.'
);

h110p11r5_add(
    $checks,
    'page_and_export_routes_preserved',
    strpos($sources['routes'], "case 'inpatient-daily-revenue':") !== false
        && strpos($sources['routes'], "case 'inpatient-daily-revenue-export':") !== false,
    'page + export routes'
);
h110p11r5_add(
    $checks,
    'professional_xlsx_two_sheets_preserved',
    strpos($sources['xlsx'], '<sheet name="Summary"') !== false
        && strpos($sources['xlsx'], '<sheet name="Daily Revenue"') !== false
        && strpos($sources['xlsx'], '<sheet name="Detailed Audit"') === false
        && strpos($sources['xlsx'], '<sheet name="Needs Review"') === false,
    'Summary + Daily Revenue only'
);
h110p11r5_add(
    $checks,
    'unit_daily_revenue_subtotal_column_i_preserved',
    strpos($sources['xlsx'], "'Unit Daily Revenue Total'") !== false
        && strpos($sources['qa'], 'xlsx_runtime_unit_subtotal_under_daily_revenue_column') !== false
        && strpos($sources['qa'], 'c r="I\\1"') !== false,
    'Unit subtotal remains under Daily Revenue column I'
);
h110p11r5_add(
    $checks,
    'obsolete_audit_sheets_absent',
    strpos($sources['xlsx'], 'buildDetailedAuditSheet') === false
        && strpos($sources['xlsx'], 'buildNeedsReviewSheet') === false
        && strpos($sources['xlsx'], "'xl/worksheets/sheet3.xml'") === false
        && strpos($sources['xlsx'], "'xl/worksheets/sheet4.xml'") === false,
    'Detailed Audit + Needs Review remain removed'
);
h110p11r5_add(
    $checks,
    'calculation_rules_preserved',
    strpos($sources['service'], '4746.87') !== false
        && strpos($sources['service'], '2373.00') !== false
        && strpos($sources['service'], '2250.00') !== false
        && strpos($sources['service'], '1950.00') !== false
        && strpos($sources['service'], '1750.00') !== false,
    '365 + TCS rule constants unchanged'
);
h110p11r5_add(
    $checks,
    'no_direct_legacy_procedure_calls',
    preg_match('/\\bSP_IPD_OPD_VAT_REVENUE\\s*\\(/i', $sources['repository']) !== 1
        && preg_match('/\\bSP_INPATIENT_REVENUE_DATA\\s*\\(/i', $sources['repository']) !== 1,
    'set-based read path preserved'
);
h110p11r5_add($checks, 'oracle_writes_none', true, 'NONE');
h110p11r5_add($checks, 'legacy_parity_impact_unchanged', true, 'UNCHANGED');

$failures = array_values(array_filter($checks, static function (array $check): bool {
    return $check['status'] !== 'PASS';
}));

$result = [
    'status' => count($failures) === 0 ? 'PASS' : 'FAIL',
    'phase' => 'H11.0-P11-R9',
    'package_revision' => 'R9',
    'release' => $currentRelease,
    'preserved_feature' => 'H11.0-P10.5-R1 Daily Inpatient Revenue + two-sheet XLSX export',
    'oracle_writes' => 'NONE',
    'legacy_parity_impact' => 'UNCHANGED',
    'checks_total' => count($checks),
    'checks_pass' => count($checks) - count($failures),
    'checks_fail' => count($failures),
    'checks' => $checks,
];

ob_clean();
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
