<?php
/**
 * SUDANNA AI OS — GO-LIVE VERIFICATION SCRIPT v1.0
 * ═══════════════════════════════════════════════════
 * Run ONCE on server: /go_live_proof.php?token=GOLIVE2026
 * DELETE IMMEDIATELY AFTER
 * Returns full JSON proof of end-to-end execution
 */
if (($_GET['token'] ?? '') !== 'GOLIVE2026') {
    http_response_code(403);
    die(json_encode(['error' => 'forbidden']));
}

// Load full system
require_once __DIR__ . '/config.php';

// ═══════════════════════════════════════════════════════════════
// SECURITY: This file MUST be deleted after first run on server
// DELETE: rm /var/www/go_live_proof.php
// Or: add to .htaccess: <Files go_live_proof.php> Deny from all </Files>
// ═══════════════════════════════════════════════════════════════
if (file_exists(__DIR__ . '/.golive_done')) {
    http_response_code(410);
    die(json_encode(['error' => 'already_run', 'message' => 'This script has been executed. Delete it from server for security.']));
}
require_once __DIR__ . '/engine/Gateway.php';
require_once __DIR__ . '/engine/InvoiceEngine.php';
require_once __DIR__ . '/engine/FinancialAgent.php';
require_once __DIR__ . '/engine/EventBus.php';
require_once __DIR__ . '/engine/QueueEngine.php';
require_once __DIR__ . '/engine/AIOrchestrator.php';
require_once __DIR__ . '/engine/InferenceEngine.php';

header('Content-Type: application/json; charset=utf-8');

$proof  = ['run_at' => date('Y-m-d H:i:s'), 'steps' => [], 'failures' => []];
$userId = 1; // admin user for proof
$pass   = 0;
$total  = 0;

$step = function(string $id, callable $fn) use (&$proof, &$pass, &$total) {
    $total++;
    $t0 = round(microtime(true) * 1000);
    try {
        $result = $fn();
        $ok = $result['ok'] ?? true;
        if ($ok) $pass++;
        $proof['steps'][$id] = array_merge(
            ['ok' => $ok, 'ms' => round(microtime(true)*1000) - $t0],
            $result
        );
    } catch (Throwable $e) {
        $proof['steps'][$id] = ['ok' => false, 'error' => $e->getMessage(),
                                 'ms' => round(microtime(true)*1000) - $t0];
        $proof['failures'][] = "$id: " . $e->getMessage();
    }
};

// ══ 1. DATABASE HEALTH ═══════════════════════════════════════════
$step('01_db_health', function() {
    $tables  = db()->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
    $needed  = ['users','invoices','payment_proofs','ledger','accounts',
                 'tasks','flow_sessions','notifications','wallet',
                 'wallet_transactions','ai_decisions','audit_logs'];
    $missing = array_values(array_diff($needed, $tables));
    $providers = (int)db()->query(
        "SELECT COUNT(*) FROM users WHERE provider_verified=1"
    )->fetchColumn();
    return [
        'ok'               => empty($missing),
        'total_tables'     => count($tables),
        'missing'          => $missing,
        'verified_providers'=> $providers,
        'accounts_seeded'  => (int)db()->query("SELECT COUNT(*) FROM accounts")->fetchColumn(),
    ];
});

// ══ 2. INTELLIGENCE TEST ══════════════════════════════════════════
$step('02_intelligence', function() {
    $tests = [
        ['q'=>'محتاج محامي',       'exp'=>'legal'],
        ['q'=>'طفلي مريض',         'exp'=>'medical'],
        ['q'=>'أريد دواء',          'exp'=>'pharmacy'],
        ['q'=>'أبحث عن وظيفة',    'exp'=>'career'],
        ['q'=>'أريد أتعلم برمجة',  'exp'=>'academic'],
        ['q'=>'أحداث في الخرطوم', 'exp'=>'community'],
        ['q'=>'عايز مشروع',        'exp'=>'business'],
    ];
    $pass = 0; $results = [];
    foreach ($tests as $t) {
        $r = InferenceEngine::infer($t['q']);
        $ok = ($r['sector'] ?? '') === $t['exp'];
        if ($ok) $pass++;
        $results[] = ['q'=>$t['q'], 'got'=>$r['sector']??'null',
                       'conf'=>round($r['confidence']??0,2), 'ok'=>$ok];
    }
    return ['ok' => $pass === count($tests), 'passed' => "$pass/".count($tests),
             'results' => $results];
});

// ══ 3. API KEYS VALIDATION ════════════════════════════════════════
$step('03_api_keys', function() {
    $keys = [
        'GEMINI_API_KEY'  => defined('GEMINI_API_KEY')  ? strlen(GEMINI_API_KEY)  : 0,
        'CLAUDE_API_KEY'  => defined('CLAUDE_API_KEY')  ? strlen(CLAUDE_API_KEY)  : 0,
        'FCM_SERVER_KEY'  => defined('FCM_SERVER_KEY')  ? strlen(FCM_SERVER_KEY)  : 0,
    ];
    $realKeys = array_filter($keys, fn($len) => $len > 20);
    return [
        'ok'       => count($realKeys) >= 1,
        'keys'     => array_map(fn($l) => $l > 20 ? "SET($l chars)" : "EMPTY/SHORT", $keys),
    ];
});

// ══ 4. INVOICE CREATION ═══════════════════════════════════════════
$invoiceId = null;
$refCode   = null;
$step('04_invoice_create', function() use (&$invoiceId, &$refCode, $userId) {
    $r = InvoiceEngine::create($userId, 'legal', 500.00, ['test' => 'go_live_proof']);
    $invoiceId = $r['invoice_id'] ?? null;
    $refCode   = $r['reference_code'] ?? null;
    if ($invoiceId) {
        $row = db()->query("SELECT id,user_id,service,amount,reference_code,status,created_at
                            FROM invoices WHERE id=$invoiceId")->fetch(PDO::FETCH_ASSOC);
    }
    return [
        'ok'             => ($r['success'] ?? false) && $invoiceId,
        'invoice_id'     => $invoiceId,
        'reference_code' => $refCode,
        'db_row'         => $row ?? null,
        'instructions'   => $r['instructions'] ?? null,
    ];
});

// ══ 5. PROOF UPLOAD ════════════════════════════════════════════════
$fileHash = null;
$step('05_proof_upload', function() use (&$fileHash, $invoiceId) {
    if (!$invoiceId) return ['ok'=>false,'error'=>'No invoice from step 4'];
    $fakePath = 'uploads/proofs/test_' . time() . '.jpg';
    $fileHash = hash('sha256', 'go_live_test_' . $invoiceId . microtime());
    $r = InvoiceEngine::uploadProof($invoiceId, $fakePath, $fileHash);
    $row = db()->query("SELECT * FROM payment_proofs WHERE invoice_id=$invoiceId")
                ->fetch(PDO::FETCH_ASSOC);
    return [
        'ok'         => $r['success'] ?? false,
        'db_row'     => $row,
        'response'   => $r,
    ];
});

// ══ 6. IDEMPOTENCY — DUPLICATE PROOF ══════════════════════════════
$step('06_idempotency_proof', function() use ($invoiceId, $fileHash) {
    if (!$invoiceId) return ['ok'=>false,'error'=>'No invoice'];
    // Test 1: Same invoice_id → must fail (UNIQUE constraint)
    $dup1 = InvoiceEngine::uploadProof($invoiceId, 'dup_' . time() . '.jpg',
                                        hash('sha256', 'new_hash_' . time()));
    // Test 2: Same file_hash → must fail (duplicate image)
    $dup2 = InvoiceEngine::uploadProof(999, 'other_' . time() . '.jpg', $fileHash);
    return [
        'ok'              => !($dup1['success'] ?? true) && !($dup2['success'] ?? true),
        'dup_invoice_rejected' => !($dup1['success']??true),
        'dup_hash_rejected'    => !($dup2['success']??true),
        'dup1_error'      => $dup1['error'] ?? null,
        'dup2_error'      => $dup2['error'] ?? null,
    ];
});

// ══ 7. IDEMPOTENCY — DUPLICATE REFERENCE CODE ════════════════════
$step('07_idempotency_refcode', function() use ($userId, $refCode) {
    $r = InvoiceEngine::create($userId, 'legal', 500.00, ['test'=>'dup_test']);
    $sameRef = db()->query(
        "SELECT reference_code FROM invoices WHERE user_id=$userId AND service='legal'
         ORDER BY id DESC LIMIT 2"
    )->fetchAll(PDO::FETCH_COLUMN);
    return [
        'ok'           => ($r['reused'] ?? false) || ($r['invoice_id'] ?? 0) > 0,
        'reused_existing' => $r['reused'] ?? false,
        'invoice_id'   => $r['invoice_id'] ?? null,
        'reference_codes_for_user' => $sameRef,
    ];
});

// ══ 8. PAYMENT APPROVAL (FinancialAgent) ══════════════════════════
$step('08_payment_approval', function() use ($invoiceId, $userId) {
    if (!$invoiceId) return ['ok'=>false,'error'=>'No invoice'];
    // Mark as proof_uploaded so approval can proceed
    db()->prepare("UPDATE invoices SET status='proof_uploaded' WHERE id=?")
        ->execute([$invoiceId]);
    $ledger_before = (int)db()->query("SELECT COUNT(*) FROM ledger")->fetchColumn();
    $r = FinancialAgent::confirmPayment($invoiceId, 1);
    $ledger_after  = (int)db()->query("SELECT COUNT(*) FROM ledger")->fetchColumn();
    return [
        'ok'             => $r['success'] ?? false,
        'result'         => $r,
        'ledger_entries_created' => $ledger_after - $ledger_before,
    ];
});

// ══ 9. LEDGER ENTRIES ═════════════════════════════════════════════
$step('09_ledger_entries', function() use ($invoiceId) {
    if (!$invoiceId) return ['ok'=>false,'error'=>'No invoice'];
    $entries = db()->query(
        "SELECT l.id, a.code, a.name, l.debit, l.credit, l.description, l.created_at
         FROM ledger l
         JOIN accounts a ON a.id = l.account_id
         WHERE l.reference_type='invoice' AND l.reference_id=$invoiceId
         ORDER BY l.id"
    )->fetchAll(PDO::FETCH_ASSOC);
    $totalDebit  = array_sum(array_column($entries, 'debit'));
    $totalCredit = array_sum(array_column($entries, 'credit'));
    return [
        'ok'           => count($entries) >= 4 && abs($totalDebit - $totalCredit) < 0.01,
        'count'        => count($entries),
        'total_debit'  => $totalDebit,
        'total_credit' => $totalCredit,
        'balanced'     => abs($totalDebit - $totalCredit) < 0.01,
        'entries'      => $entries,
    ];
});

// ══ 10. DUPLICATE PAYMENT ATTEMPT ════════════════════════════════
$step('10_dup_payment', function() use ($invoiceId) {
    if (!$invoiceId) return ['ok'=>false,'error'=>'No invoice'];
    $r = FinancialAgent::confirmPayment($invoiceId, 1);
    return [
        'ok'       => !($r['success'] ?? true),
        'rejected' => !($r['success'] ?? true),
        'error'    => $r['error'] ?? null,
    ];
});

// ══ 11. GLOBAL LEDGER BALANCE ════════════════════════════════════
$step('11_ledger_balance', function() {
    $row = db()->query(
        "SELECT COALESCE(SUM(debit),0) AS total_debit,
                COALESCE(SUM(credit),0) AS total_credit
         FROM ledger"
    )->fetch(PDO::FETCH_ASSOC);
    $diff = round(abs((float)$row['total_debit'] - (float)$row['total_credit']), 2);
    return [
        'ok'           => $diff < 0.01,
        'total_debit'  => (float)$row['total_debit'],
        'total_credit' => (float)$row['total_credit'],
        'difference'   => $diff,
        'balanced'     => $diff < 0.01,
    ];
});

// ══ 12. EVENTBUS → QUEUE ═════════════════════════════════════════
$step('12_eventbus_queue', function() use ($invoiceId, $userId) {
    $before = (int)db()->query("SELECT COUNT(*) FROM tasks WHERE status='pending'")->fetchColumn();
    EventBus::emit('payment.confirmed', [
        'user_id'    => $userId,
        'invoice_id' => $invoiceId,
        'amount'     => 500.00,
    ]);
    $after = (int)db()->query("SELECT COUNT(*) FROM tasks WHERE status='pending'")->fetchColumn();
    $task  = db()->query("SELECT id,type,status,created_at FROM tasks ORDER BY id DESC LIMIT 1")
                  ->fetch(PDO::FETCH_ASSOC);
    return [
        'ok'           => $after > $before,
        'tasks_before' => $before,
        'tasks_after'  => $after,
        'latest_task'  => $task,
    ];
});

// ══ 13. WORKER EXECUTION (INLINE SYNC) ═══════════════════════════
$step('13_worker_inline', function() {
    require_once __DIR__ . '/engine/DecisionEngine.php';
    require_once __DIR__ . '/engine/PolicyEngine.php';
    require_once __DIR__ . '/engine/ControlEngine.php';
    require_once __DIR__ . '/engine/TaskEngine.php';
    require_once __DIR__ . '/engine/GrowthBrain.php';
    require_once __DIR__ . '/engine/SupportEngines.php';
    require_once __DIR__ . '/engine/FinancialAgent.php';
    require_once __DIR__ . '/engine/BehaviorEngine.php';

    $tasks     = QueueEngine::fetch(5);
    $processed = 0; $errors = [];
    foreach ($tasks as $task) {
        try {
            $payload = json_decode($task['payload'], true) ?? [];
            if ($task['type'] === 'event') {
                $event = $payload['event'] ?? '';
                unset($payload['event']);
                if ($event) { AIOrchestrator::run($event, $payload); $processed++; }
            }
            QueueEngine::done((int)$task['id']);
        } catch (Throwable $e) {
            QueueEngine::fail((int)$task['id'], $e->getMessage());
            $errors[] = $e->getMessage();
        }
    }
    $done_count = (int)db()->query(
        "SELECT COUNT(*) FROM tasks WHERE status='done'"
    )->fetchColumn();
    $stuck = (int)db()->query(
        "SELECT COUNT(*) FROM tasks WHERE status='processing'
         AND updated_at < DATE_SUB(NOW(), INTERVAL 10 MINUTE)"
    )->fetchColumn();
    $all_stats = db()->query(
        "SELECT status, COUNT(*) as cnt FROM tasks GROUP BY status"
    )->fetchAll(PDO::FETCH_ASSOC);
    return [
        'ok'             => $processed >= 0 && $stuck === 0,
        'fetched'        => count($tasks),
        'processed'      => $processed,
        'done_total'     => $done_count,
        'stuck_tasks'    => $stuck,
        'task_stats'     => $all_stats,
        'errors'         => $errors,
    ];
});

// ══ 14. AI DECISIONS WRITTEN ══════════════════════════════════════
$step('14_ai_decisions', function() {
    $recent = db()->query(
        "SELECT id,event,score,created_at FROM ai_decisions ORDER BY id DESC LIMIT 5"
    )->fetchAll(PDO::FETCH_ASSOC);
    return [
        'ok'     => count($recent) > 0,
        'count'  => count($recent),
        'recent' => $recent,
    ];
});

// ══ 15. NOTIFICATIONS CREATED ════════════════════════════════════
$step('15_notifications', function() use ($userId) {
    $recent = db()->query(
        "SELECT id,type,title,created_at FROM notifications
         WHERE user_id=$userId ORDER BY id DESC LIMIT 5"
    )->fetchAll(PDO::FETCH_ASSOC);
    return [
        'ok'     => count($recent) >= 0,
        'count'  => count($recent),
        'recent' => $recent,
    ];
});

// ══ 16. WORKER LOG FILE ═══════════════════════════════════════════
$step('16_worker_logs', function() {
    $log_paths = [
        '/home/saiadmin/logs/worker.log',
        '/tmp/worker.log',
        sys_get_temp_dir() . '/worker.log',
    ];
    foreach ($log_paths as $lp) {
        if (file_exists($lp)) {
            $lines = array_slice(file($lp), -10);
            return ['ok'=>true, 'log_path'=>$lp, 'last_10_lines'=>$lines];
        }
    }
    return ['ok'=>false, 'error'=>'No worker.log found — cron may not be active yet',
             'searched_paths' => $log_paths];
});

// ══ 17. GATEWAY LIVE TEST ═════════════════════════════════════════
$step('17_gateway_test', function() {
    $r = Gateway::handle([
        'question' => 'محتاج محامي',
        'user'     => null,
        'ip'       => '127.0.0.1',
    ]);
    return [
        'ok'      => !empty($r['answer']) || !empty($r['flow']),
        'service' => $r['service'] ?? null,
        'source'  => $r['source'] ?? null,
        'has_flow'=> isset($r['flow']),
        'answer_preview' => mb_substr($r['answer'] ?? '', 0, 100),
    ];
});

// ══ WALLET CHECK ══════════════════════════════════════════════════
$step('18_wallet', function() use ($userId) {
    $w = db()->query("SELECT * FROM wallet WHERE user_id=$userId")->fetch(PDO::FETCH_ASSOC);
    return [
        'ok'      => (bool)$w,
        'wallet'  => $w,
    ];
});

// ══ SUMMARY ═══════════════════════════════════════════════════════
$score = round($pass / max($total,1) * 100);
$proof['summary'] = [
    'passed'      => $pass,
    'total'       => $total,
    'score'       => $score . '%',
    'system_mode' => $score >= 90 ? 'READY FOR PRODUCTION ✅'
                   : ($score >= 70 ? 'READY FOR TEST ⚠️' : 'NOT READY ❌'),
    'failures'    => $proof['failures'],
    'runtime_ms'  => round(microtime(true) * 1000) - (int)($_SERVER['REQUEST_TIME_FLOAT'] * 1000 ?? 0),
];

echo json_encode($proof, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
