<?php

declare(strict_types=1);

$siteRoot = dirname(__DIR__);
$result = [
    'schema' => 'DIAR4B_LOCAL_FOUNDATION_TEST_V1',
    'captured_at' => date(DATE_ATOM),
    'status' => 'FAIL',
    'gates' => [],
    'source_counts' => [],
    'php_runtime' => PHP_VERSION,
    'oracle_operational_writes' => 'NONE',
];

function countCsvRows(string $path): int
{
    if (!is_file($path)) {
        return -1;
    }
    $h = fopen($path, 'rb');
    if (!$h) {
        return -1;
    }
    $count = -1;
    while (fgetcsv($h) !== false) {
        $count++;
    }
    fclose($h);
    return max(0, $count);
}

function lintPhp(string $path): bool
{
    if (!is_file($path) || !function_exists('proc_open')) {
        return false;
    }
    $out = tempnam(sys_get_temp_dir(), 'd4bo');
    $err = tempnam(sys_get_temp_dir(), 'd4be');
    if ($out === false || $err === false) {
        return false;
    }
    $null = PHP_OS_FAMILY === 'Windows' ? 'NUL' : '/dev/null';
    $spec = [0=>['file',$null,'r'],1=>['file',$out,'w'],2=>['file',$err,'w']];
    $process = @proc_open([PHP_BINARY,'-l',$path], $spec, $pipes, $siteRoot, null, PHP_OS_FAMILY === 'Windows' ? ['bypass_shell'=>true] : []);
    if (!is_resource($process)) {
        @unlink($out); @unlink($err);
        return false;
    }
    $code = proc_close($process);
    @unlink($out); @unlink($err);
    return $code === 0;
}

try {
    $required = [
        'app/Controllers/DiarInvestigationController.php',
        'app/Repositories/DiarInvestigationRepository.php',
        'app/Views/diar_investigations/index.php',
        'app/Views/diar_investigations/detail.php',
        'public/assets/css/diar-investigations.css',
        'public/assets/js/diar-investigations.js',
        'tools/diar4b-apply.php',
        'tools/diar4b-live-acceptance.php',
        'config/access_control.php',
        'public/index.php',
        'app/Views/layouts/main.php',
        'DDB_VERSION.json',
    ];
    foreach ($required as $relative) {
        if (!is_file($siteRoot . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relative))) {
            throw new RuntimeException('REQUIRED_FILE_MISSING_' . $relative);
        }
    }
    $result['gates']['REQUIRED_FILES'] = 'PASS';

    $phpFiles = array_values(array_filter($required, function (string $relative): bool {
        return substr($relative, -4) === '.php';
    }));
    foreach ($phpFiles as $relative) {
        if (!lintPhp($siteRoot . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relative))) {
            throw new RuntimeException('PHP_LINT_FAILED_' . $relative);
        }
    }
    $result['gates']['PHP_LINT'] = 'PASS';

    $access = (string)file_get_contents($siteRoot . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'access_control.php');
    $router = (string)file_get_contents($siteRoot . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'index.php');
    $layout = (string)file_get_contents($siteRoot . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'Views' . DIRECTORY_SEPARATOR . 'layouts' . DIRECTORY_SEPARATOR . 'main.php');
    foreach ([
        'diar.investigation.view','diar.investigation.assign','diar.investigation.review',
        'diar.investigation.evidence','diar.investigation.escalate','diar.investigation.close'
    ] as $permission) {
        if (strpos($access, "'" . $permission . "'") === false) {
            throw new RuntimeException('ACL_PERMISSION_MISSING_' . $permission);
        }
    }
    if (strpos($router, "case 'diar-investigations':") === false
        || strpos($router, "case 'diar-investigation':") === false
        || strpos($router, 'DiarInvestigationController') === false) {
        throw new RuntimeException('ROUTER_CONTRACT_MISSING');
    }
    if (strpos($layout, 'DIAR4B_NAV_V1') === false
        || strpos($layout, 'diar-investigations.css') === false
        || strpos($layout, 'diar-investigations.js') === false) {
        throw new RuntimeException('LAYOUT_CONTRACT_MISSING');
    }
    $result['gates']['ACL_ROUTER_LAYOUT'] = 'PASS';

    $repositoryText = (string)file_get_contents($siteRoot . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'Repositories' . DIRECTORY_SEPARATOR . 'DiarInvestigationRepository.php');
    $ddlText = (string)file_get_contents($siteRoot . DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'DIAR4B_SCHEMA_DDL.sql');
    if (strpos($repositoryText, 'ASSIGNEE_SITE_ACCESS_REQUIRED') === false
        || strpos($repositoryText, 'previous_resolution_summary') === false
        || strpos($repositoryText, 'DETAIL_JSON') === false
        || strpos($ddlText, 'UX_DIAR_ASSIGN_ONE_ACTIVE') === false) {
        throw new RuntimeException('CASE_GOVERNANCE_GUARDS_MISSING');
    }
    $result['gates']['CASE_GOVERNANCE_GUARDS'] = 'PASS';

    $version = json_decode((string)file_get_contents($siteRoot . DIRECTORY_SEPARATOR . 'DDB_VERSION.json'), true);
    if (!is_array($version) || !is_array($version['diar4b'] ?? null)
        || (int)($version['diar4b']['source_cases'] ?? 0) !== 3421
        || (int)($version['diar4b']['review_entities'] ?? 0) !== 2913) {
        throw new RuntimeException('VERSION_CONTRACT_FAILED');
    }
    $result['gates']['VERSION_CONTRACT'] = 'PASS';

    $seedRoot = $siteRoot . DIRECTORY_SEPARATOR . 'tools' . DIRECTORY_SEPARATOR . 'diar4b-seed';
    $hashes = [
        'cross_branch_final_review_queue.csv' => 'd7a33ada04c4b98886c03e0955571c7ba32ab37ae247159000d568b369c01a08',
        'NJCH/event_member_details.csv' => '94f9a40f79ab39e59b62b90f00386da417a17818911f60c6b22c808e600b2b46',
        'MNH/event_member_details.csv' => '4439adabc4ac1ee20b12e42b19f7cf65ecd08840593d268ec93131a9f062ced1',
    ];
    foreach ($hashes as $relative => $expected) {
        $path = $seedRoot . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relative);
        if (!is_file($path) || !hash_equals($expected, hash_file('sha256', $path))) {
            throw new RuntimeException('SEED_HASH_FAILED_' . $relative);
        }
    }
    $queueCount = countCsvRows($seedRoot . DIRECTORY_SEPARATOR . 'cross_branch_final_review_queue.csv');
    $njchCount = countCsvRows($seedRoot . DIRECTORY_SEPARATOR . 'NJCH' . DIRECTORY_SEPARATOR . 'event_member_details.csv');
    $mnhCount = countCsvRows($seedRoot . DIRECTORY_SEPARATOR . 'MNH' . DIRECTORY_SEPARATOR . 'event_member_details.csv');
    $result['source_counts'] = ['queue'=>$queueCount,'njch_source'=>$njchCount,'mnh_source'=>$mnhCount,'source_total'=>$njchCount+$mnhCount];
    if ($queueCount !== 2913 || $njchCount !== 685 || $mnhCount !== 2736) {
        throw new RuntimeException('SOURCE_ROW_COUNTS_FAILED');
    }
    $result['gates']['SOURCE_FILES_AND_COUNTS'] = 'PASS';

    $scanFiles = [];
    foreach ($phpFiles as $relative) {
        $scanFiles[] = $siteRoot . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $relative);
    }
    $scanFiles[] = $siteRoot . DIRECTORY_SEPARATOR . 'database' . DIRECTORY_SEPARATOR . 'DIAR4B_SCHEMA_DDL.sql';
    foreach ($scanFiles as $path) {
        if (!is_file($path)) {
            continue;
        }
        $text = (string)file_get_contents($path);
        if (preg_match('/\bmixed\s+\$[A-Za-z_]/', $text)) {
            throw new RuntimeException('PHP74_MIXED_TYPE_DECLARATION_FOUND_' . basename($path));
        }
        if (preg_match('/\b(str_contains|str_starts_with|str_ends_with)\s*\(/', $text)) {
            throw new RuntimeException('PHP8_FUNCTION_FOUND_' . basename($path));
        }
        if (preg_match('/\b(INSERT\s+INTO|UPDATE|DELETE\s+FROM|MERGE\s+INTO|CREATE\s+TABLE|ALTER\s+TABLE|DROP\s+TABLE)\s+MM[A-Z0-9_]+/i', $text)) {
            throw new RuntimeException('OPERATIONAL_MM_WRITE_FOUND_' . basename($path));
        }
    }
    $result['gates']['PHP74_COMPATIBILITY'] = 'PASS';
    $result['gates']['ORACLE_OPERATIONAL_WRITES_NONE'] = 'PASS';
    $result['gates']['NO_AUTOMATIC_FRAUD_CONCLUSION'] = 'PASS';
    $result['status'] = 'PASS';
    echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(0);
} catch (Throwable $e) {
    $result['error'] = $e->getMessage();
    echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
    exit(1);
}
