<?php
/**
 * POST /api/dashboard/chat-stream.php  (SSE)
 *
 * Streams a RAG chat answer using the user's private corpus + the dobetter
 * legal package. Each output token is delivered as an SSE event named "token".
 * On completion, sources, chunks_used, model, and elapsed_ms are sent as a
 * "done" event. Errors are sent as a "fail" event.
 *
 * Request body (JSON):
 *   {
 *     "question": "Hva sier barnevernloven § 4-12?",
 *     "history":  [{role:"user"|"assistant", content:"..."}],  // optional, capped at 8
 *     "category": "barnevern" (optional),
 *     "language": "no" | "en" (optional, default no)
 *   }
 */

declare(strict_types=1);

require_once dirname(__DIR__, 2) . '/includes/bootstrap.php';

dbnToolsRequireMethod('POST');
dbnToolsRequireAuth();

try {
    $tenant = dbnToolsEnsureDashboardTenant();
} catch (DbnToolsHttpException $e) {
    dbnToolsError($e->getMessage(), $e->status, $e->errorCode);
}
$clientId = (int)$tenant['client_id'];

$input    = dbnToolsJsonInput(80_000);
$question = trim((string)($input['question'] ?? ''));
if ($question === '') {
    dbnToolsError('question is required.', 400, 'missing_question');
}
if (mb_strlen($question, 'UTF-8') > 4000) {
    dbnToolsError('question is too long (max 4000 chars).', 422, 'question_too_long');
}

$history = is_array($input['history'] ?? null) ? $input['history'] : [];
$history = array_slice($history, -8);
$history = array_values(array_filter($history, fn($m) => is_array($m)
    && in_array($m['role'] ?? '', ['user', 'assistant'], true)
    && is_string($m['content'] ?? null)));

$category = trim((string)($input['category'] ?? '')) ?: null;
$language = in_array($input['language'] ?? 'no', ['no', 'en'], true) ? $input['language'] : 'no';

// SSE setup
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache, no-transform');
header('X-Accel-Buffering: no');
@ini_set('output_buffering', 'off');
@ini_set('zlib.output_compression', '0');
while (ob_get_level() > 0) ob_end_flush();
ob_implicit_flush(true);

function sseEmit(string $event, array $data): void {
    echo "event: {$event}\n";
    echo 'data: ' . json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n\n";
    if (function_exists('flush')) @flush();
}

dbnToolsBootCaveau();

try {
    $rag = new ClientRagPipeline($clientId);

    $options = [
        'conversation_history' => $history,
        'language'             => $language,
        'user_id'              => (int)($tenant['client_user_id'] ?? 0),
        'user_role'            => 'owner',
    ];

    $result = $rag->askStreaming(
        $question,
        null,         // model: let pipeline choose default
        $category,
        $options,
        function (string $chunk): void {
            if ($chunk !== '') sseEmit('token', ['t' => $chunk]);
        }
    );

    $sources = [];
    foreach (($result['fullChunks'] ?? $result['chunks'] ?? []) as $c) {
        if (!is_array($c)) continue;
        $sources[] = [
            'document_id'  => (int)($c['document_id'] ?? 0),
            'title'        => (string)($c['title'] ?? ''),
            'section'      => (string)($c['section_title'] ?? $c['section'] ?? ''),
            'source_url'   => (string)($c['source_url'] ?? ''),
            'score'        => isset($c['score']) ? (float)$c['score'] : null,
        ];
    }

    sseEmit('done', [
        'ok'              => true,
        'chunks_used'     => (int)($result['chunks_used'] ?? count($sources)),
        'model'           => (string)($result['model'] ?? ''),
        'response_time_ms'=> (int)($result['response_time_ms'] ?? 0),
        'sources'         => $sources,
    ]);
} catch (Throwable $e) {
    sseEmit('fail', ['ok' => false, 'message' => $e->getMessage()]);
}
exit;
