<?php
/**
 * /api/dashboard/saved-searches.php — "smart folders" CRUD.
 *
 * GET  ?action=list                       → { ok, items: [...] }   (user-owned + tenant-shared)
 * POST ?action=create body: { name, query, is_shared?, color?, icon? }
 * POST ?action=update body: { id, name?, query?, is_shared?, color?, icon? }
 * POST ?action=delete body: { id }
 * POST ?action=reorder body: { ids: [...] }
 */

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'];
$userId     = (int)($tenant['client_user_id'] ?? 0);
$tenantRole = (string)($tenant['role'] ?? 'editor');

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

try {
    switch ($action) {
        case 'list':    dbnToolsRequireMethod('GET');  listItems($db, $clientId, $userId);            break;
        case 'create':  dbnToolsRequireMethod('POST'); createItem($db, $clientId, $userId, $tenantRole); break;
        case 'update':  dbnToolsRequireMethod('POST'); updateItem($db, $clientId, $userId, $tenantRole); break;
        case 'delete':  dbnToolsRequireMethod('POST'); deleteItem($db, $clientId, $userId, $tenantRole); break;
        case 'reorder': dbnToolsRequireMethod('POST'); reorderItems($db, $clientId, $userId);           break;
        default: dbnToolsError('Unknown action.', 400, 'unknown_action');
    }
} catch (DbnToolsHttpException $e) {
    dbnToolsError($e->getMessage(), $e->status, $e->errorCode, $e->extra);
} catch (Throwable $e) {
    error_log('[dbn-dms/saved-searches] ' . $e->getMessage());
    dbnToolsError('Saved-search operation failed.', 500, 'op_failed');
}

function listItems(PDO $db, int $clientId, int $userId): void
{
    $stmt = $db->prepare(
        'SELECT id, name, icon, color, query_json, is_shared, sort_order, user_id, created_at, updated_at
         FROM client_saved_searches
         WHERE client_id = ? AND (user_id = ? OR is_shared = 1)
         ORDER BY sort_order ASC, name ASC'
    );
    $stmt->execute([$clientId, $userId]);
    $rows = $stmt->fetchAll();
    foreach ($rows as &$r) {
        $r['query']     = json_decode((string)$r['query_json'], true) ?? [];
        $r['is_mine']   = (int)$r['user_id'] === $userId;
        $r['is_shared'] = (int)$r['is_shared'] === 1;
        unset($r['query_json']);
    }
    dbnToolsRespond(['ok' => true, 'items' => $rows]);
}

function createItem(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    $input    = dbnToolsJsonInput(20_000);
    $name     = trim((string)($input['name'] ?? ''));
    $query    = $input['query'] ?? [];
    $isShared = !empty($input['is_shared']);
    $color    = trim((string)($input['color'] ?? ''));
    $icon     = trim((string)($input['icon'] ?? ''));

    if ($name === '' || mb_strlen($name, 'UTF-8') > 120) {
        dbnToolsError('Name is required (1–120 chars).', 422, 'invalid_name');
    }
    if (!is_array($query) || !$query) {
        dbnToolsError('Query payload is required.', 422, 'invalid_query');
    }
    if ($isShared && !in_array($tenantRole, ['editor','admin','owner'], true)) {
        dbnToolsError('Only editors+ can share smart folders.', 403, 'forbidden');
    }
    if ($color !== '' && !preg_match('/^#[0-9a-fA-F]{6}$/', $color)) {
        dbnToolsError('Invalid color.', 422, 'invalid_color');
    }

    $stmt = $db->prepare(
        'INSERT INTO client_saved_searches
            (client_id, user_id, name, icon, color, query_json, is_shared, sort_order, created_at, updated_at)
         VALUES (?, ?, ?, ?, ?, ?, ?, 0, NOW(), NOW())'
    );
    $stmt->execute([
        $clientId, $userId, $name,
        $icon !== '' ? substr($icon, 0, 40) : null,
        $color !== '' ? $color : null,
        json_encode(sanitizeQuery($query), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
        $isShared ? 1 : 0,
    ]);
    $id = (int)$db->lastInsertId();
    dbnDmsLogAudit($clientId, $userId, 'saved_search_create', ['name' => $name, 'id' => $id]);
    dbnToolsRespond(['ok' => true, 'id' => $id], 201);
}

function updateItem(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    $input = dbnToolsJsonInput(20_000);
    $id    = (int)($input['id'] ?? 0);
    if ($id <= 0) {
        dbnToolsError('id is required.', 400, 'missing_id');
    }
    $row = $db->prepare('SELECT user_id, is_shared FROM client_saved_searches WHERE id = ? AND client_id = ?');
    $row->execute([$id, $clientId]);
    $existing = $row->fetch();
    if (!$existing) {
        dbnToolsError('Not found.', 404, 'not_found');
    }
    $isMine = (int)$existing['user_id'] === $userId;
    $canEdit = $isMine || in_array($tenantRole, ['admin','owner'], true);
    if (!$canEdit) {
        dbnToolsError('Forbidden.', 403, 'forbidden');
    }

    $fields = [];
    $params = [];

    if (array_key_exists('name', $input)) {
        $name = trim((string)$input['name']);
        if ($name === '' || mb_strlen($name, 'UTF-8') > 120) {
            dbnToolsError('Invalid name.', 422, 'invalid_name');
        }
        $fields[] = 'name = ?';
        $params[] = $name;
    }
    if (array_key_exists('query', $input)) {
        if (!is_array($input['query']) || !$input['query']) {
            dbnToolsError('Invalid query.', 422, 'invalid_query');
        }
        $fields[] = 'query_json = ?';
        $params[] = json_encode(sanitizeQuery($input['query']), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
    if (array_key_exists('is_shared', $input)) {
        $fields[] = 'is_shared = ?';
        $params[] = !empty($input['is_shared']) ? 1 : 0;
    }
    if (array_key_exists('color', $input)) {
        $color = trim((string)$input['color']);
        if ($color !== '' && !preg_match('/^#[0-9a-fA-F]{6}$/', $color)) {
            dbnToolsError('Invalid color.', 422, 'invalid_color');
        }
        $fields[] = 'color = ?';
        $params[] = $color !== '' ? $color : null;
    }
    if (array_key_exists('icon', $input)) {
        $icon = trim((string)$input['icon']);
        $fields[] = 'icon = ?';
        $params[] = $icon !== '' ? substr($icon, 0, 40) : null;
    }
    if (!$fields) {
        dbnToolsError('Nothing to update.', 400, 'no_fields');
    }
    $params[] = $id;
    $params[] = $clientId;

    $stmt = $db->prepare(
        'UPDATE client_saved_searches SET ' . implode(', ', $fields) . ', updated_at = NOW()
         WHERE id = ? AND client_id = ?'
    );
    $stmt->execute($params);
    dbnDmsLogAudit($clientId, $userId, 'saved_search_update', ['id' => $id]);
    dbnToolsRespond(['ok' => true]);
}

function deleteItem(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    $input = dbnToolsJsonInput(2_000);
    $id    = (int)($input['id'] ?? 0);
    if ($id <= 0) {
        dbnToolsError('id is required.', 400, 'missing_id');
    }
    $row = $db->prepare('SELECT user_id FROM client_saved_searches WHERE id = ? AND client_id = ?');
    $row->execute([$id, $clientId]);
    $existing = $row->fetch();
    if (!$existing) {
        dbnToolsError('Not found.', 404, 'not_found');
    }
    $isMine = (int)$existing['user_id'] === $userId;
    if (!$isMine && !in_array($tenantRole, ['admin','owner'], true)) {
        dbnToolsError('Forbidden.', 403, 'forbidden');
    }
    $del = $db->prepare('DELETE FROM client_saved_searches WHERE id = ? AND client_id = ?');
    $del->execute([$id, $clientId]);
    dbnDmsLogAudit($clientId, $userId, 'saved_search_delete', ['id' => $id]);
    dbnToolsRespond(['ok' => true]);
}

function reorderItems(PDO $db, int $clientId, int $userId): void
{
    $input = dbnToolsJsonInput(20_000);
    $ids   = $input['ids'] ?? [];
    if (!is_array($ids)) {
        dbnToolsError('ids array is required.', 400, 'missing_ids');
    }
    $ids = array_values(array_filter(array_map('intval', $ids), fn($v) => $v > 0));
    $upd = $db->prepare('UPDATE client_saved_searches SET sort_order = ? WHERE id = ? AND client_id = ? AND (user_id = ? OR is_shared = 1)');
    foreach ($ids as $i => $id) {
        $upd->execute([$i, $id, $clientId, $userId]);
    }
    dbnToolsRespond(['ok' => true, 'reordered' => count($ids)]);
}

function sanitizeQuery(array $query): array
{
    $allowed = ['q', 'category', 'status', 'source_type', 'folder_id', 'include_subfolders', 'tags', 'sort', 'dir'];
    $clean = [];
    foreach ($allowed as $key) {
        if (array_key_exists($key, $query)) {
            $clean[$key] = is_array($query[$key]) ? array_slice(array_values($query[$key]), 0, 50) : $query[$key];
        }
    }
    return $clean;
}
