<?php
error_reporting(0);
ini_set('display_errors', 0);

// ── Environment Loader ────────────────────────────────────────
// Secrets are loaded from .env (NOT from code)
// .env must exist in root and must NOT be in version control
if (file_exists(__DIR__ . '/.env')) {
    require_once __DIR__ . '/env_loader.php';
}

// ── Database ─────────────────────────────────────────────────
define('DB_HOST',    $_ENV['DB_HOST']    ?? 'localhost');
define('DB_NAME',    $_ENV['DB_NAME']    ?? 'saiadmin_sudb999');
define('DB_USER',    $_ENV['DB_USER']    ?? 'saiadmin_sudb999');
define('DB_PASS',    $_ENV['DB_PASS']    ?? '');   // ← must be in .env
define('DB_CHARSET', 'utf8mb4');

// ── Site ──────────────────────────────────────────────────────
define('SITE_URL',  $_ENV['SITE_URL']  ?? 'https://sudanna.ai'); // root by default
define('FCM_SERVER_KEY', $_ENV['FCM_SERVER_KEY'] ?? ''); // optional
define('SITE_NAME', 'سودانا');

// ── Auth ──────────────────────────────────────────────────────
define('JWT_SECRET',     $_ENV['JWT_SECRET']     ?? '');  // ← must be in .env
define('ADMIN_PASSWORD', $_ENV['ADMIN_PASSWORD'] ?? '');  // ← must be in .env
define('TRACE_ENABLED',    false);  // FIX 7: set true on production for debugging

// ── Subscription Plan Limits ──────────────────────────────────

// ── PRICING & LIMITS — DB Primary, PHP Constants as Fallback ──────────
// These values are stored in platform_settings (DB) — admin-configurable.
// PHP constants below serve as fallback if DB is unavailable.
// DO NOT remove — getSetting() uses defined() to read them as fallback.
// ─────────────────────────────────────────────────────────────────────
// [PRICING — DB primary, PHP fallback] define('AI_DAILY_LIMIT_FREE',  20);   // FREE: 20 سؤال/يوم
// [PRICING — DB primary, PHP fallback] define('AI_DAILY_LIMIT_PLUS',  60);   // PLUS: 60 سؤال/يوم
// [PRICING — DB primary, PHP fallback] define('AI_DAILY_LIMIT_PRO',   200);  // PRO: 200 سؤال/يوم
// [PRICING — DB primary, PHP fallback] define('AI_DAILY_LIMIT_PAID',  100);  // legacy compat
// [PRICING — DB primary, PHP fallback] define('AI_DAILY_LIMIT_GUEST', 5);    // زوار: 5/يوم

// [PRICING — DB primary, PHP fallback] define('BOOKING_DAILY_LIMIT_FREE', 2);   // FREE: 2 حجز/يوم
// [PRICING — DB primary, PHP fallback] define('BOOKING_DAILY_LIMIT_PLUS', 5);   // PLUS: 5 حجز/يوم
// [PRICING — DB primary, PHP fallback] define('BOOKING_DAILY_LIMIT_PRO',  20);  // PRO: 20 حجز/يوم
define('SESSION_LIFETIME', 2592000); // 30 يوم

// ── Gemini AI ─────────────────────────────────────────────────
define('GEMINI_API_KEY',  $_ENV['GEMINI_API_KEY'] ?? '');  // ← set in .env
define('GEMINI_MODEL',    'gemini-1.5-flash');   // v20: fixed — 2.0-flash deprecated (404)
define('GEMINI_FALLBACK', 'gemini-1.5-pro');    // v20: pro as fallback for quality
define('GEMINI_ENDPOINT', 'https://generativelanguage.googleapis.com/v1beta/models/');
define('GEMINI_TIMEOUT',  30);

// ── Claude AI ─────────────────────────────────────────────────
define('CLAUDE_API_KEY',    $_ENV['CLAUDE_API_KEY'] ?? '');    // ← set in .env
define('CLAUDE_MODEL',      'claude-haiku-4-5-20251001');
define('CLAUDE_MODEL_SMART','claude-sonnet-4-5-20251001');
define('CLAUDE_ENDPOINT',   'https://api.anthropic.com/v1/messages');
define('CLAUDE_VERSION',    '2023-06-01');
define('CLAUDE_TIMEOUT',    45);

// ── OpenAI GPT-4o mini ────────────────────────────────────────
define('OPENAI_API_KEY',    $_ENV['OPENAI_API_KEY'] ?? '');    // ← set in .env
define('OPENAI_MODEL',      'gpt-4o-mini');
define('OPENAI_ENDPOINT',   'https://api.openai.com/v1/chat/completions');
define('OPENAI_TIMEOUT',    45);

// ── سياسة الاستخدام العادل ────────────────────────────────────
// Inference Engine → Gemini Flash → Claude Haiku (بهذا الترتيب)

// ── FCM Push ──────────────────────────────────────────────────
define('FCM_PROJECT_ID',          'sudanna26-d9fec');
define('FCM_SERVICE_ACCOUNT_PATH','/secure/sudanna26-d9fec-firebase-adminsdk-fbsvc-2cc8ab28dc.json');
define('FCM_SENDER_ID',           '1012255287874');

// ── Uploads ───────────────────────────────────────────────────
define('UPLOAD_DIR',    __DIR__ . '/uploads/');
define('UPLOAD_URL',    SITE_URL . '/uploads/');
define('MAX_UPLOAD_MB',     5);
define('IMAGE_QUALITY',     75);   // جودة ضغط الصور (0-100)
define('IMAGE_MAX_W',       900);  // أقصى عرض للصور
define('IMAGE_MAX_H',       700);  // أقصى ارتفاع
define('THUMB_W',           320);  // عرض الـ thumbnail
define('THUMB_H',           240);  // ارتفاع الـ thumbnail

// ── Limits ────────────────────────────────────────────────────
define('FREE_LESSONS_PER_WEEK',  2);
define('FREE_MARKET_ITEMS',      5);
define('FREE_FAMILY_MEMBERS',    1);
define('PAID_PRICE_SDG',         10000); // 10,000 جنيه سوداني/شهر

// ── SUDANNA PAY — E-Wallet Configuration ─────────────────────────
// ── Webhook Security ──────────────────────────────────────────────
define('BANK_INTEGRATION_ENABLED', filter_var(getenv('BANK_INTEGRATION_ENABLED') ?: 'false', FILTER_VALIDATE_BOOLEAN));
define('BANK_API_URL',             getenv('BANK_API_URL') ?: '');
define('BANK_API_KEY',             getenv('BANK_API_KEY') ?: '');
define('WEBHOOK_SECRET',      getenv('WEBHOOK_SECRET') ?: hash('sha256', JWT_SECRET . '_wh'));
define('APP_ENV',             getenv('APP_ENV') ?: 'production');

// [PRICING — DB primary, PHP fallback] define('PAY_COMMISSION_RATE',    0.10);    // 10% على كل حجز
// [PRICING — DB primary, PHP fallback] define('PAY_AGENT_RATE',         0.01);    // 1% للوكيل
// [PRICING — DB primary, PHP fallback] define('PAY_DAILY_LIMIT_FREE',   5000);    // SDG يومياً للمجاني
// [PRICING — DB primary, PHP fallback] define('PAY_DAILY_LIMIT_PLUS',   50000);   // SDG يومياً للبلاس
// [PRICING — DB primary, PHP fallback] define('PAY_MONTHLY_LIMIT',      200000);  // SDG شهرياً
define('PAY_MIN_TOPUP',          100);     // أقل شحن 100 SDG
define('PAY_BANK_ACCOUNT',       '1821425'); // بنك الخرطوم
define('PAY_BANK_NAME',          'بنك الخرطوم');
define('PAY_ACCOUNT_HOLDER',     'حامد مختار');
// [PRICING — DB primary, PHP fallback] define('PARTNER_RATE_LIMIT_DAY', 500);
// [PRICING — DB primary, PHP fallback] define('RATE_LIMIT_PER_MIN',     30);
define('DEV_MODE',               false);

// ── محفظة سودانا ──────────────────────────────────────────────
define('POINTS_EXCHANGE_RATE',   0.10);
define('POINTS_MEDICATION_HELP', 50);
define('POINTS_QUIZ_EXCELLENT',  20);
define('HEALTH_EMERGENCY_MODE',  true);
define('MARKET_AI_VERIFICATION', true);
define('ACADEMY_AI_SUMMARIES',   true);

// ── Session ───────────────────────────────────────────────────
function start_secure_session(): void {
    if (session_status() === PHP_SESSION_NONE) {
        // ── Cookie path: derived from SITE_URL — works for / or /subdir/
        $_sess_path = parse_url(SITE_URL, PHP_URL_PATH);
        $_sess_path = ($_sess_path && $_sess_path !== '') ? rtrim($_sess_path, '/') . '/' : '/';
        session_set_cookie_params([
            'lifetime' => SESSION_LIFETIME,
            'path'     => $_sess_path,
            'secure'   => true,
            'httponly' => true,
            'samesite' => 'Lax',
        ]);
        unset($_sess_path);
        session_start();
    }
}

// ── Database ──────────────────────────────────────────────────
function db(): PDO {
    static $pdo = null;
    if ($pdo) return $pdo;
    try {
        $dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=' . DB_CHARSET;
        $pdo = new PDO($dsn, DB_USER, DB_PASS, [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES   => false,
        ]);
    } catch (PDOException $e) {
        // Log but don't die — allow admin to see error page instead of crash
        error_log('[DB] Connection failed: ' . $e->getMessage());
        if (php_sapi_name() === 'cli') die('DB Error: ' . $e->getMessage());
        // For web: throw to caller so they can handle gracefully
        throw new RuntimeException('قاعدة البيانات غير متاحة مؤقتاً — حاول لاحقاً', 503);
    }
    return $pdo;
}

// ── JSON Response ─────────────────────────────────────────────
function json_response(array $data, int $code = 200): void {
    http_response_code($code);
    header('Content-Type: application/json; charset=utf-8');
    header('X-Content-Type-Options: nosniff');
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

// ── Current User ──────────────────────────────────────────────

// ── URL helpers (use these instead of hardcoded paths) ─────────
function url(string $path = ''): string {
    $base = rtrim(SITE_URL, '/');
    $path = '/' . ltrim($path, '/');
    return $base . $path;
}

function path(string $rel = ''): string {
    // Returns the URL path portion (e.g. '/api/health.php')
    $u = parse_url(SITE_URL, PHP_URL_PATH) ?: '';
    return rtrim($u, '/') . '/' . ltrim($rel, '/');
}

function current_user(): ?array {
    start_secure_session();
    if (empty($_SESSION['user_id']) || empty($_SESSION['session_token'])) return null;
    try {
        $st = db()->prepare(
            'SELECT u.* FROM users u
             JOIN sessions s ON s.user_id = u.id
             WHERE u.id = ? AND s.token = ? AND s.expires_at > NOW() LIMIT 1'
        );
        $st->execute([$_SESSION['user_id'], hash('sha256', $_SESSION['session_token'])]);
        return $st->fetch() ?: null;
    } catch (Throwable $e) {
        return null;
    }
}

function require_auth(): array {
    $u = current_user();
    if (!$u) json_response(['error' => 'unauthorized'], 401);
    return $u;
}

function require_partner(): array {
    $key = $_SERVER['HTTP_X_PARTNER_KEY'] ?? '';
    if (!$key) json_response(['error' => 'partner_key_required'], 401);
    $st = db()->prepare('SELECT * FROM partners WHERE api_key = ? AND active = 1 LIMIT 1');
    $st->execute([hash('sha256', $key)]);
    $p = $st->fetch();
    if (!$p) json_response(['error' => 'invalid_partner_key'], 403);
    return $p;
}

// ── Rate Limit ────────────────────────────────────────────────
function check_rate_limit(string $key, int $max, int $window_sec): bool {
    $k = hash('sha256', $key); // FIX 4: aligned with schema_fix.sql key_hash column
    try {
        if (rand(1, 100) === 1) {
            try { db()->exec('DELETE FROM rate_limits WHERE window_end < NOW()'); } catch(Throwable $ignored){}
        }
        db()->prepare(
            'INSERT INTO rate_limits (key_hash, count, window_end)
             VALUES (?, 1, DATE_ADD(NOW(), INTERVAL ? SECOND))
             ON DUPLICATE KEY UPDATE count = count + 1'
        )->execute([$k, $window_sec]);
        $row = db()->prepare('SELECT count FROM rate_limits WHERE key_hash = ?');
        $row->execute([$k]);
        return (int)($row->fetchColumn() ?: 0) <= $max;
    } catch (Throwable $e) {
        error_log('[rate_limit] DB error: ' . $e->getMessage());
        return true;
    }
}

// ── Notifications: save internal notification ─────────────────
function save_notification(int $user_id, string $type, string $title, string $body = '', array $data = []): void {
    try {
        db()->prepare(
            'INSERT INTO notifications (user_id, type, title, body, data) VALUES (?,?,?,?,?)'
        )->execute([$user_id, $type, $title, $body, $data ? json_encode($data, JSON_UNESCAPED_UNICODE) : null]);
    } catch (Throwable $ignored) {}
}

// ── AI Logging ────────────────────────────────────────────────
function _log_ai(string $service, ?int $user_id = null): void {
    try {
        db()->prepare('INSERT INTO ai_logs (user_id, service) VALUES (?, ?)')
            ->execute([$user_id, $service]);
    } catch (Throwable $ignored) {}
}

// ── Gemini: HTTP call ─────────────────────────────────────────
function _gemini_call(array $payload, string $model): array {
    $url = GEMINI_ENDPOINT . $model . ':generateContent?key=' . GEMINI_API_KEY;
    $ch  = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => GEMINI_TIMEOUT,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    ]);
    $raw  = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $cerr = curl_error($ch);
    curl_close($ch);
    // v20: Enhanced error logging (per Technical Report recommendation)
    if ($http !== 200 || $cerr) {
        error_log("[Gemini] HTTP={$http} MODEL={$model} ERR={$cerr} RESPONSE=" . substr($raw ?? '', 0, 200));
    }
    return [
        'raw'  => (string)$raw,
        'http' => $http,
        'err'  => $cerr,
        'data' => $raw ? (json_decode($raw, true) ?? []) : [],
    ];
}

// ── Gemini: build payload ─────────────────────────────────────
function _gemini_payload(
    string $prompt,
    string $system = '',
    array  $history = [],
    int    $max_tokens = 500,
    float  $temperature = 0.7,
    bool   $safe = false
): array {
    $contents = [];
    foreach ($history as $turn) {
        if (!empty($turn['role']) && !empty($turn['text']))
            $contents[] = ['role' => $turn['role'], 'parts' => [['text' => $turn['text']]]];
    }
    $contents[] = ['role' => 'user', 'parts' => [['text' => $prompt]]];
    $p = [
        'contents'         => $contents,
        'generationConfig' => ['maxOutputTokens' => $max_tokens, 'temperature' => $temperature],
    ];
    if ($system) $p['system_instruction'] = ['parts' => [['text' => $system]]];
    if ($safe) {
        $p['safetySettings'] = [
            ['category' => 'HARM_CATEGORY_HARASSMENT',        'threshold' => 'BLOCK_ONLY_HIGH'],
            ['category' => 'HARM_CATEGORY_HATE_SPEECH',       'threshold' => 'BLOCK_ONLY_HIGH'],
            ['category' => 'HARM_CATEGORY_SEXUALLY_EXPLICIT', 'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'],
            ['category' => 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold' => 'BLOCK_ONLY_HIGH'],
        ];
    }
    return $p;
}

// ── ask_gemini: main function ─────────────────────────────────
function ask_gemini(
    string $prompt,
    string $system = '',
    array  $history = [],
    int    $max_tokens = 500,
    float  $temperature = 0.7,
    bool   $safe = false
): string {
    if (!GEMINI_API_KEY || !trim($prompt)) return '';
    $payload = _gemini_payload($prompt, $system, $history, $max_tokens, $temperature, $safe);
    foreach ([GEMINI_MODEL, GEMINI_FALLBACK] as $model) {
        $r = _gemini_call($payload, $model);
        error_log("[Gemini/$model] http={$r['http']} err={$r['err']} prefix=" . substr($r['raw'], 0, 80));
        if ($r['err'] || !$r['raw']) continue;
        if (in_array($r['http'], [400, 404])) continue;
        if ($r['http'] === 429)               continue;
        if (isset($r['data']['error']))       continue;
        $text = trim($r['data']['candidates'][0]['content']['parts'][0]['text'] ?? '');
        if ($text) return $text;
    }
    return '';
}

// ── Image Validation ──────────────────────────────────────────
function validate_image_base64(string $b64, int $max_mb = 5): array {
    $pure    = preg_replace('/^data:image\/\w+;base64,/', '', $b64);
    $decoded = base64_decode($pure, true);
    if ($decoded === false || strlen($decoded) < 8)
        return ['ok' => false, 'error' => 'invalid_base64'];
    if (strlen($decoded) > $max_mb * 1024 * 1024)
        return ['ok' => false, 'error' => 'image_too_large', 'max_mb' => $max_mb];

    $magic = substr($decoded, 0, 12);
    $ext   = null;
    if (substr($magic, 0, 3) === "\xFF\xD8\xFF")                                  $ext = 'jpg';
    elseif (substr($magic, 0, 8) === "\x89PNG\r\n\x1a\n")                          $ext = 'png';
    elseif (substr($magic, 0, 4) === 'RIFF' && substr($decoded, 8, 4) === 'WEBP') $ext = 'webp';
    if (!$ext) return ['ok' => false, 'error' => 'unsupported_format'];

    $mime_map     = ['jpg' => 'image/jpeg', 'png' => 'image/png', 'webp' => 'image/webp'];
    $actual_mime  = $mime_map[$ext];
    if (function_exists('finfo_open')) {
        $fi          = finfo_open(FILEINFO_MIME_TYPE);
        $actual_mime = finfo_buffer($fi, $decoded);
        finfo_close($fi);
        if ($actual_mime !== $mime_map[$ext])
            return ['ok' => false, 'error' => 'mime_mismatch', 'got' => $actual_mime];
    }

    // EXIF stripping for JPEG (polyglot defense)
    $clean = $decoded;
    if ($ext === 'jpg' && function_exists('imagecreatefromstring') && function_exists('imagejpeg')) {
        $img = @imagecreatefromstring($decoded);
        if ($img !== false) {
            ob_start(); imagejpeg($img, null, 90); $clean = ob_get_clean(); imagedestroy($img);
            $pure = base64_encode($clean);
        }
    }
    return ['ok' => true, 'ext' => $ext, 'mime' => $actual_mime, 'pure' => $pure, 'data' => $clean, 'size' => strlen($clean)];
}

// ── Save image from base64 ────────────────────────────────────
function save_uploaded_image(string $b64): ?string {
    $check = validate_image_base64($b64, MAX_UPLOAD_MB);
    if (!$check['ok']) return null;
    $fname = uniqid('img_', true) . '.' . $check['ext'];
    if (!is_dir(UPLOAD_DIR)) mkdir(UPLOAD_DIR, 0755, true);
    file_put_contents(UPLOAD_DIR . $fname, $check['data']);
    return UPLOAD_URL . $fname;
}

// ── Email: send notification to user ─────────────────────────
// ── Finance email — always uses finance@sudanna.ai ──────────────────
function send_finance_email(string $to, string $name, string $subject, string $html): bool {
    $headers  = "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html; charset=utf-8\r\n";
    $headers .= "From: سودانا المالية <finance@sudanna.ai>\r\n";
    $headers .= "Reply-To: finance@sudanna.ai\r\n";
    $encodedSubject = '=?utf-8?B?' . base64_encode($subject) . '?=';
    $sent = @mail($to, $encodedSubject, $html, $headers);
    if (!$sent) error_log("[finance_email] Failed: to=$to subject=$subject");
    return (bool)$sent;
}

function send_email(string $to, string $name, string $subject, string $html_body): bool {
    $encoded_subject = '=?utf-8?B?' . base64_encode($subject) . '?=';
    $headers  = "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html; charset=utf-8\r\n";
    $headers .= "From: " . SITE_NAME . " <no-reply@sudanna.ai>\r\n";
    $headers .= "Reply-To: no-reply@sudanna.ai\r\n";
    $headers .= "X-Mailer: PHP/" . PHP_VERSION . "\r\n";
    return @mail($to, $encoded_subject, $html_body, $headers);
}

function send_password_changed_email(string $to, string $name): void {
    $subject = 'تم تغيير كلمة المرور — سودانا';
    $html = '<!DOCTYPE html><html dir="rtl" lang="ar"><head><meta charset="utf-8">
<style>body{font-family:Arial,sans-serif;background:#f4f4f4;margin:0;padding:20px}
.box{background:#fff;max-width:480px;margin:0 auto;border-radius:12px;padding:32px;text-align:center}
.logo{font-size:1.5rem;font-weight:900;color:#073328;margin-bottom:8px}
.alert{background:#fff3e0;border:1px solid #ffb74d;border-radius:10px;padding:16px;margin:20px 0;font-size:.9rem}
</style></head>
<body><div class="box">
<div class="logo">🇸🇩 ' . SITE_NAME . '</div>
<p>مرحباً ' . htmlspecialchars($name) . '،</p>
<div class="alert">⚠️ تم تغيير كلمة المرور لحسابك مؤخراً.<br>إذا لم تقم بذلك بنفسك، تواصل معنا فوراً.</div>
<p style="font-size:.85rem;color:#888">وقت التغيير: ' . date('Y-m-d H:i:s') . '</p>
</div></body></html>';
    send_email($to, $name, $subject, $html);
}

// ── FCM: base64url ────────────────────────────────────────────
function _b64url(string $data): string {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function _fcm_token(): string {
    $cache = '/tmp/sudanna_fcm_token.json';
    if (file_exists($cache)) {
        $d = json_decode(file_get_contents($cache), true);
        if (isset($d['token'], $d['exp']) && time() < $d['exp']) return $d['token'];
    }
    if (!file_exists(FCM_SERVICE_ACCOUNT_PATH)) return '';
    $sa  = json_decode(file_get_contents(FCM_SERVICE_ACCOUNT_PATH), true);
    $now = time();
    $hdr   = _b64url(json_encode(['alg' => 'RS256', 'typ' => 'JWT']));
    $claim = _b64url(json_encode([
        'iss'   => $sa['client_email'],
        'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
        'aud'   => 'https://oauth2.googleapis.com/token',
        'iat'   => $now, 'exp' => $now + 3600,
    ]));
    $sig = ''; openssl_sign("$hdr.$claim", $sig, $sa['private_key'], 'SHA256');
    $jwt = "$hdr.$claim." . _b64url($sig);
    $ch = curl_init('https://oauth2.googleapis.com/token');
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => http_build_query(['grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt]),
        CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15,
    ]);
    $r = json_decode(curl_exec($ch), true); curl_close($ch);
    $token = $r['access_token'] ?? '';
    if ($token) file_put_contents($cache, json_encode(['token' => $token, 'exp' => $now + 3300]));
    return $token;
}

function send_push(string $fcm_token, string $title, string $body, array $data = []): bool {
    if (!$fcm_token || !file_exists(FCM_SERVICE_ACCOUNT_PATH)) return false;
    $access = _fcm_token(); if (!$access) return false;
    $payload = ['message' => [
        'token'        => $fcm_token,
        'notification' => ['title' => $title, 'body' => $body],
        'data'         => array_map('strval', $data),
        'android'      => ['notification' => ['sound' => 'default', 'default_vibrate_timings' => true]],
        'webpush'      => ['notification' => ['icon' => '/icon-192.png', 'badge' => '/icon-192.png', 'dir' => 'rtl', 'lang' => 'ar']],
    ]];
    $ch = curl_init('https://fcm.googleapis.com/v1/projects/' . FCM_PROJECT_ID . '/messages:send');
    curl_setopt_array($ch, [
        CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload),
        CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $access],
    ]);
    $res  = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if (in_array($code, [404, 410]))
        db()->prepare('DELETE FROM user_devices WHERE fcm_token = ?')->execute([$fcm_token]);
    return $code === 200;
}

// ── FCM multi-device ──────────────────────────────────────────
function get_user_tokens(int $user_id): array {
    try {
        $st = db()->prepare('SELECT fcm_token FROM user_devices WHERE user_id = ? AND last_seen > NOW() - INTERVAL 90 DAY');
        $st->execute([$user_id]);
        $tokens = array_column($st->fetchAll(), 'fcm_token');
        if ($tokens) return $tokens;
    } catch (Throwable $ignored) {}
    $st = db()->prepare('SELECT fcm_token FROM users WHERE id = ? AND fcm_token IS NOT NULL');
    $st->execute([$user_id]);
    $t = $st->fetchColumn();
    return $t ? [$t] : [];
}

function get_user_token(int $user_id): string {
    $tokens = get_user_tokens($user_id);
    return $tokens[0] ?? '';
}

function get_hood_tokens(int $neighborhood_id, int $exclude_user = 0): array {
    try {
        $st = db()->prepare(
            'SELECT DISTINCT d.fcm_token FROM user_devices d
             JOIN users u ON u.id = d.user_id
             WHERE u.neighborhood_id = ? AND u.id != ?
               AND d.last_seen > NOW() - INTERVAL 90 DAY LIMIT 200'
        );
        $st->execute([$neighborhood_id, $exclude_user]);
        $tokens = array_column($st->fetchAll(), 'fcm_token');
        if ($tokens) return $tokens;
    } catch (Throwable $ignored) {}
    $st = db()->prepare('SELECT fcm_token FROM users WHERE neighborhood_id = ? AND id != ? AND fcm_token IS NOT NULL LIMIT 200');
    $st->execute([$neighborhood_id, $exclude_user]);
    return array_column($st->fetchAll(), 'fcm_token');
}

// ── Broadcast Push: إرسال إشعار لقطاعات محددة ─────────────────
/**
 * يرسل إشعار FCM لمجموعة مستخدمين بناءً على فلاتر:
 * $filter = [
 *   'segment' => 'all' | 'paid' | 'free' | 'state' | 'city' | 'hood' | 'track'
 *   'value'   => قيمة الفلتر (اسم الولاية، المسار، إلخ)
 *   'limit'   => حد الإرسال (افتراضي 1000)
 * ]
 * يُرجع: ['sent' => int, 'failed' => int, 'total_targeted' => int]
 */
function broadcast_push(string $title, string $body, array $filter = [], array $data = []): array {
    $segment = $filter['segment'] ?? 'all';
    $value   = $filter['value']   ?? '';
    $limit   = min((int)($filter['limit'] ?? 1000), 5000);

    // بناء استعلام استهداف المستخدمين
    $where  = 'fcm_token IS NOT NULL AND fcm_token != ""';
    $params = [];

    switch ($segment) {
        case 'paid':
            $where .= ' AND subscription_tier = "paid"';
            break;
        case 'free':
            $where .= ' AND subscription_tier = "free"';
            break;
        case 'state':
            if ($value) { $where .= ' AND state = ?'; $params[] = $value; }
            break;
        case 'city':
            if ($value) { $where .= ' AND city = ?'; $params[] = $value; }
            break;
        case 'hood':
            if ($value) { $where .= ' AND neighborhood_id = ?'; $params[] = (int)$value; }
            break;
        case 'track':
            if ($value) { $where .= ' AND learning_track = ?'; $params[] = $value; }
            break;
        case 'user_type':
            if ($value) { $where .= ' AND user_type = ?'; $params[] = $value; }
            break;
        // 'all' = no extra filter
    }

    // جلب التوكنات من user_devices أولاً، ثم fallback لـ users.fcm_token
    $tokens = [];
    try {
        $st = db()->prepare(
            "SELECT DISTINCT d.fcm_token, d.user_id
             FROM user_devices d
             JOIN users u ON u.id = d.user_id
             WHERE u.$where
               AND d.last_seen > NOW() - INTERVAL 90 DAY
             LIMIT $limit"
        );
        $st->execute($params);
        $tokens = $st->fetchAll();
    } catch (Throwable $e) {
        // Fallback: قراءة مباشرة من users
        $st = db()->prepare("SELECT fcm_token, id AS user_id FROM users WHERE $where LIMIT $limit");
        $st->execute($params);
        $tokens = $st->fetchAll();
    }

    $total   = count($tokens);
    $sent    = 0;
    $failed  = 0;
    $data['broadcast'] = '1';

    foreach ($tokens as $row) {
        $fcm = $row['fcm_token'] ?? '';
        if (!$fcm) { $failed++; continue; }

        if (send_push($fcm, $title, $body, $data)) {
            $sent++;
            // حفظ إشعار داخلي أيضاً
            if (!empty($row['user_id'])) {
                save_notification((int)$row['user_id'], 'broadcast', $title, $body, $data);
            }
        } else {
            $failed++;
        }

        // تأخير صغير كل 100 رسالة لمنع throttle
        if ($sent % 100 === 0) usleep(50000);
    }

    // تسجيل في ai_logs للمراقبة
    try {
        db()->prepare("INSERT INTO staff_activity_log (staff_id, action, target_type, target_id, details, ip_address) VALUES (?,?,?,?,?,?)")
            ->execute([0, 'broadcast_push', 'notification', 0,
                json_encode(['segment' => $segment, 'value' => $value, 'sent' => $sent, 'title' => $title], JSON_UNESCAPED_UNICODE),
                $_SERVER['REMOTE_ADDR'] ?? '']);
    } catch (Throwable $ignored) {}

    return ['sent' => $sent, 'failed' => $failed, 'total_targeted' => $total];
}

// ══════════════════════════════════════════════════════════════
// Claude AI — ask_claude() + Dual AI Router
// ══════════════════════════════════════════════════════════════

/**
 * ask_claude() — استدعاء Claude API مباشرة
 * يدعم PHP 7.4+ (بدون named arguments)
 */
function ask_claude(string $prompt, string $system = '', int $max_tokens = 500, float $temperature = 0.7, string $model = ''): string {
    if (!defined('CLAUDE_API_KEY') || !CLAUDE_API_KEY || CLAUDE_API_KEY === 'YOUR_NEW_CLAUDE_KEY_HERE') return '';
    if (!$prompt) return '';

    $use_model = $model ?: CLAUDE_MODEL;
    $payload   = [
        'model'      => $use_model,
        'max_tokens' => $max_tokens,
        'messages'   => [['role' => 'user', 'content' => $prompt]],
    ];
    if ($system) $payload['system'] = $system;

    $ch = curl_init(CLAUDE_ENDPOINT);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => CLAUDE_TIMEOUT,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_HTTPHEADER     => [
            'Content-Type: application/json',
            'x-api-key: ' . CLAUDE_API_KEY,
            'anthropic-version: ' . CLAUDE_VERSION,
        ],
    ]);
    $raw  = curl_exec($ch);
    $http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $cerr = curl_error($ch);
    curl_close($ch);
    // v20: Enhanced error logging (per Technical Report recommendation)
    if ($http !== 200 || $cerr) {
        error_log("[Claude] HTTP={$http} MODEL={$use_model} ERR={$cerr} RESPONSE=" . substr($raw ?? '', 0, 200));
    }

    if ($cerr || !$raw) {
        error_log("[Claude] curl error: $cerr");
        return '';
    }

    $data = json_decode($raw, true);
    if (isset($data['error'])) {
        error_log("[Claude] API error: " . ($data['error']['message'] ?? $raw));
        return '';
    }

    return trim($data['content'][0]['text'] ?? '');
}

/**
 * ask_openai() — GPT-4o mini
 * الأفضل في: الرياضيات، اللغة العربية الدارجة، الشرح العلمي
 */
function ask_openai(string $prompt, string $system = '', int $max_tokens = 500, float $temperature = 0.7): string {
    if (!defined('OPENAI_API_KEY') || !OPENAI_API_KEY || OPENAI_API_KEY === 'YOUR_NEW_OPENAI_KEY_HERE') return '';
    if (!$prompt) return '';

    $messages = [];
    if ($system) $messages[] = ['role' => 'system', 'content' => $system];
    $messages[] = ['role' => 'user', 'content' => $prompt];

    $payload = [
        'model'       => OPENAI_MODEL,
        'messages'    => $messages,
        'max_tokens'  => $max_tokens,
        'temperature' => $temperature,
    ];

    $ch = curl_init(OPENAI_ENDPOINT);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => OPENAI_TIMEOUT,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_HTTPHEADER     => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . OPENAI_API_KEY,
        ],
    ]);
    $raw  = curl_exec($ch);
    $cerr = curl_error($ch);
    curl_close($ch);

    if ($cerr || !$raw) { error_log("[OpenAI] curl: $cerr"); return ''; }
    $data = json_decode($raw, true);
    if (isset($data['error'])) { error_log("[OpenAI] error: " . ($data['error']['message'] ?? '')); return ''; }
    return trim($data['choices'][0]['message']['content'] ?? '');
}

/**
 * ask_ai() — الموجّه الذكي للـ AI
 * يختار Inference Engine → Gemini → Claude تلقائياً
 * حسب نوع السؤال وميزانية المستخدم
 *
 * $mode:
 *   'fast'   → Gemini Flash فقط (وصف المنتجات، الدروس)
 *   'smart'  → Claude Haiku (استشارات، تحليل، CRM)
 *   'expert' → Claude Sonnet (مهام معقدة، عقود، استثمار)
 *   'auto'   → يقرر تلقائياً
 */
function ask_ai(string $prompt, string $system = '', string $mode = 'auto', int $max_tokens = 500, float $temperature = 0.7): string {
    if (!$prompt) return '';

    switch ($mode) {
        case 'fast':
            // Gemini فقط — مجاني وسريع
            return ask_gemini($prompt, $system, [], $max_tokens, $temperature);

        case 'smart':
            // Claude Haiku → Gemini → GPT-4o mini
            $ans = ask_claude($prompt, $system, $max_tokens, $temperature, CLAUDE_MODEL);
            if (!$ans) $ans = ask_gemini($prompt, $system, [], $max_tokens, $temperature);
            if (!$ans) $ans = ask_openai($prompt, $system, $max_tokens, $temperature);
            return $ans;

        case 'expert':
            // Claude Sonnet → Claude Haiku → GPT-4o mini
            $ans = ask_claude($prompt, $system, $max_tokens, $temperature, CLAUDE_MODEL_SMART);
            if (!$ans) $ans = ask_claude($prompt, $system, $max_tokens, $temperature, CLAUDE_MODEL);
            if (!$ans) $ans = ask_openai($prompt, $system, $max_tokens, $temperature);
            if (!$ans) $ans = ask_gemini($prompt, $system, [], $max_tokens, $temperature);
            return $ans;

        case 'math':
            // GPT-4o mini الأفضل للرياضيات والعلوم
            $ans = ask_openai($prompt, $system, $max_tokens, $temperature);
            if (!$ans) $ans = ask_gemini($prompt, $system, [], $max_tokens, $temperature);
            return $ans;

        case 'arabic':
            // GPT-4o mini الأفضل للعربية الدارجة
            $ans = ask_openai($prompt, $system, $max_tokens, $temperature);
            if (!$ans) $ans = ask_claude($prompt, $system, $max_tokens, $temperature);
            if (!$ans) $ans = ask_gemini($prompt, $system, [], $max_tokens, $temperature);
            return $ans;

        default: // auto
            // محرك ثلاثي: Gemini (سريع) → Claude (معقد) → GPT (احتياط)
            if ($max_tokens <= 200 || mb_strlen($prompt) < 80) {
                $ans = ask_gemini($prompt, $system, [], $max_tokens, $temperature);
                if (!$ans) $ans = ask_openai($prompt, $system, $max_tokens, $temperature);
                return $ans;
            }
            $ans = ask_claude($prompt, $system, $max_tokens, $temperature);
            if (!$ans) $ans = ask_gemini($prompt, $system, [], $max_tokens, $temperature);
            if (!$ans) $ans = ask_openai($prompt, $system, $max_tokens, $temperature);
            return $ans;
    }
}

// ── معالجة ملفات PDF/Word/Text ────────────────────────────────
/**
 * extract_text_from_file()
 * يستخرج النص من ملفات: txt, pdf (basic), docx
 * يُرجع النص أو '' عند الفشل
 */
function extract_text_from_file(string $file_path, string $mime_type): string {
    if (!file_exists($file_path)) return '';

    // TXT — مباشر
    if (str_contains($mime_type, 'text/plain')) {
        return mb_substr(file_get_contents($file_path), 0, 15000);
    }

    // DOCX — استخراج من XML داخل ZIP
    if (str_contains($mime_type, 'wordprocessingml') || str_ends_with($file_path, '.docx')) {
        if (!class_exists('ZipArchive')) return '';
        $zip = new ZipArchive();
        if ($zip->open($file_path) !== true) return '';
        $xml = $zip->getFromName('word/document.xml');
        $zip->close();
        if (!$xml) return '';
        // إزالة XML tags
        $text = strip_tags(str_replace(['</w:p>', '</w:r>'], ["\n", ' '], $xml));
        return mb_substr(preg_replace('/\s+/', ' ', $text), 0, 15000);
    }

    // PDF — استخراج نص بسيط (بدون pdfparser)
    if (str_contains($mime_type, 'pdf') || str_ends_with($file_path, '.pdf')) {
        $content = file_get_contents($file_path);
        if (!$content) return '';
        // استخراج النصوص بين BT...ET (PDF text blocks)
        preg_match_all('/BT(.+?)ET/s', $content, $matches);
        $text = '';
        foreach ($matches[1] as $block) {
            preg_match_all('/\(([^)]+)\)\s*Tj/', $block, $tj);
            foreach ($tj[1] as $t) $text .= $t . ' ';
        }
        $text = mb_convert_encoding($text, 'UTF-8', 'auto');
        return mb_substr(trim($text), 0, 15000);
    }

    return '';
}

/**
 * compress_image_upload()
 * يضغط صورة Base64 إلى WebP/JPEG بجودة 75% وأبعاد 800×600
 * يُقلِّل الحجم من 3MB إلى ~150KB (وفر 95%)
 */
function compress_image_upload(string $b64, int $max_w = 800, int $max_h = 600, int $quality = 72): array {
    $pure    = preg_replace('/^data:[^;]+;base64,/', '', $b64);
    $decoded = base64_decode($pure, true);
    if (!$decoded || strlen($decoded) < 100) return ['ok'=>false,'error'=>'invalid_image'];

    // إنشاء صورة من البيانات
    $img = @imagecreatefromstring($decoded);
    if (!$img) return ['ok'=>false,'error'=>'cannot_decode'];

    $orig_w = imagesx($img);
    $orig_h = imagesy($img);

    // حساب الأبعاد الجديدة مع الحفاظ على النسبة
    $ratio  = min($max_w / $orig_w, $max_h / $orig_h, 1.0);
    $new_w  = (int)round($orig_w * $ratio);
    $new_h  = (int)round($orig_h * $ratio);

    // إنشاء صورة مضغوطة
    $new_img = imagecreatetruecolor($new_w, $new_h);
    // خلفية بيضاء للصور الشفافة
    $white = imagecolorallocate($new_img, 255, 255, 255);
    imagefilledrectangle($new_img, 0, 0, $new_w, $new_h, $white);
    imagecopyresampled($new_img, $img, 0, 0, 0, 0, $new_w, $new_h, $orig_w, $orig_h);
    imagedestroy($img);

    // حفظ كـ JPEG مضغوط
    ob_start();
    imagejpeg($new_img, null, $quality);
    $compressed = ob_get_clean();
    imagedestroy($new_img);

    if (!$compressed) return ['ok'=>false,'error'=>'compression_failed'];

    $saved_pct = $orig_w > $max_w || $orig_h > $max_h
        ? round((1 - strlen($compressed)/strlen($decoded))*100)
        : round((1 - $quality/100)*50);

    return [
        'ok'        => true,
        'data'      => $compressed,
        'ext'       => 'jpg',
        'mime'      => 'image/jpeg',
        'orig_size' => strlen($decoded),
        'new_size'  => strlen($compressed),
        'saved_pct' => $saved_pct,
        'new_w'     => $new_w,
        'new_h'     => $new_h,
    ];
}

/**
 * validate_document_upload()
 * يتحقق من ملفات: txt, docx, pdf (حتى 10MB)
 */
function validate_document_upload(string $b64, int $max_mb = 10): array {
    $pure    = preg_replace('/^data:[^;]+;base64,/', '', $b64);
    $decoded = base64_decode($pure, true);
    if (!$decoded || strlen($decoded) < 10) return ['ok' => false, 'error' => 'invalid_file'];
    if (strlen($decoded) > $max_mb * 1024 * 1024) return ['ok' => false, 'error' => 'file_too_large'];

    // Detect file type by magic bytes
    $magic = substr($decoded, 0, 8);
    $ext   = null;
    $mime  = null;

    if (substr($magic, 0, 4) === "%PDF") { $ext = 'pdf'; $mime = 'application/pdf'; }
    elseif (substr($magic, 0, 4) === "PK\x03\x04") { $ext = 'docx'; $mime = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; }
    elseif (ctype_print(substr($decoded, 0, 200))) { $ext = 'txt'; $mime = 'text/plain'; }

    if (!$ext) return ['ok' => false, 'error' => 'unsupported_format', 'note' => 'PDF/DOCX/TXT only'];

    return ['ok' => true, 'ext' => $ext, 'mime' => $mime, 'data' => $decoded, 'size' => strlen($decoded)];
}

// ══════════════════════════════════════════════════════════════
// ضغط الصور — Image Compression
// ══════════════════════════════════════════════════════════════

/**
 * compress_to_thumbnail() — ضغط إلى thumbnail صغير
 * 200x150, جودة 65% → ~15-25KB
 */
function compress_to_thumbnail(string $b64): string {
    $result = compress_image_upload($b64, 200, 150, 65);
    return $result['ok'] ? base64_encode($result['data']) : '';
}

/**
 * compress_image_base64()
 * يضغط صورة base64 ويُرجعها بصيغة JPEG مضغوطة
 * الهدف: تقليل الحجم 80-95% مع حفاظ على الجودة المرئية
 */
function compress_image_base64(string $b64, int $max_width = 800, int $quality = 78): string {
    $pure = preg_replace('/^data:image\/\w+;base64,/', '', $b64);
    $data = base64_decode($pure, true);
    if (!$data || strlen($data) < 100) return $b64;

    $img = @imagecreatefromstring($data);
    if (!$img) return $b64;

    $orig_w = imagesx($img);
    $orig_h = imagesy($img);

    // تصغير الأبعاد إذا تجاوزت الحد
    if ($orig_w > $max_width) {
        $ratio  = $max_width / $orig_w;
        $new_w  = $max_width;
        $new_h  = (int)round($orig_h * $ratio);
        $resized = imagecreatetruecolor($new_w, $new_h);
        // الحفاظ على الشفافية
        imagealphablending($resized, false);
        imagesavealpha($resized, true);
        imagecopyresampled($resized, $img, 0, 0, 0, 0, $new_w, $new_h, $orig_w, $orig_h);
        imagedestroy($img);
        $img = $resized;
    }

    // ضغط وتحويل لـ JPEG
    ob_start();
    imagejpeg($img, null, $quality);
    $compressed = ob_get_clean();
    imagedestroy($img);

    if (!$compressed) return $b64;

    // إذا الضغط لم يُحسِّن الحجم، ارجع للأصل
    $orig_size = strlen(base64_decode($pure));
    if (strlen($compressed) >= $orig_size) return $b64;

    return 'data:image/jpeg;base64,' . base64_encode($compressed);
}

/**
 * image_save_optimized()
 * يحفظ نسختين: thumbnail (200px) + full (800px)
 * يُقلِّل التخزين بنسبة 90%+
 */
function image_save_optimized(string $b64, string $prefix = 'img'): array {
    $check = validate_image_base64($b64, MAX_UPLOAD_MB);
    if (!$check['ok']) return ['ok' => false];

    if (!is_dir(UPLOAD_DIR)) mkdir(UPLOAD_DIR, 0755, true);
    $uid = uniqid($prefix . '_', true);

    // Full — 800px max, quality 78%
    $full_b64  = compress_image_base64($b64, 800, 78);
    $full_pure = preg_replace('/^data:[^;]+;base64,/', '', $full_b64);
    $full_data = base64_decode($full_pure);
    $full_name = $uid . '_full.jpg';
    file_put_contents(UPLOAD_DIR . $full_name, $full_data);

    // Thumbnail — 280px max, quality 72%
    $thumb_b64  = compress_image_base64($b64, 280, 72);
    $thumb_pure = preg_replace('/^data:[^;]+;base64,/', '', $thumb_b64);
    $thumb_data = base64_decode($thumb_pure);
    $thumb_name = $uid . '_thumb.jpg';
    file_put_contents(UPLOAD_DIR . $thumb_name, $thumb_data);

    return [
        'ok'        => true,
        'full_url'  => UPLOAD_URL . $full_name,
        'thumb_url' => UPLOAD_URL . $thumb_name,
        'full_kb'   => round(strlen($full_data) / 1024),
        'thumb_kb'  => round(strlen($thumb_data) / 1024),
    ];
}

/**
 * validate_and_compress_image_base64()
 * يتحقق من الصورة ثم يضغطها تلقائياً
 * يُستخدَم بدلاً من validate_image_base64() في كل upload
 */
function validate_and_compress_image_base64(string $b64, int $max_mb = 5): array {
    // ضغط أولاً
    $compressed_b64 = compress_image_base64($b64, 800, 78);
    // ثم تحقق
    return validate_image_base64($compressed_b64, $max_mb);
}
// Auto-load PricingEngine
if (!class_exists('PricingEngine') && function_exists('db')) {
    require_once __DIR__ . '/engine/PricingEngine.php';
}

// ════════════════════════════════════════════════════════
// Platform Pricing (admin-controlled via platform_settings)
// Exchange rate: 1 USD = 4,100 SDG (updated via admin panel)
// ════════════════════════════════════════════════════════
// [PRICING — DB primary, PHP fallback] define('USD_TO_SDG_RATE',          4100);    // سعر الصرف الافتراضي
// [PRICING — DB primary, PHP fallback] define('SUB_PLUS_PRICE_SDG',       20000);   // Plus بالجنيه
// [PRICING — DB primary, PHP fallback] define('SUB_PRO_PRICE_SDG',        50000);   // Pro بالجنيه
// [PRICING — DB primary, PHP fallback] define('SUB_PLUS_CREDIT_SDG',      15000);   // رصيد وثائق Plus
// [PRICING — DB primary, PHP fallback] define('SUB_PRO_CREDIT_SDG',       50000);   // رصيد وثائق Pro
define('CORP_STARTER_USD',         99);      // Corporate Starter
define('CORP_BUSINESS_USD',        249);     // Corporate Business
define('CORP_SCALE_USD',           599);     // Corporate Scale

// ── Security Secrets ─────────────────────────────────────────
define('CSRF_SECRET',    bin2hex(random_bytes(16)));   // CSRF protection
define('SESSION_SECRET', bin2hex(random_bytes(16)));   // Session signing

// ── Logging ─────────────────────────────────────────────────
define('LOG_LEVEL', APP_ENV === 'production' ? 'error' : 'debug');
define('LOG_FILE',  '/var/log/sudanna/app.log');


// ── Sudanna Pay Configuration ─────────────────────────────────
define('SDPAY_ENABLED',          true);
// [PRICING — DB primary, PHP fallback] define('SDPAY_MAX_TRANSFER_SDG', 10000000);
// [PRICING — DB primary, PHP fallback] define('SDPAY_MIN_TRANSFER_SDG', 10);
define('SDPAY_REVERSAL_MINUTES', 15);
// [PRICING — DB primary, PHP fallback] define('SDPAY_AGENT_COMMISSION', 0.005);
// [PRICING — DB primary, PHP fallback] define('SDPAY_MERCHANT_COMMISSION_DEFAULT', 0.015);
define('SDPAY_PLATFORM_FEE_PCT', 0.02);
define('SDPAY_PROFIT_SHARE_PCT', 0.05);
define('SDPAY_SAFETY_POOL_PCT',  0.01);
// [PRICING — DB primary, PHP fallback] define('SDPAY_AML_THRESHOLD_SDG', 10000000);
define('SDPAY_KYC1_LIMIT_SDG',  500000);
define('SDPAY_KYC2_LIMIT_SDG',  5000000);
// [PRICING — DB primary, PHP fallback] define('INVEST_MIN_SDG',         5000);
// [PRICING — DB primary, PHP fallback] define('ROSCA_MIN_MONTHLY_SDG',  100);
define('ROSCA_MAX_MEMBERS',      50);

// ════════════════════════════════════════════════════════════
// SUDANNA PAY — Assistant Sector Config
// ════════════════════════════════════════════════════════════
define('PAY_SECTORS', serialize([
    'pay','gov','invest','merchant','rosca','zakat','bills','agent'
]));
define('PAY_DIRECT_INTENTS', serialize([
    'check_balance','sdpay_balance','sdpay_transfer','sdpay_bill_electricity',
    'sdpay_bill_water','sdpay_bill_telecom','sdpay_gov_passport','sdpay_zakat',
    'sdpay_rosca','invest_projects','merchant_pay','merchant_register'
]));
define('INFERENCE_PAY_ENABLED', true);
define('VISITOR_ASK_PAY_BUTTONS', true);

// ════════════════════════════════════════════════════════════
// FINANCIAL INSTITUTIONS — تكامل المؤسسات المالية
// ════════════════════════════════════════════════════════════

// وضع الاختبار — يُغيَّر لـ false عند الإنتاج
define('SANDBOX_MODE',                   true);
define('BANK_INTEGRATION_ENABLED',       false); // يُفعَّل بعد الحصول على API credentials

// EBS — شبكة المدفوعات السودانية
define('EBS_ENABLED',                    false);
define('EBS_API_URL',                    'https://api.ebssudan.com/v1');
define('EBS_SANDBOX_URL',               'https://sandbox.ebssudan.com/v1');
define('EBS_MERCHANT_ID',               '');   // من EBS
define('EBS_TERMINAL_ID',               '');   // من EBS
define('EBS_CLIENT_ID',                 '');
define('EBS_CLIENT_SECRET',             '');

// بنك الخرطوم — الشريك الأساسي
define('BANK_ACCOUNT_NO',               '1821425');
define('BANK_ACCOUNT_NAME',             'شركة سودانا للتقنية');
define('BANK_API_URL',                  'https://api.bankofkhartoum.sd/v1');
define('BANK_SANDBOX_URL',              'https://sandbox.bankofkhartoum.sd/v1');
define('BANK_SETTLEMENT_ACCOUNT',       '1821425');
define('BANK_SETTLEMENT_CURRENCY',      'SDG');

// سلوك الدفع
define('CASH_IN_REQUIRES_BANK_CONFIRM', true);   // إيداع نقدي يحتاج تأكيد بنكي
define('TRANSFER_REQUIRES_BANK_CONFIRM',true);   // تحويل يحتاج تأكيد بنكي
define('PAYOUT_REQUIRES_BANK_CONFIRM',  true);   // صرف يحتاج تأكيد بنكي

// Escrow
define('ESCROW_ENABLED',                true);
define('ESCROW_AUTO_RELEASE_HOURS',     48);     // تحرير تلقائي بعد 48 ساعة

// PIN Security
define('PIN_MAX_ATTEMPTS',              3);      // أقصى محاولات PIN
define('PIN_LOCKOUT_MINUTES',           15);     // مدة الإغلاق
define('PIN_HISTORY_COUNT',             3);      // لا تعيد آخر 3 PIN

// التسوية
define('SETTLEMENT_HOUR',               23);     // ساعة التسوية اليومية
define('RECONCILE_AUTO',                true);
define('RECONCILE_WINDOW_HOURS',        24);

// رسوم الخدمات
define('SERVICE_PLATFORM_FEE',          0.10);   // 10% عمولة الخدمات
define('ACCOUNTING_ENABLED',            true);
define('AI_MODEL_DEFAULT',              'claude-sonnet-4-20250514');
define('APP_URL', SITE_URL); // ← always matches SITE_URL
define('MAIL_HOST',                     'smtp.gmail.com');

// SLA
define('SLA_RESPONSE_HOURS_URGENT',     4);
define('SLA_RESPONSE_HOURS_HIGH',       8);
define('SLA_RESPONSE_HOURS_NORMAL',     24);
define('TICKET_ATTACHMENT_MAX_MB',      5);

// Webhook
define('BANK_WEBHOOK_SECRET',           hash('sha256', DB_PASS ?? 'sudanna_webhook_2025'));