<?php
require_once __DIR__ . '/../core/config.php';
require_once __DIR__ . '/../core/database.php';
require_once __DIR__ . '/../services/billing/BillingRuntimeGate.php';

date_default_timezone_set('UTC');
$root = dirname(__DIR__);
$checks = array();
$failures = array();

function v6191_check(&$checks, &$failures, $label, $ok, $detail = '') {
    $checks[] = array($label, (bool)$ok, (string)$detail);
    if (!$ok) $failures[] = $label . ($detail !== '' ? ': ' . $detail : '');
}
function v6191_file($root, $relative) {
    $path = $root . '/' . $relative;
    return is_file($path) ? (string)file_get_contents($path) : '';
}
function v6191_has_all($text, array $needles) {
    foreach ($needles as $needle) if (strpos($text, $needle) === false) return false;
    return true;
}

$pdo = db();
$dbName = (string)$pdo->query('SELECT DATABASE()')->fetchColumn();
$payables = v6191_file($root, 'services/billing/BillingPayablesService.php');
$sync = v6191_file($root, 'services/facto/FactoInboxDocumentsSyncService.php');
$ui = v6191_file($root, 'modules/billing/payables.php');

v6191_check($checks, $failures, 'database target', $dbName === 'icylab_app', $dbName);
v6191_check($checks, $failures, 'approved invoice status detector installed', v6191_has_all($payables, array('approvedPayableStatusSql', 'isApprovedPayableDocument', 'is_approved_for_payable')));
v6191_check($checks, $failures, 'unapproved invoice cannot materialize CxP', strpos($payables, 'La factura debe estar aprobada antes de crear la cuenta por pagar.') !== false && strpos($payables, 'La factura recibida no está aprobada') !== false);
v6191_check($checks, $failures, 'sync catch-up for approved invoices installed', v6191_has_all($sync, array('catchUpApprovedPayable', 'BillingPayablesService', 'billing_runtime_gate_allows')));
v6191_check($checks, $failures, 'payable list distinguishes approval and CxP state', v6191_has_all($ui, array('pendiente_cxp', 'pendiente_aprobacion', 'is_approved_for_payable')));
v6191_check($checks, $failures, 'individual and group selection remain collection guarded', v6191_has_all($ui, array("Number(r.collection_id||0)>0", 'payables-select-all-group', 'payable-select')));
v6191_check($checks, $failures, 'production issue remains blocked', !billing_runtime_gate_allows('issue', 'production'));

$approvedSql = "(
 LOWER(TRIM(CAST(COALESCE(d.icylab_reception_status,'') AS CHAR))) IN ('approved','approved_with_observations')
 OR LOWER(TRIM(CAST(COALESCE(d.document_approval_status,'') AS CHAR))) IN ('1','accepted','approved','approved_with_observations')
 OR TRIM(CAST(COALESCE(d.inbox_document_status,'') AS CHAR)) IN ('2','3')
)";

$candidateSql = "SELECT COUNT(*) FROM facto_inbox_documents d
 LEFT JOIN billing_collections c ON BINARY c.environment=BINARY d.environment AND BINARY c.direction=BINARY 'payable' AND BINARY c.inbox_document_id=BINARY d.inbox_document_id
 WHERE BINARY d.environment=BINARY 'production'
   AND CAST(COALESCE(d.document_type_id,0) AS UNSIGNED) IN (9,33)
   AND d.total_amount > 0
   AND " . $approvedSql . "
   AND c.id IS NULL";
$approvedMissing = (int)$pdo->query($candidateSql)->fetchColumn();

$selectable = (int)$pdo->query("SELECT COUNT(*) FROM billing_collections c
 WHERE BINARY c.environment=BINARY 'production' AND BINARY c.direction=BINARY 'payable'
   AND c.balance_amount > 0.5 AND c.collection_status NOT IN ('pagado','rechazado','anulado')")->fetchColumn();

$duplicates = (int)$pdo->query("SELECT COUNT(*) FROM (
 SELECT environment,inbox_document_id,COUNT(*) c
 FROM billing_collections
 WHERE BINARY environment=BINARY 'production' AND BINARY direction=BINARY 'payable'
 GROUP BY environment,inbox_document_id HAVING COUNT(*)>1
) x")->fetchColumn();

v6191_check($checks, $failures, 'no duplicate productive CxP groups', $duplicates === 0, 'groups=' . $duplicates);

$gate = billing_runtime_gate_state('production');

echo "ICYLAB BILLING PAYABLE SELECTION + APPROVED CxP CATCH-UP DIAGNOSTIC v6.19.1\n";
echo 'Generated at UTC: ' . gmdate('Y-m-d H:i:s') . "\n";
echo 'PHP: ' . PHP_VERSION . "\n";
echo 'App root: ' . $root . "\n";
echo 'DB name: ' . $dbName . "\n\n";
foreach ($checks as $check) {
    echo $check[0] . ': ' . ($check[1] ? 'PASS' : 'FAIL') . ($check[2] !== '' ? ' [' . $check[2] . ']' : '') . "\n";
}
echo "\nRUNTIME / DATA\n";
echo 'production read: ' . ($gate['read_enabled'] ? 'ALLOWED' : 'BLOCKED') . "\n";
echo 'production finance: ' . ($gate['finance_enabled'] ? 'ALLOWED' : 'BLOCKED') . "\n";
echo 'production issue: ' . ($gate['issue_enabled'] ? 'ALLOWED' : 'BLOCKED') . "\n";
echo 'approved invoices missing CxP: ' . $approvedMissing . "\n";
echo 'currently selectable open CxP: ' . $selectable . "\n";
echo "\nRESULT: " . (count($failures) === 0 ? 'PASS' : 'FAIL') . "\n";
if ($failures) foreach ($failures as $failure) echo '- ' . $failure . "\n";
exit($failures ? 1 : 0);
