<?php
/**
 * /api/dashboard/categories.php — tenant-managed category dictionary.
 *
 * GET  ?action=list                       → { ok, categories: [...] }
 *   Auto-seeds defaults if dictionary empty for this tenant.
 *
 * POST ?action=create body: { slug, label, color?, icon? }
 * POST ?action=update body: { id, label?, color?, icon?, sort_order? }
 * POST ?action=delete body: { id }   — blocked if is_system=1
 * 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');  listCats($db, $clientId);                        break;
        case 'create':  dbnToolsRequireMethod('POST'); createCat($db, $clientId, $userId, $tenantRole); break;
        case 'update':  dbnToolsRequireMethod('POST'); updateCat($db, $clientId, $userId, $tenantRole); break;
        case 'delete':  dbnToolsRequireMethod('POST'); deleteCat($db, $clientId, $userId, $tenantRole); break;
        case 'reorder': dbnToolsRequireMethod('POST'); reorderCats($db, $clientId);                     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/categories] ' . $e->getMessage());
    dbnToolsError('Category operation failed.', 500, 'op_failed');
}

function listCats(PDO $db, int $clientId): void
{
    dbnDmsSeedDefaultCategoriesIfEmpty($clientId);
    $stmt = $db->prepare(
        'SELECT id, slug, label, color, icon, sort_order, is_system, created_at
         FROM client_categories
         WHERE client_id = ?
         ORDER BY sort_order ASC, label ASC'
    );
    $stmt->execute([$clientId]);

    // Also fetch usage counts.
    $counts = $db->prepare(
        "SELECT category, COUNT(*) AS n
         FROM client_documents
         WHERE client_id = ? AND deleted_at IS NULL
         GROUP BY category"
    );
    $counts->execute([$clientId]);
    $countMap = [];
    foreach ($counts->fetchAll() as $r) {
        $countMap[(string)$r['category']] = (int)$r['n'];
    }

    $rows = $stmt->fetchAll();
    foreach ($rows as &$r) {
        $r['doc_count'] = $countMap[(string)$r['slug']] ?? 0;
        $r['is_system'] = (int)$r['is_system'] === 1;
    }
    dbnToolsRespond(['ok' => true, 'categories' => $rows]);
}

function createCat(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    if (!in_array($tenantRole, ['editor','admin','owner'], true)) {
        dbnToolsError('Forbidden.', 403, 'forbidden');
    }
    $input = dbnToolsJsonInput(10_000);
    $slug  = strtolower(trim((string)($input['slug'] ?? '')));
    $slug  = preg_replace('/[^a-z0-9\-_]/', '', $slug) ?: '';
    $label = trim((string)($input['label'] ?? ''));
    $color = trim((string)($input['color'] ?? ''));
    $icon  = trim((string)($input['icon'] ?? ''));

    if ($slug === '' || mb_strlen($slug, 'UTF-8') > 50) {
        dbnToolsError('Slug is required (lowercase, 1–50, [a-z0-9-_]).', 422, 'invalid_slug');
    }
    if ($label === '' || mb_strlen($label, 'UTF-8') > 100) {
        dbnToolsError('Label is required (1–100).', 422, 'invalid_label');
    }
    if ($color !== '' && !preg_match('/^#[0-9a-fA-F]{6}$/', $color)) {
        dbnToolsError('Invalid color.', 422, 'invalid_color');
    }

    try {
        $stmt = $db->prepare(
            'INSERT INTO client_categories (client_id, slug, label, color, icon, sort_order, is_system, created_at)
             VALUES (?, ?, ?, ?, ?, 999, 0, NOW())'
        );
        $stmt->execute([
            $clientId, $slug, $label,
            $color !== '' ? $color : null,
            $icon !== ''  ? substr($icon, 0, 40) : null,
        ]);
    } catch (PDOException $e) {
        if ((int)$e->errorInfo[1] === 1062) {
            dbnToolsError('A category with this slug already exists.', 409, 'duplicate_slug');
        }
        throw $e;
    }
    $id = (int)$db->lastInsertId();
    dbnDmsLogAudit($clientId, $userId, 'category_create', ['slug' => $slug]);
    dbnToolsRespond(['ok' => true, 'id' => $id], 201);
}

function updateCat(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    if (!in_array($tenantRole, ['editor','admin','owner'], true)) {
        dbnToolsError('Forbidden.', 403, 'forbidden');
    }
    $input = dbnToolsJsonInput(10_000);
    $id    = (int)($input['id'] ?? 0);
    if ($id <= 0) {
        dbnToolsError('id is required.', 400, 'missing_id');
    }
    $fields = [];
    $params = [];
    if (array_key_exists('label', $input)) {
        $label = trim((string)$input['label']);
        if ($label === '' || mb_strlen($label, 'UTF-8') > 100) {
            dbnToolsError('Invalid label.', 422, 'invalid_label');
        }
        $fields[] = 'label = ?'; $params[] = $label;
    }
    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 (array_key_exists('sort_order', $input)) {
        $fields[] = 'sort_order = ?'; $params[] = (int)$input['sort_order'];
    }
    if (!$fields) {
        dbnToolsError('Nothing to update.', 400, 'no_fields');
    }
    $params[] = $id;
    $params[] = $clientId;
    $stmt = $db->prepare('UPDATE client_categories SET ' . implode(', ', $fields) . ' WHERE id = ? AND client_id = ?');
    $stmt->execute($params);
    dbnDmsLogAudit($clientId, $userId, 'category_update', ['id' => $id]);
    dbnToolsRespond(['ok' => true]);
}

function deleteCat(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    if (!in_array($tenantRole, ['admin','owner'], true)) {
        dbnToolsError('Forbidden.', 403, 'forbidden');
    }
    $input = dbnToolsJsonInput(2_000);
    $id    = (int)($input['id'] ?? 0);
    if ($id <= 0) {
        dbnToolsError('id is required.', 400, 'missing_id');
    }
    $row = $db->prepare('SELECT slug, is_system FROM client_categories WHERE id = ? AND client_id = ?');
    $row->execute([$id, $clientId]);
    $existing = $row->fetch();
    if (!$existing) {
        dbnToolsError('Not found.', 404, 'not_found');
    }
    if ((int)$existing['is_system'] === 1) {
        dbnToolsError('System categories cannot be deleted.', 422, 'is_system');
    }
    // Reassign any docs in this category to uncategorized.
    $db->prepare("UPDATE client_documents SET category = 'uncategorized' WHERE client_id = ? AND category = ?")
       ->execute([$clientId, $existing['slug']]);
    $del = $db->prepare('DELETE FROM client_categories WHERE id = ? AND client_id = ?');
    $del->execute([$id, $clientId]);
    dbnDmsLogAudit($clientId, $userId, 'category_delete', ['id' => $id, 'slug' => $existing['slug']]);
    dbnToolsRespond(['ok' => true]);
}

function reorderCats(PDO $db, int $clientId): 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_categories SET sort_order = ? WHERE id = ? AND client_id = ?');
    foreach ($ids as $i => $id) {
        $upd->execute([$i, $id, $clientId]);
    }
    dbnToolsRespond(['ok' => true, 'reordered' => count($ids)]);
}
