<?php
/**
 * POST /api/dashboard/save-from-tool.php
 *
 * Improved successor to /api/save-to-corpus.php — adds:
 *   - tags as either CSV string or array
 *   - source_tool slug recorded as import provenance
 *   - chat-answer kind (records import_method='chat_answer')
 *   - preview flag: if true, returns the proposed chunks WITHOUT persisting (dry-run)
 *
 * Request body (JSON, max 2 MB):
 *   title:        string   (required)
 *   content:      string   (required, min 30 chars)
 *   source_tool:  string   (optional slug; default 'dashboard-save')
 *   tags:         string[] | string CSV (optional, max 20 tags, 32 chars each)
 *   category:     string   (optional; default 'tool-output')
 *   language:     string   (optional; default 'no')
 *   author:       string   (optional)
 *   kind:         'tool_output'|'chat_answer'|'manual'  (default 'tool_output')
 *   preview:      bool     (optional; if true, return chunk preview without saving)
 *
 * Response (saved):
 *   { ok, document_id, chunks, status }
 * Response (preview):
 *   { ok, preview:true, chunks: [...], word_count }
 */

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'];
$corpusId = (int)$tenant['corpus_id'];

$input = dbnToolsJsonInput(2_000_000);

$title = trim((string)($input['title'] ?? ''));
if ($title === '') dbnToolsError('title is required.', 400, 'missing_title');
if (mb_strlen($title, 'UTF-8') > 500) dbnToolsError('title too long (max 500).', 422, 'title_too_long');

$content = trim((string)($input['content'] ?? ''));
if (mb_strlen($content, 'UTF-8') < 30) dbnToolsError('content too short (min 30 chars).', 400, 'content_too_short');
if (mb_strlen($content, 'UTF-8') > 1_900_000) dbnToolsError('content exceeds 2 MB.', 422, 'content_too_large');

$sourceTool = trim((string)($input['source_tool'] ?? 'dashboard-save'));
$sourceTool = substr(preg_replace('/[^a-z0-9\-_]/', '', strtolower($sourceTool)) ?: 'dashboard-save', 0, 64);

$rawTags = $input['tags'] ?? '';
$tagList = is_array($rawTags)
    ? array_map('strval', $rawTags)
    : array_map('trim', explode(',', (string)$rawTags));
$tagList = array_values(array_filter(array_map(fn($t) => substr(trim($t), 0, 32), $tagList)));
$tagList = array_slice($tagList, 0, 20);
$tagsCsv = implode(',', $tagList);

$category = strtolower(trim((string)($input['category'] ?? 'tool-output')));
$category = substr(preg_replace('/[^a-z0-9\-_]/', '', $category) ?: 'tool-output', 0, 50);

$language = trim((string)($input['language'] ?? 'no')) ?: 'no';
$author   = trim((string)($input['author']   ?? '')) ?: null;

$kind = (string)($input['kind'] ?? 'tool_output');
$importMethod = match ($kind) {
    'chat_answer' => 'chat_answer',
    'manual'      => 'manual',
    default       => 'tool_output',
};

$preview = !empty($input['preview']);
$wordCount = str_word_count($content);

dbnToolsBootCaveau();

try {
    if ($preview) {
        require_once dbnToolsAiPortalRoot() . '/lib/ai/TextChunker.php';
        $chunker = new TextChunker();
        $chunks  = $chunker->chunk($content);
        $sample  = array_slice($chunks, 0, 8);
        dbnToolsRespond([
            'ok'         => true,
            'preview'    => true,
            'word_count' => $wordCount,
            'chunks'     => array_map(fn($c) => [
                'section_title' => (string)($c['section_title'] ?? ''),
                'word_count'    => (int)str_word_count((string)($c['content'] ?? '')),
                'snippet'       => mb_substr((string)($c['content'] ?? ''), 0, 240, 'UTF-8'),
            ], $sample),
            'total_chunks' => count($chunks),
        ]);
    }

    $db  = getDb();
    $ins = $db->prepare("
        INSERT INTO client_documents
            (client_id, corpus_id, title, source_type, content, category, language,
             tags, author, import_method, source_tool, word_count, status)
        VALUES (?, ?, ?, 'text', ?, ?, ?, ?, ?, ?, ?, ?, 'pending')
    ");
    $ins->execute([
        $clientId, $corpusId, $title, $content, $category, $language,
        $tagsCsv, $author, $importMethod, $sourceTool, $wordCount,
    ]);
    $docId = (int)$db->lastInsertId();

    $rag    = new ClientRagPipeline($clientId);
    $chunks = $rag->ingestDocument($docId);

    dbnToolsRespond([
        'ok'          => true,
        'document_id' => $docId,
        'chunks'      => (int)$chunks,
        'status'      => 'ready',
    ], 201);
} catch (Throwable $e) {
    if (isset($docId)) {
        try {
            $db->prepare("UPDATE client_documents SET status='error', error_message=? WHERE id=?")
               ->execute([substr($e->getMessage(), 0, 1000), $docId]);
        } catch (Throwable $ignored) { /* non-fatal */ }
        dbnToolsError(
            'Saved to corpus but indexing failed: ' . $e->getMessage(),
            500, 'index_failed',
            ['document_id' => $docId]
        );
    }
    dbnToolsError('Save failed: ' . $e->getMessage(), 500, 'save_failed');
}
