<?php
/**
 * POST /api/bde/generate
 * Phase 3 — Full Replace (NOT Bridge)
 *
 * ARCHITECTURE: Kernel + PricingEngine + ReservationEngine + BDE Executor
 * See full design in: DEPLOYMENT_README.md
 */
require_once __DIR__ . '/../../config.php';
require_once __DIR__ . '/../../engine/SafetyEngine.php';
require_once __DIR__ . '/../../engine/Kernel.php';
require_once __DIR__ . '/../../engine/PricingEngine.php';
require_once __DIR__ . '/../../engine/BudgetGate.php';
require_once __DIR__ . '/../../engine/ReservationEngine.php';
require_once __DIR__ . '/../../engine/UsageMeter.php';
require_once __DIR__ . '/../../engine/BillingEngine.php';
require_once __DIR__ . '/../../engine/TemplateEngine.php';

// ══ GOVERNANCE GATE ──────────────────────────────────────────────
$ctx  = Kernel::handle(['auth' => true, 'rate' => 'ai']);
$user = $ctx['user'];
$uid  = (int)$user['id'];
$plan = $user['plan_key'] ?? $user['subscription_tier'] ?? 'free';

// BDE-specific rate: 5 docs/hour (in addition to Kernel AI rate bucket)
if (!check_rate_limit('bde_gen_' . $uid, 5, 3600)) {
    Kernel::fail('rate_limit', 'الحد الأقصى 5 وثائق/ساعة. حاول لاحقاً.', 429);
}

$body = Kernel::jsonBody();

// ══ SCENARIO A: Token → Execute ══════════════════════════════════
if (!empty($body['token'])) {
    $token = preg_replace('/[^A-Za-z0-9_]/', '', $body['token']);

    // Activate: validates token, checks TTL, debits (pessimistic), sets status→active.
    // Atomic: WHERE status='pending'. Throws on any violation (anti-replay).
    try {
        $activation = ReservationEngine::activate($token);
    } catch (RuntimeException $e) {
        Kernel::fail(
            $e->getMessage(),
            match($e->getMessage()) {
                'invalid_or_expired_token'      => 'الرمز غير صالح أو انتهت صلاحيته.',
                'price_snapshot_expired'        => 'انتهت صلاحية التقدير. أعد الطلب.',
                'reservation_already_activated' => 'تم إنشاء الوثيقة مسبقاً.',
                'debit_failed'                  => 'رصيد غير كافٍ لإتمام العملية.',
                default                         => 'خطأ في تفعيل الحجز.',
            },
            400
        );
    }

    $bdeCtx = $activation['plan']['bde_context'] ?? [];
    $docId  = (int)($bdeCtx['doc_id'] ?? 0);
    if (!$docId) {
        ReservationEngine::cancel($activation['reservation_id'], 'missing_bde_context');
        Kernel::fail('reservation_corrupt', 'بيانات الوثيقة مفقودة في الحجز.', 500);
    }

    $docSt = db()->prepare('SELECT * FROM bde_documents WHERE id=? AND user_id=? LIMIT 1');
    $docSt->execute([$docId, $uid]);
    $document = $docSt->fetch();
    if (!$document) {
        ReservationEngine::cancel($activation['reservation_id'], 'doc_not_found');
        Kernel::fail('doc_not_found', 'الوثيقة غير موجودة.', 404);
    }

    db()->prepare("UPDATE bde_documents SET status='generating' WHERE id=?")->execute([$docId]);

    // Prompts frozen at estimation time inside reservation metadata
    $builtPrompt  = $bdeCtx['prompt'] ?? '';
    $systemPrompt = $bdeCtx['system'] ?? 'أنت متخصص في إعداد المستندات الاحترافية.';

    // Defensive fallback if context is incomplete
    if (!$builtPrompt) {
        $tpl = TemplateEngine::getTemplate($document['doc_type']);
        if ($tpl) {
            $builtPrompt  = TemplateEngine::buildPrompt($tpl, json_decode($document['collected_data'] ?? '{}', true) ?? []);
            $systemPrompt = $tpl['ai_instructions'] ?? $systemPrompt;
        }
    }

        // Safety: evaluate user input before AI call
    $_se_in = SafetyEngine::evaluateInput($q ?? '', ['endpoint' => 'bde/generate.php']);
    if ($_se_in['action'] === SafetyEngine::BLOCK) {
        Logger::warn('ai_input_blocked', ['endpoint' => 'bde/generate.php']);
        $generated = null;
    } elseif ($_se_in['action'] === SafetyEngine::WARN) {
        $generated = SafetyEngine::emergencyResponse();
    } else {
        $_um_bde = UsageMeter::wrap((int)$uid, 'chat', 'bde', fn() => AIClient::call($builtPrompt, $systemPrompt, 'auto', 2000, 0.5, false), ['skip_debit' => true]);
        $generated = $_um_bde['ok'] ? ($_um_bde['result']['text'] ?? null) : null;

        // Safety: evaluate AI output
        if ($generated) {
            $_se_out = SafetyEngine::evaluateOutput($generated, 'general');
            if ($_se_out['action'] === SafetyEngine::WARN && !empty($_se_out['replace'])) {
                $generated = $_se_out['replace'];
            } elseif ($_se_out['action'] === SafetyEngine::BLOCK) {
                $generated = null;
            }
        }
    }

    if (!$generated) $generated = ask_gemini($builtPrompt, $systemPrompt, [], 2000, 0.5);
    if (!$generated) $generated = ask_openai($builtPrompt, $systemPrompt, 2000, 0.5);

    if (!$generated) {
        // Generation failed → cancel reservation → FULL REFUND (cancel() refunds if active)
        ReservationEngine::cancel($activation['reservation_id'], 'generation_failed');
        db()->prepare("UPDATE bde_documents SET status='draft' WHERE id=?")->execute([$docId]);
        Kernel::fail('generation_failed',
            'تعذّر توليد الوثيقة. تم إعادة رصيدك كاملاً.', 500,
            ['refund' => true, 'reservation_id' => $activation['reservation_id']]);
    }

    db()->prepare("UPDATE bde_documents SET generated_content=?, status='ready' WHERE id=?")
        ->execute([$generated, $docId]);

    // BDE is atomic — actual cost = reserved cost
    $actualSdg = (int)$activation['reserved_sdg'];
    ReservationEngine::complete($activation['reservation_id'], $actualSdg, [[
        'task_key' => 'document:' . ($document['doc_type'] ?? 'contract'),
        'status'   => 'done',
        'cost_sdg' => $actualSdg,
    ]]);

    Logger::info('bde_generated', ['doc_id'=>$docId,'reservation_id'=>$activation['reservation_id'],'scenario'=>'A']);
    Logger::aiUsage($uid, 'bde_document', ['service'=>'bde:'.$docId,'cost_sdg'=>$actualSdg,'reservation_id'=>$activation['reservation_id']]);
    try { db()->prepare('INSERT INTO ai_logs (user_id,service) VALUES (?,?)')->execute([$uid,'bde']); } catch(Throwable $x){}

    Kernel::respond([
        'success'        => true,
        'doc_id'         => $docId,
        'status'         => 'ready',
        'title'          => $document['title'] ?? '',
        'content'        => $generated,
        'preview'        => mb_substr($generated, 0, 500) . '...',
        'reservation_id' => $activation['reservation_id'],
        'charged_sdg'    => $actualSdg,
        'message'        => "✅ تم إنشاء وثيقتك الاحترافية!\n\nيمكنك:\n• تصدير PDF أو HTML\n• طلب مراجعة خبير\n• تعديل المحتوى",
        'actions' => [
            ['label'=>'تصدير PDF','url'=>"/api/bde/export.php?doc_id={$docId}&format=html",'icon'=>'📄'],
            ['label'=>'طلب مراجعة خبير','url'=>'#consultation','icon'=>'⚖️'],
        ],
    ]);
}

// ══ SCENARIOS B + C: New request ═════════════════════════════════
$docId = (int)($body['doc_id'] ?? 0);
if (!$docId) Kernel::fail('doc_id_required', 'doc_id مطلوب', 400);

$docSt = db()->prepare('SELECT * FROM bde_documents WHERE id=? AND user_id=? LIMIT 1');
$docSt->execute([$docId, $uid]);
$document = $docSt->fetch();
if (!$document) Kernel::fail('not_found', 'الوثيقة غير موجودة', 404);

$template = TemplateEngine::getTemplate($document['doc_type']);
if (!$template) Kernel::fail('template_not_found', 'القالب غير موجود', 404);

$collectedData  = json_decode($document['collected_data'] ?? '{}', true) ?? [];
$requiredFields = array_filter($template['fields'] ?? [], fn($f) => !empty($f['required']));
$missingFields  = array_filter($requiredFields, fn($f) => empty($collectedData[$f['key'] ?? '']));
if (!empty($missingFields)) {
    Kernel::fail('missing_required_fields', 'يرجى إكمال الحقول المطلوبة أولاً', 400, [
        'missing_fields' => array_values(array_map(fn($f) => $f['label'] ?? '', $missingFields)),
    ]);
}

// ── PricingEngine: SSOT ───────────────────────────────────────────
$docType  = $document['doc_type'] ?? 'contract';
$priceSdg = PricingEngine::getDocumentPrice($docType, $plan);
$threshold = (int)PricingEngine::getSetting('estimation_threshold_sdg', 3000);

// Build prompts now (same inputs regardless of scenario)
$builtPrompt  = TemplateEngine::buildPrompt($template, $collectedData);
$systemPrompt = $template['ai_instructions'] ?? 'أنت متخصص في إعداد المستندات الاحترافية.';

// ══ SCENARIO B: price ≥ threshold → Hold → Token ═════════════════
if ($priceSdg >= $threshold) {

    $estimatedPlan = [
        'tasks' => [[
            'type'=>'document','subtype'=>$docType,'count'=>1,
            'cost_sdg'=>$priceSdg,'unit_cost_sdg'=>$priceSdg,
            'sector'=>'general','plan_applied'=>$plan,
        ]],
        'cost'           => ['total_sdg'=>$priceSdg,'breakdown'=>['document'=>['count'=>1,'cost_sdg'=>$priceSdg]]],
        'price_snapshot' => [
            'locked_at'   => date('c'),
            'ttl_seconds' => (int)PricingEngine::getSetting('estimation_ttl_minutes', 30) * 60,
            'plan'        => $plan,
            'exchange_rate' => PricingEngine::getRate(),
        ],
        'confidence'  => 1.0,
        'method'      => 'direct_pricing',
        // Frozen prompts stored for Scenario A execution
        'bde_context' => ['doc_id'=>$docId,'prompt'=>$builtPrompt,'system'=>$systemPrompt],
    ];

    $budget = BudgetGate::canAffordEstimate($uid, $estimatedPlan);
    if (!$budget['ok']) {
        Kernel::respond([
            'ok'=>false, 'error'=>$budget['error']??'insufficient_funds',
            'required_sdg'=>$budget['required_sdg'], 'available_sdg'=>$budget['available_sdg'],
            'shortfall_sdg'=>$budget['shortfall_sdg'], 'breakdown'=>$budget['breakdown'],
            'suggestions'=>$budget['suggestions']??[],
        ], 402);
    }

    $ttl         = (int)PricingEngine::getSetting('estimation_ttl_minutes', 30);
    $reservation = ReservationEngine::hold($uid, $estimatedPlan, $ttl);

    Logger::info('bde_estimation_held', ['doc_id'=>$docId,'price_sdg'=>$priceSdg,'reservation_id'=>$reservation['reservation_id'],'scenario'=>'B']);

    Kernel::respond([
        'ok'                => true,
        'action'            => 'awaiting_confirmation',
        'doc_id'            => $docId,
        'doc_type'          => $docType,
        'doc_title'         => $document['title'] ?? '',
        'cost'              => $estimatedPlan['cost'],
        'token'             => $reservation['confirmation_token'],
        'expires_in_seconds'=> $ttl * 60,
        'expires_at'        => $reservation['expires_at'],
        'wallet_after_confirm' => max(0, $budget['breakdown']['available'] - $priceSdg),
        'action_label'      => 'راجع التكلفة واضغط تأكيد لإنشاء الوثيقة',
        'message'           => 'تكلفة الوثيقة: ' . number_format($priceSdg) . ' SDG — اضغط تأكيد لخصمها وبدء التوليد',
    ]);
}

// ══ SCENARIO C: price < threshold → Direct Execute ════════════════
$limit = BillingEngine::checkAILimit($uid, $plan);
if (!empty($limit['exceeded'])) {
    Kernel::fail('daily_limit_exceeded', "تجاوزت حد {$limit['limit']} استدعاء/يوم", 429,
        ['used'=>$limit['used'],'limit'=>$limit['limit']]);
}

if ($priceSdg > 0 && !UsageMeter::checkFunds($uid, $priceSdg)) {
    Kernel::fail('insufficient_funds', 'رصيدك غير كافٍ. المطلوب: ' . number_format($priceSdg) . ' SDG', 402,
        ['required_sdg'=>$priceSdg]);
}

db()->prepare("UPDATE bde_documents SET status='generating' WHERE id=?")->execute([$docId]);

$generated = ask_claude($builtPrompt, $systemPrompt, 2000, 0.5, CLAUDE_MODEL_SMART ?? CLAUDE_MODEL);
if (!$generated) $generated = ask_gemini($builtPrompt, $systemPrompt, [], 2000, 0.5);
if (!$generated) $generated = ask_openai($builtPrompt, $systemPrompt, 2000, 0.5);

if (!$generated) {
    db()->prepare("UPDATE bde_documents SET status='draft' WHERE id=?")->execute([$docId]);
    Kernel::fail('generation_failed', 'تعذّر توليد الوثيقة — حاول مرة أخرى', 500);
}

db()->prepare("UPDATE bde_documents SET generated_content=?, status='ready' WHERE id=?")
    ->execute([$generated, $docId]);

// DEBIT AFTER SUCCESS ONLY
$chargedSdg = 0;
if ($priceSdg > 0) {
    $debit = UsageMeter::debit($uid, $priceSdg, 'document', $docType);
    $chargedSdg = $debit['ok'] ? $priceSdg : 0;
    if (!$debit['ok']) {
        Logger::warn('bde_debit_failed_post_success', ['user_id'=>$uid,'price_sdg'=>$priceSdg,'error'=>$debit['error']??'?']);
    }
}

Logger::info('bde_generated', ['doc_id'=>$docId,'charged_sdg'=>$chargedSdg,'scenario'=>'C']);
Logger::aiUsage($uid, 'bde_document', ['service'=>'bde:'.$docType,'cost_sdg'=>$chargedSdg]);
try { db()->prepare('INSERT INTO ai_logs (user_id,service) VALUES (?,?)')->execute([$uid,'bde']); } catch(Throwable $x){}

Kernel::respond([
    'success'    => true,
    'doc_id'     => $docId,
    'status'     => 'ready',
    'title'      => $document['title'] ?? '',
    'content'    => $generated,
    'preview'    => mb_substr($generated, 0, 500) . '...',
    'charged_sdg'=> $chargedSdg,
    'message'    => "✅ تم إنشاء وثيقتك الاحترافية!\n\nيمكنك:\n• تصدير PDF أو HTML\n• طلب مراجعة خبير\n• تعديل المحتوى",
    'actions'    => [
        ['label'=>'تصدير PDF','url'=>"/api/bde/export.php?doc_id={$docId}&format=html",'icon'=>'📄'],
        ['label'=>'طلب مراجعة خبير','url'=>'#consultation','icon'=>'⚖️'],
    ],
]);
