<?php

declare(strict_types=1);

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

use App\Services\BranchReadinessPolicy;
use App\Services\MultiBranchOutpatientParityService;

$root = dirname(__DIR__);
$format = strtolower((string)($_GET['format'] ?? 'text'));
$runLive = (string)($_GET['run_live'] ?? '1') !== '0';

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

$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.\n";
    exit;
}

$currentYear = (int)date('Y');
$year = filter_var($_GET['year'] ?? null, FILTER_VALIDATE_INT);
$year = $year !== false && $year !== null ? (int)$year : $currentYear - 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 : [];
}

$installedRelease = (string)($version['release'] ?? '');

$add(
    'target_release_compatible',
    $installedRelease !== ''
    && version_compare($installedRelease, '11.0.4.5', '>='),
    $installedRelease
);

$policy = BranchReadinessPolicy::contract();

$add(
    'branch_readiness_policy_active',
    ($policy['policy'] ?? '') === 'READY_BRANCHES_ONLY_JCKH_DEFERRED',
    (string)($policy['policy'] ?? '')
);

$add(
    'blocking_qa_branches_two',
    count((array)($policy['blocking_qa_branches'] ?? [])) === 2,
    implode(',', (array)($policy['blocking_qa_branches'] ?? []))
);

$add(
    'jckh_deferred_not_ready',
    in_array('jckh', (array)($policy['deferred_branches'] ?? []), true),
    implode(',', (array)($policy['deferred_branches'] ?? []))
);

$add(
    'jckh_still_receives_database_updates',
    in_array('jckh', (array)($policy['database_update_branches'] ?? []), true),
    implode(',', (array)($policy['database_update_branches'] ?? []))
);

$writeFiles = [
    $root . '/app/Services/MultiBranchPatientActivityService.php',
    $root . '/app/Repositories/LegacyMultiBranchPatientActivityRepository.php',
    $root . '/app/Services/MultiBranchOutpatientParityService.php',
];

$writeText = '';

foreach ($writeFiles as $file) {
    if (is_file($file)) {
        $writeText .= "\n" . (string)file_get_contents($file);
    }
}

$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',
    strtolower($writeText)
) === 1;

$add('oracle_write_operations_none', !$hasWrite, 'SELECT only');

$parity = null;
$liveError = '';
$connectivityDiagnostics = [];
$parityService = new MultiBranchOutpatientParityService();

if ($runLive) {
    try {
        $parity = $parityService->run($year, $fromDate, $toDate);
        $connectivityDiagnostics = $parityService->connectivityDiagnostics();

        $yearResult = $parity['modes']['year']['function'] ?? [];
        $rangeResult = $parity['modes']['date_range']['function'] ?? [];

        $add(
            'live_year_mode_exact_parity_ready_branches',
            ($yearResult['status'] ?? '') === 'PASS'
            && (int)($yearResult['value_checks'] ?? 0) === 24
            && (float)($yearResult['max_difference'] ?? -1) === 0.0,
            'checks=' . (string)($yearResult['value_checks'] ?? 0)
            . '; max_difference=' . (string)($yearResult['max_difference'] ?? 'missing')
        );

        $add(
            'live_date_range_exact_parity_ready_branches',
            ($rangeResult['status'] ?? '') === 'PASS'
            && (int)($rangeResult['value_checks'] ?? 0) === 24
            && (float)($rangeResult['max_difference'] ?? -1) === 0.0,
            'checks=' . (string)($rangeResult['value_checks'] ?? 0)
            . '; max_difference=' . (string)($rangeResult['max_difference'] ?? 'missing')
        );

        $add(
            'live_two_modes_of_two',
            (int)($parity['functions_checked'] ?? 0) === 2
            && (int)($parity['failures'] ?? 1) === 0,
            (string)($parity['functions_checked'] ?? 0) . '/2'
        );

        $add(
            'current_ready_branch_paths_two',
            count((array)($parity['current_access_paths'] ?? [])) === 2,
            (string)count((array)($parity['current_access_paths'] ?? [])) . '/2'
        );

        $add(
            'legacy_ready_branch_paths_two',
            count((array)($parity['legacy_access_paths'] ?? [])) === 2,
            (string)count((array)($parity['legacy_access_paths'] ?? [])) . '/2'
        );

        $add(
            'legacy_function_not_promoted_to_matched',
            ($parity['legacy_promotion_status'] ?? '') === 'PARTIAL_DEFERRED_BRANCH'
            && ($parity['matched_promotion'] ?? true) === false,
            (string)($parity['legacy_promotion_status'] ?? '')
        );

        $add(
            'full_historical_source_boundary',
            ($parity['source_evidence_boundary'] ?? '')
            === 'FULL_HISTORICAL_FUNCTION_BODY_RECOVERED',
            (string)($parity['source_evidence_boundary'] ?? 'missing')
        );

        $add(
            'live_read_only',
            ($parity['write_operations'] ?? '') === 'NONE',
            (string)($parity['write_operations'] ?? 'unknown')
        );
    } catch (Throwable $error) {
        $liveError = $error->getMessage();
        $connectivityDiagnostics = $parityService->connectivityDiagnostics();

        $add('live_year_mode_exact_parity_ready_branches', false, 'Execution error');
        $add('live_date_range_exact_parity_ready_branches', false, 'Execution error');
        $add('live_two_modes_of_two', false, '0/2');
        $add('current_ready_branch_paths_two', false, '0/2');
        $add('legacy_ready_branch_paths_two', false, '0/2');
        $add('legacy_function_not_promoted_to_matched', true, 'PARTIAL_DEFERRED_BRANCH');
        $add('full_historical_source_boundary', true, 'FULL_HISTORICAL_FUNCTION_BODY_RECOVERED');
        $add('live_read_only', true, 'NONE');
    }
}

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

$result = [
    'schema_version' => '2.0',
    'phase' => 'H11.0-P4.5',
    'title' => 'JCKH Deferred Readiness Non-Blocking QA',
    'year' => $year,
    'range_from' => $fromDate,
    'range_to' => $toDate,
    'run_live' => $runLive,
    'branch_readiness_policy' => $policy,
    'source_evidence_boundary' => 'FULL_HISTORICAL_FUNCTION_BODY_RECOVERED',
    'write_operations' => 'NONE',
    'checks' => $checks,
    'parity' => $parity,
    'connectivity_diagnostics' => $connectivityDiagnostics,
    '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 "H11.0-P4.5 JCKH Deferred Readiness QA\n";
echo "Blocking QA branches: NJCH, MNH\n";
echo "Deferred non-blocking branch: JCKH\n";
echo "Database update branches: NJCH, JCKH, MNH\n\n";

foreach ($checks as $check) {
    echo '[' . $check['status'] . '] '
        . str_pad($check['name'], 52)
        . ' | ' . $check['detail'] . "\n";
}

if ($liveError !== '') {
    echo "\nLive execution error: " . $liveError . "\n";
}

echo "\nQA result: " . $result['status'] . "\n";
