<?php
/**
 * /api/dashboard/documents.php — CRUD for the current user's CaveauAI documents.
 *
 * GET  ?action=list&offset=0&limit=20&q=&status=&category=
 *      → { ok, total, documents: [...] }
 * GET  ?action=get&id=123
 *      → { ok, document: {...} }
 * POST ?action=update  body: { id, title?, category?, tags?, language?, author? }
 *      → { ok, document: {...} }
 * POST ?action=delete  body: { ids: [1,2,3] }
 *      → { ok, deleted: N }
 *
 * All filtered by client_id from the dashboard session — no cross-tenant access possible.
 */

declare(strict_types=1);

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

dbnToolsRequireAuth();

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

$method = strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET'));
$action = (string)($_GET['action'] ?? ($method === 'POST' ? '' : 'list'));

$db = dbnToolsDb();

switch ($action) {
    case 'list':
        dbnToolsRequireMethod('GET');
        respondList($db, $clientId);
        break;
    case 'get':
        dbnToolsRequireMethod('GET');
        respondGet($db, $clientId);
        break;
    case 'update':
        dbnToolsRequireMethod('POST');
        respondUpdate($db, $clientId);
        break;
    case 'delete':
        dbnToolsRequireMethod('POST');
        respondDelete($db, $clientId);
        break;
    default:
        dbnToolsError('Unknown action.', 400, 'unknown_action');
}

function respondList(PDO $db, int $clientId): void
{
    $offset = max(0, (int)($_GET['offset'] ?? 0));
    $limit  = max(1, min(100, (int)($_GET['limit'] ?? 20)));
    $q        = trim((string)($_GET['q'] ?? ''));
    $status   = trim((string)($_GET['status'] ?? ''));
    $category = trim((string)($_GET['category'] ?? ''));

    $where  = ['client_id = ?'];
    $params = [$clientId];

    if ($q !== '') {
        $where[]  = '(title LIKE ? OR tags LIKE ?)';
        $like     = '%' . str_replace(['%', '_'], ['\%', '\_'], $q) . '%';
        $params[] = $like;
        $params[] = $like;
    }
    $allowedStatus = ['pending', 'processing', 'ready', 'error'];
    if ($status !== '' && in_array($status, $allowedStatus, true)) {
        $where[]  = 'status = ?';
        $params[] = $status;
    }
    if ($category !== '') {
        $where[]  = 'category = ?';
        $params[] = $category;
    }
    $sourceType = trim((string)($_GET['source_type'] ?? ''));
    $allowedSourceTypes = ['text', 'audio', 'url', 'tool-output', 'upload'];
    if ($sourceType !== '' && in_array($sourceType, $allowedSourceTypes, true)) {
        $where[]  = 'source_type = ?';
        $params[] = $sourceType;
    }

    $whereSql = 'WHERE ' . implode(' AND ', $where);

    $countStmt = $db->prepare("SELECT COUNT(*) FROM client_documents {$whereSql}");
    $countStmt->execute($params);
    $total = (int)$countStmt->fetchColumn();

    $sql = "SELECT id, title, source_type, language, category, tags, author,
                   source_tool, import_method, status, word_count, chunk_count,
                   file_size_bytes, source_url, error_message,
                   created_at, updated_at
            FROM client_documents
            {$whereSql}
            ORDER BY id DESC
            LIMIT {$limit} OFFSET {$offset}";
    $stmt = $db->prepare($sql);
    $stmt->execute($params);
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

    dbnToolsRespond([
        'ok'        => true,
        'total'     => $total,
        'offset'    => $offset,
        'limit'     => $limit,
        'documents' => array_map('shapeDoc', $rows),
    ]);
}

function respondGet(PDO $db, int $clientId): void
{
    $id = (int)($_GET['id'] ?? 0);
    if ($id <= 0) {
        dbnToolsError('id is required.', 400, 'missing_id');
    }
    $stmt = $db->prepare(
        'SELECT * FROM client_documents WHERE id = ? AND client_id = ? LIMIT 1'
    );
    $stmt->execute([$id, $clientId]);
    $doc = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$doc) {
        dbnToolsError('Document not found.', 404, 'not_found');
    }

    $chunks = $db->prepare(
        'SELECT id, content, section_title
         FROM client_chunks
         WHERE client_id = ? AND document_id = ?
         ORDER BY id ASC
         LIMIT 200'
    );
    try {
        $chunks->execute([$clientId, $id]);
        $chunkRows = $chunks->fetchAll(PDO::FETCH_ASSOC);
    } catch (Throwable $e) {
        $chunkRows = [];
    }

    dbnToolsRespond([
        'ok'       => true,
        'document' => shapeDoc($doc) + ['content' => (string)$doc['content']],
        'chunks'   => $chunkRows,
    ]);
}

function respondUpdate(PDO $db, int $clientId): void
{
    $input = dbnToolsJsonInput(20_000);
    $id    = (int)($input['id'] ?? 0);
    if ($id <= 0) {
        dbnToolsError('id is required.', 400, 'missing_id');
    }

    $fields = [];
    $params = [];
    $allowed = [
        'title'    => ['VARCHAR', 500],
        'category' => ['VARCHAR', 50],
        'tags'     => ['VARCHAR', 500],
        'language' => ['VARCHAR', 10],
        'author'   => ['VARCHAR', 200],
    ];
    foreach ($allowed as $col => [$kind, $max]) {
        if (!array_key_exists($col, $input)) {
            continue;
        }
        $val = trim((string)$input[$col]);
        if (mb_strlen($val, 'UTF-8') > $max) {
            dbnToolsError("Field {$col} exceeds {$max} chars.", 422, 'field_too_long');
        }
        $fields[] = "{$col} = ?";
        $params[] = $val !== '' ? $val : null;
    }
    if (!$fields) {
        dbnToolsError('No editable fields supplied.', 400, 'no_fields');
    }
    $params[] = $id;
    $params[] = $clientId;

    $stmt = $db->prepare(
        'UPDATE client_documents SET ' . implode(', ', $fields)
        . ', updated_at = NOW() WHERE id = ? AND client_id = ?'
    );
    $stmt->execute($params);

    $stmt = $db->prepare('SELECT * FROM client_documents WHERE id = ? AND client_id = ? LIMIT 1');
    $stmt->execute([$id, $clientId]);
    $doc = $stmt->fetch(PDO::FETCH_ASSOC);

    dbnToolsRespond(['ok' => true, 'document' => shapeDoc($doc ?: [])]);
}

function respondDelete(PDO $db, int $clientId): void
{
    $input = dbnToolsJsonInput(50_000);
    $ids   = $input['ids'] ?? [];
    if (!is_array($ids) || !$ids) {
        dbnToolsError('ids array is required.', 400, 'missing_ids');
    }
    $ids = array_values(array_unique(array_map('intval', $ids)));
    $ids = array_filter($ids, fn($v) => $v > 0);
    if (!$ids) {
        dbnToolsError('No valid ids.', 400, 'invalid_ids');
    }
    if (count($ids) > 200) {
        dbnToolsError('Cannot delete more than 200 documents at once.', 422, 'too_many');
    }

    $placeholders = implode(',', array_fill(0, count($ids), '?'));
    $stmt = $db->prepare(
        "DELETE FROM client_documents
         WHERE client_id = ? AND id IN ({$placeholders})"
    );
    $stmt->execute(array_merge([$clientId], $ids));

    try {
        $chunks = $db->prepare(
            "DELETE FROM client_chunks WHERE client_id = ? AND document_id IN ({$placeholders})"
        );
        $chunks->execute(array_merge([$clientId], $ids));
    } catch (Throwable $e) {
        // table may be filtered to client_id only; non-fatal
    }

    dbnToolsRespond(['ok' => true, 'deleted' => $stmt->rowCount()]);
}

function shapeDoc(array $row): array
{
    return [
        'id'             => (int)($row['id'] ?? 0),
        'title'          => (string)($row['title'] ?? ''),
        'source_type'    => (string)($row['source_type'] ?? ''),
        'language'       => (string)($row['language'] ?? ''),
        'category'       => (string)($row['category'] ?? ''),
        'tags'           => (string)($row['tags'] ?? ''),
        'author'         => $row['author'] ?? null,
        'source_url'     => $row['source_url'] ?? null,
        'source_tool'    => $row['source_tool'] ?? null,
        'import_method'  => (string)($row['import_method'] ?? ''),
        'status'         => (string)($row['status'] ?? ''),
        'word_count'     => (int)($row['word_count'] ?? 0),
        'chunk_count'    => (int)($row['chunk_count'] ?? 0),
        'file_size_bytes'=> (int)($row['file_size_bytes'] ?? 0),
        'error_message'  => $row['error_message'] ?? null,
        'created_at'     => (string)($row['created_at'] ?? ''),
        'updated_at'     => (string)($row['updated_at'] ?? ''),
    ];
}
