<?php

/**
 * ICYLAB Billing runtime gate diagnostic v6.10.
 * Read-only. Does not connect to FACTO and does not modify the database.
 */

if (PHP_SAPI !== 'cli') {
    http_response_code(403);
    exit("CLI only.\n");
}

require_once __DIR__ . '/../core/config.php';

function diagnostic_bool($value)
{
    return $value ? 'true' : 'false';
}

function diagnostic_assertion($operation, $environment)
{
    try {
        billing_assert_runtime_operation($operation, $environment, 'Diagnóstico v6.10');
        return array(
            'status' => 'ALLOWED',
            'gate_code' => null,
        );
    } catch (BillingRuntimeGateException $e) {
        return array(
            'status' => 'BLOCKED',
            'gate_code' => $e->getGateCode(),
        );
    } catch (Throwable $e) {
        return array(
            'status' => 'ERROR',
            'gate_code' => get_class($e) . ': ' . $e->getMessage(),
        );
    }
}

$production = billing_runtime_gate_state('production');
$sandbox = billing_runtime_gate_state('sandbox');
$defaultEnvironment = billing_runtime_environment(null);
$operations = array('read', 'sync', 'download', 'email', 'finance', 'payment', 'collection', 'reception', 'issue', 'emit');

$expectedProduction = array(
    'read' => $production['read_enabled'],
    'sync' => $production['read_enabled'],
    'download' => $production['read_enabled'],
    'email' => $production['read_enabled'],
    'finance' => $production['finance_enabled'],
    'payment' => $production['finance_enabled'],
    'collection' => $production['finance_enabled'],
    'reception' => $production['finance_enabled'],
    'issue' => $production['issue_enabled'],
    'emit' => $production['issue_enabled'],
);

$failures = array();
$rows = array();
foreach (array('production', 'sandbox') as $environment) {
    foreach ($operations as $operation) {
        $assertion = diagnostic_assertion($operation, $environment);
        $allowed = $assertion['status'] === 'ALLOWED';
        $expected = $environment === 'sandbox' ? true : (bool)$expectedProduction[$operation];
        if ($allowed !== $expected || $assertion['status'] === 'ERROR') {
            $failures[] = $environment . '/' . $operation;
        }
        $rows[] = array(
            'environment' => $environment,
            'operation' => $operation,
            'status' => $assertion['status'],
            'gate_code' => $assertion['gate_code'],
            'expected' => $expected ? 'ALLOWED' : 'BLOCKED',
        );
    }
}

$hierarchyOk = true;
if ($production['finance_enabled'] && !$production['read_enabled']) {
    $hierarchyOk = false;
    $failures[] = 'hierarchy/finance_without_read';
}
if ($production['issue_enabled'] && (!$production['read_enabled'] || !$production['finance_enabled'])) {
    $hierarchyOk = false;
    $failures[] = 'hierarchy/issue_without_read_finance';
}

$requiredFiles = array(
    'services/billing/BillingRuntimeGate.php',
    'services/billing/BillingReceivablesService.php',
    'services/billing/BillingPayablesService.php',
    'services/billing/BillingInboxReceptionService.php',
    'services/facto/FactoClient.php',
    'services/facto/FactoCustomersSyncService.php',
    'services/facto/FactoDocumentsSyncService.php',
    'services/facto/FactoInboxDocumentsSyncService.php',
);
$missingFiles = array();
foreach ($requiredFiles as $relativePath) {
    if (!is_file(dirname(__DIR__) . '/' . $relativePath)) {
        $missingFiles[] = $relativePath;
        $failures[] = 'missing_file/' . $relativePath;
    }
}

$result = count($failures) === 0 ? 'PASS' : 'FAIL';

echo "ICYLAB BILLING RUNTIME GATE DIAGNOSTIC v6.10\n";
echo "Generated at UTC: " . gmdate('Y-m-d H:i:s') . "\n";
echo "PHP: " . PHP_VERSION . "\n";
echo "App root: " . dirname(__DIR__) . "\n";
echo "DB name: " . (defined('DB_NAME') ? DB_NAME : 'UNDEFINED') . "\n";
echo "Default FACTO environment: " . $defaultEnvironment . "\n";
echo "Gate version: " . (defined('ICYLAB_BILLING_RUNTIME_GATE_VERSION') ? ICYLAB_BILLING_RUNTIME_GATE_VERSION : 'UNDEFINED') . "\n\n";

echo "PRODUCTION FLAGS\n";
echo "read_flag=" . diagnostic_bool($production['production_read_flag']) . "\n";
echo "finance_flag=" . diagnostic_bool($production['production_finance_flag']) . "\n";
echo "issue_flag=" . diagnostic_bool($production['production_issue_flag']) . "\n";
echo "effective_read=" . diagnostic_bool($production['read_enabled']) . "\n";
echo "effective_finance=" . diagnostic_bool($production['finance_enabled']) . "\n";
echo "effective_issue=" . diagnostic_bool($production['issue_enabled']) . "\n";
echo "hierarchy=" . ($hierarchyOk ? 'PASS' : 'FAIL') . "\n\n";

echo "ASSERTION MATRIX\n";
foreach ($rows as $row) {
    echo $row['environment'] . '/' . $row['operation'] . ': ' . $row['status'];
    if ($row['gate_code']) {
        echo ' [' . $row['gate_code'] . ']';
    }
    echo ' expected=' . $row['expected'] . "\n";
}

echo "\nREQUIRED FILES\n";
foreach ($requiredFiles as $relativePath) {
    echo $relativePath . ': ' . (in_array($relativePath, $missingFiles, true) ? 'MISSING' : 'OK') . "\n";
}

echo "\nRESULT: " . $result . "\n";
if ($failures) {
    echo "FAILURES:\n- " . implode("\n- ", $failures) . "\n";
}

exit($result === 'PASS' ? 0 : 1);
