<?php

declare(strict_types=1);

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

use App\Services\PowerBiDailyRevenueExportService;
use App\Services\PowerBiReportValidator;

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

$baseRoot = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'ddb_powerbi_r40_' . bin2hex(random_bytes(6));
@mkdir($baseRoot, 0775, true);

$projectRoot = static function (string $name) use ($baseRoot): string {
    $root = $baseRoot . DIRECTORY_SEPARATOR . $name;
    @mkdir($root . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'powerbi', 0775, true);
    return $root;
};

$masterPath = static function (string $root): string {
    return $root . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'powerbi'
        . DIRECTORY_SEPARATOR . 'Daily_Inpatient_Revenue_Master.pbix';
};

$createArchive = static function (string $path, array $entries): void {
    @unlink($path);
    @unlink($path . '.zip');
    $tempZip = $path . '.zip';
    $archive = new \PharData($tempZip);
    foreach ($entries as $name => $content) {
        $archive[$name] = (string)$content;
    }
    unset($archive);
    if (!@rename($tempZip, $path)) {
        throw new \RuntimeException('Unable to finalize QA archive: ' . $path);
    }
};

$removeTree = static function (string $path) use (&$removeTree): void {
    if (!is_dir($path)) {
        @unlink($path);
        return;
    }
    $items = scandir($path);
    if (!is_array($items)) {
        return;
    }
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') {
            continue;
        }
        $removeTree($path . DIRECTORY_SEPARATOR . $item);
    }
    @rmdir($path);
};

try {
    $missingRoot = $projectRoot('missing');
    $missingValidator = new PowerBiReportValidator($missingRoot);
    $status = $missingValidator->status();
    $add('missing_pbix_is_not_available', ($status['available'] ?? true) === false && ($status['state'] ?? '') === 'MISSING', (string)($status['reason'] ?? ''));

    $textRoot = $projectRoot('renamed_text');
    $textMaster = $masterPath($textRoot);
    file_put_contents($textMaster, str_repeat('not a pbix file', 100));
    $status = (new PowerBiReportValidator($textRoot))->status();
    $add('renamed_text_file_rejected', ($status['available'] ?? true) === false && ($status['state'] ?? '') === 'INVALID', (string)($status['reason'] ?? ''));

    $plainRoot = $projectRoot('ordinary_zip');
    $plainMaster = $masterPath($plainRoot);
    $createArchive($plainMaster, [
        'not-a-powerbi-report.txt' => str_repeat('ordinary zip payload', 100),
        'another-file.txt' => 'x',
        'third-file.txt' => 'y',
    ]);
    $status = (new PowerBiReportValidator($plainRoot))->status();
    $add('ordinary_zip_renamed_pbix_rejected', ($status['available'] ?? true) === false && ($status['state'] ?? '') === 'INVALID' && ($status['reason'] ?? '') === 'PBIX_POWERBI_STRUCTURE_GATE_FAILED', (string)($status['reason'] ?? ''));

    $acceptedRoot = $projectRoot('accepted_candidate');
    $acceptedMaster = $masterPath($acceptedRoot);
    $createArchive($acceptedMaster, [
        'Version' => '1.0',
        'Report/Layout' => str_repeat('{"sections":[]}', 100),
        'Connections' => '{"Connections":[]}',
        'Metadata' => str_repeat('metadata', 100),
    ]);
    $acceptedValidator = new PowerBiReportValidator($acceptedRoot);
    $status = $acceptedValidator->status();
    $add('structural_candidate_requires_desktop_acceptance', ($status['available'] ?? true) === false && ($status['state'] ?? '') === 'STRUCTURALLY_VALID_PENDING_DESKTOP_ACCEPTANCE' && ($status['reason'] ?? '') === 'DESKTOP_ACCEPTANCE_RECEIPT_MISSING', (string)($status['reason'] ?? ''));

    $receiptPath = $acceptedMaster . '.acceptance.json';
    $receipt = [
        'schema' => PowerBiReportValidator::ACCEPTANCE_SCHEMA,
        'pbix_sha256' => str_repeat('0', 64),
        'power_bi_desktop_open' => 'PASS',
        'refresh_from_datapack' => 'PASS',
        'njch_reconciliation' => 'PASS',
        'mnh_reconciliation' => 'PASS',
        'accepted_at' => date('c'),
        'accepted_by' => 'R40 QA synthetic acceptance fixture',
        'evidence_reference' => 'R40_QA_SYNTHETIC_FIXTURE_ONLY',
    ];
    file_put_contents($receiptPath, json_encode($receipt, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
    $status = $acceptedValidator->status();
    $add('wrong_hash_acceptance_receipt_rejected', ($status['available'] ?? true) === false && ($status['state'] ?? '') === 'STRUCTURALLY_VALID_PENDING_DESKTOP_ACCEPTANCE' && ($status['reason'] ?? '') === 'DESKTOP_ACCEPTANCE_RECEIPT_GATE_FAILED', (string)($status['reason'] ?? ''));

    $receipt['pbix_sha256'] = hash_file('sha256', $acceptedMaster);
    file_put_contents($receiptPath, json_encode($receipt, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
    $status = $acceptedValidator->status();
    $add('hash_bound_desktop_acceptance_enables_report', ($status['available'] ?? false) === true && ($status['state'] ?? '') === 'ACCEPTED', (string)($status['reason'] ?? ''));

    $viewSource = (string)file_get_contents(dirname(__DIR__) . '/app/Views/inpatient_daily_revenue/index.php');
    $controllerSource = (string)file_get_contents(dirname(__DIR__) . '/app/Controllers/InpatientDailyRevenueController.php');
    $serviceSource = (string)file_get_contents(dirname(__DIR__) . '/app/Services/PowerBiDailyRevenueExportService.php');
    $validatorSource = (string)file_get_contents(dirname(__DIR__) . '/app/Services/PowerBiReportValidator.php');

    $add('ui_no_longer_uses_raw_pbix_file_existence', strpos($viewSource, "is_file(base_path('resources/powerbi/") === false && strpos($viewSource, 'powerBiReportStatus') !== false, 'view consumes validated status');
    $add('controller_and_export_share_same_service_status', substr_count($controllerSource, 'reportStatus()') >= 2 && strpos($controllerSource, 'http_response_code(409)') !== false, 'index and export use one trust gate');
    $add('service_is_fail_closed_without_accepted_pbix', strpos($serviceSource, "if ((\$status['available'] ?? false) !== true)") !== false && strpos($serviceSource, 'Power BI report is not available') !== false, 'partial package is not mislabeled as Power BI export');
    $add('validator_requires_desktop_acceptance_four_gates', strpos($validatorSource, "'power_bi_desktop_open'") !== false && strpos($validatorSource, "'refresh_from_datapack'") !== false && strpos($validatorSource, "'njch_reconciliation'") !== false && strpos($validatorSource, "'mnh_reconciliation'") !== false, 'open + refresh + NJCH + MNH');

    $report = [
        'hospital_code' => 'NJCH',
        'hospital_name' => 'New Jeddah Hospital',
        'summary' => [
            'generated_at' => date('Y-m-d H:i:s'),
            'patient_count' => 1,
            'daily_revenue' => 2373.00,
            'average_revenue' => 2373.00,
            'review_count' => 0,
        ],
        'companies' => [[
            'financial_class' => 'PAYER 365',
            'patients' => 1,
            'daily_revenue' => 2373.00,
        ]],
        'units' => [[
            'unit_name' => 'Ward A',
            'patients' => 1,
            'beds' => 10,
            'daily_revenue' => 2373.00,
        ]],
        'patients' => [[
            'patientid' => 'QA-1',
            'patient_name' => 'QA Patient',
            'attending_doctor' => 'QA Doctor',
            'room' => '101',
            'bed' => 'A',
            'unit_name' => 'Ward A',
            'financlassid' => 365,
            'financial_class' => 'PAYER 365',
            'los' => 30,
            'total_los' => 30,
            'company_share_total' => 2373.00,
            'daily_revenue' => 2373.00,
            'needs_review' => false,
        ]],
    ];

    $packagePath = $acceptedRoot . DIRECTORY_SEPARATOR . 'accepted_package.zip';
    $acceptedService = new PowerBiDailyRevenueExportService($acceptedValidator);
    $acceptedService->createPackage($packagePath, $report);
    $package = new \PharData($packagePath);
    $hasPbix = isset($package['Daily_Inpatient_Revenue_Master.pbix']);
    $hasValidation = isset($package['PBIX_VALIDATION.json']);
    $hasDataPack = isset($package['DataPack/summary.csv']) && isset($package['DataPack/power_bi_manifest.json']);
    $validationJson = $hasValidation ? json_decode((string)$package['PBIX_VALIDATION.json']->getContent(), true) : null;
    $expectedHash = hash_file('sha256', $acceptedMaster);
    $validationHashOk = is_array($validationJson) && ($validationJson['sha256'] ?? '') === $expectedHash && ($validationJson['state'] ?? '') === 'ACCEPTED';
    unset($package);

    $add('accepted_package_contains_pbix_datapack_and_validation_manifest', $hasPbix && $hasValidation && $hasDataPack, 'PBIX + DataPack + PBIX_VALIDATION.json');
    $add('package_validation_manifest_binds_exact_pbix_hash', $validationHashOk, (string)$expectedHash);

    $pendingRoot = $projectRoot('pending_package');
    $pendingMaster = $masterPath($pendingRoot);
    $createArchive($pendingMaster, [
        'Version' => '1.0',
        'Report/Layout' => str_repeat('{"sections":[]}', 100),
        'Connections' => '{"Connections":[]}',
        'Metadata' => str_repeat('metadata', 100),
    ]);
    $pendingService = new PowerBiDailyRevenueExportService(new PowerBiReportValidator($pendingRoot));
    $missingPackagePath = $pendingRoot . DIRECTORY_SEPARATOR . 'blocked_package.zip';
    $blocked = false;
    try {
        $pendingService->createPackage($missingPackagePath, $report);
    } catch (\RuntimeException $e) {
        $blocked = strpos($e->getMessage(), 'Power BI report is not available') !== false;
    }
    $add('user_facing_powerbi_package_blocked_without_desktop_acceptance', $blocked && !is_file($missingPackagePath), $blocked ? 'blocked' : 'not_blocked');
} catch (\Throwable $e) {
    $add('unexpected_exception', false, $e->getMessage());
} finally {
    $removeTree($baseRoot);
}

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

$result = [
    'phase' => 'H11.0-P11.1-R40',
    'release' => '11.0.11.47',
    'title' => 'Power BI PBIX Trust Gate and Desktop Acceptance Contract',
    'checks' => $checks,
    'pass_gates' => count($checks) - $failures,
    'fail_gates' => $failures,
    'pbix_live_file_in_candidate' => is_file(dirname(__DIR__) . '/resources/powerbi/Daily_Inpatient_Revenue_Master.pbix') ? 'PRESENT' : 'NOT_PRESENT',
    'power_bi_desktop_acceptance' => 'PENDING_UNTIL_REAL_PBIX_AND_HASH_BOUND_ACCEPTANCE_RECEIPT_EXIST',
    'oracle_writes' => 'NONE',
    'database_changes' => 'NONE',
    'calculation_rules_changed' => false,
    'status' => $failures === 0 ? 'PASS' : 'FAIL',
];

echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
exit($failures === 0 ? 0 : 1);
