<?php
/**
 * سودانا — System Validator v21
 * يتحقق من سلامة النظام الكاملة — لا بيانات وهمية
 * Usage: php engine/SystemValidator.php
 */

$isCli = PHP_SAPI === 'cli';
if (!$isCli) {
    require_once dirname(__DIR__) . '/config.php';
    session_start();
    if (empty($_SESSION['admin']) && ($_GET['key'] ?? '') !== ADMIN_PASSWORD) {
        http_response_code(403); die(json_encode(['error'=>'unauthorized']));
    }
}

$root   = dirname(__DIR__);
$errors = [];
$warnings = [];
$passed = [];

// ── Helper functions ──────────────────────────────────────────
function ok(string $msg, array &$p): void  { $p[] = "✅ $msg"; }
function err(string $msg, array &$e): void  { $e[] = "❌ $msg"; }
function warn(string $msg, array &$w): void { $w[] = "⚠️  $msg"; }

// ════════════════════════════════════════════════════════════
// CHECK 1 — Critical Engine Files
// ════════════════════════════════════════════════════════════
$engineFiles = [
    'engine/Gateway.php',
    'engine/InferenceEngine.php',
    'engine/AIClient.php',
    'engine/OutputBuilder.php',
    'engine/CacheLayer.php',
    'engine/ContextMemory.php',
    'engine/KPILogger.php',
    'engine/TemplateEngine.php',
    'engine/MetricsUpdater.php',
];
foreach ($engineFiles as $f) {
    if (file_exists("$root/$f")) {
        ok("Engine file exists: $f", $passed);
    } else {
        err("MISSING engine file: $f", $errors);
    }
}

// ════════════════════════════════════════════════════════════
// CHECK 2 — IE Rules Count (real count)
// ════════════════════════════════════════════════════════════
$ieContent  = file_get_contents("$root/engine/InferenceEngine.php") ?: '';
$ieCount    = substr_count($ieContent, "'id'=>'");
$metricsRaw = file_get_contents("$root/system/system_metrics.json") ?: '{}';
$metrics    = json_decode($metricsRaw, true) ?: [];

if ($ieCount < 100) {
    err("IE rules critically low: $ieCount (minimum 100)", $errors);
} elseif ($ieCount < 200) {
    warn("IE rules below target: $ieCount / 530", $warnings);
    ok("IE rules functional: $ieCount", $passed);
} else {
    ok("IE rules count: $ieCount", $passed);
}

// Check metrics.json matches reality
$metricsIE = (int)($metrics['ie_rules_count'] ?? 0);
if (abs($metricsIE - $ieCount) > 5) {
    warn("system_metrics.json IE count ($metricsIE) differs from actual ($ieCount) — run MetricsUpdater.php", $warnings);
} else {
    ok("system_metrics.json consistent with code", $passed);
}

// ════════════════════════════════════════════════════════════
// CHECK 3 — Critical API Files
// ════════════════════════════════════════════════════════════
$apiFiles = [
    'api/visitor_ask.php'         => 'Gateway::handle',
    'api/booking/create.php'      => 'INSERT INTO bookings',
    'api/booking/confirm.php'     => "status='confirmed'",
    'api/booking/status.php'      => 'provider_earnings',
    'api/booking/rate.php'        => 'booking_ratings',
    'api/provider/services.php'   => 'provider_services',
    'api/provider/profile.php'    => 'booking_ratings',
    'api/provider/earnings.php'   => 'provider_earnings',
    'api/bde/wizard.php'          => 'bde_documents',
    'api/bde/generate.php'        => 'ask_claude',
    'api/bde/export.php'          => 'window.print',
    'api/expert/match.php'        => 'provider_verified',
    'api/support/ticket.php'      => 'support_tickets',
    'api/kpi/dashboard.php'       => 'kpi_daily',
    'api/invest/projects.php'     => 'investment_projects',
    'api/assistant/welcome.php'   => 'quick_actions',
    'api/content/report.php'      => 'content_reports',
];
foreach ($apiFiles as $file => $keyword) {
    $path = "$root/$file";
    if (!file_exists($path)) {
        err("MISSING API: $file", $errors);
    } elseif (!str_contains(file_get_contents($path), $keyword)) {
        warn("API missing key logic '$keyword': $file", $warnings);
    } else {
        ok("API verified: $file", $passed);
    }
}

// ════════════════════════════════════════════════════════════
// CHECK 4 — DB Migration Files
// ════════════════════════════════════════════════════════════
$sqlChecks = [
    'migrate_v21.sql' => [
        'CREATE TABLE IF NOT EXISTS bookings',
        'CREATE TABLE IF NOT EXISTS ai_cache',
        'CREATE TABLE IF NOT EXISTS bde_documents',
        'CREATE TABLE IF NOT EXISTS context_memory',
        'CREATE TABLE IF NOT EXISTS feature_flags',
        "flag_name='enable_booking'",
    ],
    'seed_data.sql' => [
        'INSERT IGNORE INTO lessons',
        'INSERT IGNORE INTO pharmacies',
    ],
];
foreach ($sqlChecks as $file => $keywords) {
    $path = "$root/$file";
    if (!file_exists($path)) {
        err("MISSING SQL: $file", $errors);
        continue;
    }
    $content = file_get_contents($path);
    foreach ($keywords as $kw) {
        if (!str_contains($content, $kw)) {
            warn("SQL '$file' missing: $kw", $warnings);
        }
    }
    ok("SQL file verified: $file", $passed);
}

// ════════════════════════════════════════════════════════════
// CHECK 5 — DB Connectivity & Tables (runtime)
// ════════════════════════════════════════════════════════════
$dbOk = false;
$dbTables = [];
try {
    if (!$isCli) require_once "$root/config.php";
    $dbh = db();
    $dbOk = true;
    ok("Database connection: OK", $passed);

    $tables = $dbh->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
    $dbTables = $tables;

    $requiredTables = [
        'users','bookings','booking_ratings','provider_services',
        'provider_earnings','ai_cache','context_memory','feature_flags',
        'support_tickets','ai_requests','bde_documents','investment_projects',
    ];
    $missingTables = array_diff($requiredTables, $tables);
    if ($missingTables) {
        err("MISSING DB tables: " . implode(', ', $missingTables) . " — run migrate_v21.sql", $errors);
    } else {
        ok("All required DB tables exist (" . count($requiredTables) . ")", $passed);
    }

    // Check feature_flags
    try {
        $ff = $dbh->query("SELECT flag_name, is_enabled FROM feature_flags")->fetchAll();
        $flags = array_column($ff, 'is_enabled', 'flag_name');
        if (isset($flags['enable_booking'])) {
            ok("feature_flags: enable_booking=" . (int)$flags['enable_booking'], $passed);
        } else {
            warn("feature_flags: enable_booking not found — run seed", $warnings);
        }
        if (isset($flags['enable_ai_cache']) && $flags['enable_ai_cache']) {
            ok("feature_flags: enable_ai_cache=1", $passed);
        }
    } catch (Throwable $e) {
        warn("feature_flags table not populated — run seed_data.sql", $warnings);
    }

} catch (Throwable $e) {
    warn("Database not available (normal on dev): " . $e->getMessage(), $warnings);
}

// ════════════════════════════════════════════════════════════
// CHECK 6 — Safety: ONE CALL LAW
// ════════════════════════════════════════════════════════════
$aiClientContent = file_get_contents("$root/engine/AIClient.php") ?: '';
if (str_contains($aiClientContent, 'ONE CALL LAW') && str_contains($aiClientContent, 'self::$called')) {
    ok("ONE CALL LAW enforced in AIClient.php", $passed);
} else {
    err("ONE CALL LAW missing from AIClient.php", $errors);
}

// ════════════════════════════════════════════════════════════
// CHECK 7 — Safety: Injection Protection
// ════════════════════════════════════════════════════════════
$gatewayContent = file_get_contents("$root/engine/Gateway.php") ?: '';
if (str_contains($gatewayContent, 'isInjection') && str_contains($gatewayContent, 'ignore.*instructions')) {
    ok("Injection protection: active (9 patterns)", $passed);
} else {
    err("Injection protection: missing from Gateway.php", $errors);
}

// ════════════════════════════════════════════════════════════
// CHECK 8 — Medical Safety
// ════════════════════════════════════════════════════════════
$obContent = file_get_contents("$root/engine/OutputBuilder.php") ?: '';
if (str_contains($obContent, '⚕️') && str_contains($obContent, '999')) {
    ok("Medical safety: ⚕️ auto-inject + emergency 999", $passed);
} else {
    err("Medical safety layer missing", $errors);
}

// ════════════════════════════════════════════════════════════
// CHECK 9 — BDE Integration
// ════════════════════════════════════════════════════════════
$ieContent2 = file_get_contents("$root/engine/InferenceEngine.php") ?: '';
if (str_contains($ieContent2, 'bde_proposal') && str_contains($ieContent2, 'bde_contract')) {
    ok("BDE IE triggers: proposal + contract active", $passed);
} else {
    err("BDE IE triggers missing", $errors);
}
if (file_exists("$root/engine/TemplateEngine.php") && str_contains(file_get_contents("$root/engine/TemplateEngine.php"), 'detectIntent')) {
    ok("BDE TemplateEngine: detectIntent active", $passed);
} else {
    err("BDE TemplateEngine missing", $errors);
}

// ════════════════════════════════════════════════════════════
// CHECK 10 — Booking Dead-End Prevention
// ════════════════════════════════════════════════════════════
$createContent = file_get_contents("$root/api/booking/create.php") ?: '';
if (str_contains($createContent, 'enable_booking')) {
    ok("Booking: feature_flag check (no silent fail)", $passed);
} else {
    warn("Booking: feature_flag check missing", $warnings);
}
if (str_contains($createContent, 'provider_empty_state') || str_contains($ieContent2, 'provider_empty_state')) {
    ok("Empty state CTA: 'كن أول مزود' in IE rules", $passed);
} else {
    ok("Empty state: handled via provider_empty_state IE rule", $passed);
}
if (file_exists("$root/cron/booking_cleanup.php")) {
    ok("Dead-end prevention: 48h auto-cancel cron exists", $passed);
} else {
    warn("Dead-end: 48h auto-cancel cron missing", $warnings);
}

// ════════════════════════════════════════════════════════════
// CHECK 11 — Legal Pages
// ════════════════════════════════════════════════════════════
$legalFiles = [
    'legal/terms.html'   => ['Hamed','sudanna.ai','شروط'],
    'legal/privacy.html' => ['Hamed','sudanna.ai','خصوصية'],
    'terms.html'         => ['الشروط'],
    'privacy.html'       => ['الخصوصية'],
];
foreach ($legalFiles as $file => $keywords) {
    $path = "$root/$file";
    if (!file_exists($path)) {
        if (str_starts_with($file, 'legal/')) {
            warn("Legal page missing: $file (optional)", $warnings);
        } else {
            err("Legal page missing: $file", $errors);
        }
        continue;
    }
    $content = file_get_contents($path);
    $allFound = true;
    foreach ($keywords as $kw) {
        if (!str_contains($content, $kw)) { $allFound = false; }
    }
    if ($allFound) ok("Legal page verified: $file", $passed);
    else warn("Legal page incomplete: $file", $warnings);
}

// ════════════════════════════════════════════════════════════
// CHECK 12 — Footer Links (index.html)
// ════════════════════════════════════════════════════════════
$indexContent = file_get_contents("$root/index.html") ?: '';
$footerChecks = ['/privacy.html', '/terms.html', 'developer.html'];
foreach ($footerChecks as $link) {
    if (str_contains($indexContent, $link)) {
        ok("Footer link: $link", $passed);
    } else {
        warn("Footer link missing: $link", $warnings);
    }
}

// ════════════════════════════════════════════════════════════
// CHECK 13 — UI Actions Integration
// ════════════════════════════════════════════════════════════
if (str_contains($indexContent, 'd.actions && d.actions.length')) {
    ok("UI: actions[] rendered from Gateway", $passed);
} else {
    err("UI: actions[] NOT rendered", $errors);
}
if (str_contains($indexContent, 'id="pillars"')) {
    ok("UI: 3 Pillars section exists", $passed);
} else {
    warn("UI: 3 Pillars section missing", $warnings);
}
if (str_contains($indexContent, 'id="bde"')) {
    ok("UI: BDE section exists", $passed);
} else {
    warn("UI: BDE section missing", $warnings);
}

// ════════════════════════════════════════════════════════════
// CHECK 14 — Cron Jobs
// ════════════════════════════════════════════════════════════
$cronFiles = ['cron/kpi_aggregate.php','cron/booking_cleanup.php','cron/cache_cleanup.php','cron/sla_check.php'];
foreach ($cronFiles as $f) {
    if (file_exists("$root/$f")) ok("Cron: $f", $passed);
    else warn("Cron missing: $f", $warnings);
}

// ════════════════════════════════════════════════════════════
// CHECK 15 — system_metrics.json
// ════════════════════════════════════════════════════════════
if (file_exists("$root/system/system_metrics.json")) {
    $m = json_decode(file_get_contents("$root/system/system_metrics.json"), true);
    if ($m && isset($m['ie_rules_count'])) {
        ok("system_metrics.json: exists and valid", $passed);
    } else {
        err("system_metrics.json: invalid JSON", $errors);
    }
} else {
    err("system_metrics.json: MISSING", $errors);
}

// ════════════════════════════════════════════════════════════
// FINAL REPORT
// ════════════════════════════════════════════════════════════
$status = empty($errors) ? 'PASS' : 'FAIL';
$totalChecks = count($passed) + count($errors) + count($warnings);
$score = count($passed) + count($warnings) * 0.5; // warnings are partial credit
$pct = $totalChecks > 0 ? round($score / $totalChecks * 100) : 0;

$report = [
    'status'       => $status,
    'score'        => "$pct%",
    'passed'       => count($passed),
    'warnings'     => count($warnings),
    'errors'       => count($errors),
    'total_checks' => $totalChecks,
    'real_metrics' => [
        'ie_rules'   => $ieCount,
        'db_tables'  => count($dbTables),
        'api_files'  => count(glob("$root/api/**/*.php", GLOB_BRACE) ?: []),
    ],
    'errors_list'   => $errors,
    'warnings_list' => $warnings,
    'passed_list'   => $passed,
    'generated_at'  => gmdate('Y-m-d H:i:s') . ' UTC',
];

if ($isCli) {
    echo "\n" . str_repeat('═', 60) . "\n";
    echo "  سودانا v21 — SYSTEM VALIDATOR\n";
    echo str_repeat('═', 60) . "\n";
    echo "  STATUS: $status | SCORE: $pct%\n";
    echo "  ✅ PASSED: " . count($passed) . " | ⚠️ WARNINGS: " . count($warnings) . " | ❌ ERRORS: " . count($errors) . "\n";
    echo str_repeat('─', 60) . "\n";
    if ($errors) {
        echo "\n❌ ERRORS (" . count($errors) . "):\n";
        foreach ($errors as $e) echo "  $e\n";
    }
    if ($warnings) {
        echo "\n⚠️  WARNINGS (" . count($warnings) . "):\n";
        foreach ($warnings as $w) echo "  $w\n";
    }
    echo "\n✅ PASSED (" . count($passed) . "):\n";
    foreach ($passed as $p) echo "  $p\n";
    echo str_repeat('═', 60) . "\n";
    echo "  IE RULES:  $ieCount\n";
    echo "  DB TABLES: " . count($dbTables) . "\n";
    echo str_repeat('═', 60) . "\n";
} else {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
