<?php
/**
 * /api/dashboard/trash.php — trashed documents + folders, restore + permanent purge.
 *
 * GET  ?action=list&offset=&limit=         → { ok, total, items: [...] }
 * POST ?action=restore body: { document_ids?: [..], folder_ids?: [..] }
 * POST ?action=purge   body: { document_ids?: [..], folder_ids?: [..], all?: bool }
 *                       — admin/owner only for `all`
 */

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');
            listTrash($db, $clientId, $userId, $tenantRole);
            break;
        case 'restore':
            dbnToolsRequireMethod('POST');
            restoreTrash($db, $clientId, $userId, $tenantRole);
            break;
        case 'purge':
            dbnToolsRequireMethod('POST');
            purgeTrash($db, $clientId, $userId, $tenantRole);
            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/trash] ' . $e->getMessage());
    dbnToolsError('Trash operation failed.', 500, 'trash_op_failed');
}

function listTrash(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    $offset = max(0, (int)($_GET['offset'] ?? 0));
    $limit  = max(1, min(200, (int)($_GET['limit'] ?? 50)));

    $docs = $db->prepare(
        "SELECT id, title, folder_id, source_type, file_size_bytes, deleted_at, deleted_by,
                DATEDIFF(NOW(), deleted_at) AS days_in_trash
         FROM client_documents
         WHERE client_id = ? AND deleted_at IS NOT NULL
         ORDER BY deleted_at DESC
         LIMIT {$limit} OFFSET {$offset}"
    );
    $docs->execute([$clientId]);
    $docRows = $docs->fetchAll();

    // Filter by ACL
    $visible = [];
    foreach ($docRows as $row) {
        $fid = $row['folder_id'] ? (int)$row['folder_id'] : 0;
        if (dbnDmsUserCanAccessFolder($fid ?: null, 'read', $clientId, $userId, $tenantRole)) {
            $row['kind'] = 'document';
            $row['expires_in_days'] = max(0, DBN_DMS_TRASH_RETENTION_DAYS - (int)$row['days_in_trash']);
            $visible[] = $row;
        }
    }

    $folders = $db->prepare(
        "SELECT id, name, color, deleted_at, deleted_by,
                DATEDIFF(NOW(), deleted_at) AS days_in_trash
         FROM client_folders
         WHERE client_id = ? AND deleted_at IS NOT NULL
         ORDER BY deleted_at DESC LIMIT 200"
    );
    $folders->execute([$clientId]);
    foreach ($folders->fetchAll() as $row) {
        $row['kind'] = 'folder';
        $row['expires_in_days'] = max(0, DBN_DMS_TRASH_RETENTION_DAYS - (int)$row['days_in_trash']);
        $visible[] = $row;
    }

    $countStmt = $db->prepare(
        "SELECT COUNT(*) FROM client_documents WHERE client_id = ? AND deleted_at IS NOT NULL"
    );
    $countStmt->execute([$clientId]);
    $total = (int)$countStmt->fetchColumn();

    dbnToolsRespond([
        'ok'    => true,
        'total' => $total,
        'items' => $visible,
        'retention_days' => DBN_DMS_TRASH_RETENTION_DAYS,
    ]);
}

function restoreTrash(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    $input = dbnToolsJsonInput(20_000);
    $docIds    = sanitizeIdList($input['document_ids'] ?? []);
    $folderIds = sanitizeIdList($input['folder_ids'] ?? []);
    $restoredDocs = 0;
    $restoredFolders = 0;

    if ($docIds) {
        $ph = implode(',', array_fill(0, count($docIds), '?'));
        $rows = $db->prepare("SELECT id, folder_id FROM client_documents WHERE client_id = ? AND id IN ({$ph}) AND deleted_at IS NOT NULL");
        $rows->execute(array_merge([$clientId], $docIds));
        $allowed = [];
        foreach ($rows->fetchAll() as $r) {
            $fid = $r['folder_id'] ? (int)$r['folder_id'] : 0;
            if (dbnDmsUserCanAccessFolder($fid ?: null, 'write', $clientId, $userId, $tenantRole)) {
                $allowed[] = (int)$r['id'];
            }
        }
        if ($allowed) {
            $ph2 = implode(',', array_fill(0, count($allowed), '?'));
            $upd = $db->prepare("UPDATE client_documents SET deleted_at = NULL, deleted_by = NULL WHERE client_id = ? AND id IN ({$ph2})");
            $upd->execute(array_merge([$clientId], $allowed));
            $restoredDocs = $upd->rowCount();
            dbnDmsLogAudit($clientId, $userId ?: null, 'restore', ['ids' => $allowed]);
        }
    }

    if ($folderIds) {
        $ph = implode(',', array_fill(0, count($folderIds), '?'));
        $rows = $db->prepare("SELECT id FROM client_folders WHERE client_id = ? AND id IN ({$ph}) AND deleted_at IS NOT NULL");
        $rows->execute(array_merge([$clientId], $folderIds));
        $allowed = [];
        foreach ($rows->fetchAll() as $r) {
            if (dbnDmsUserCanAccessFolder((int)$r['id'], 'manage', $clientId, $userId, $tenantRole)) {
                $allowed[] = (int)$r['id'];
            }
        }
        if ($allowed) {
            $ph2 = implode(',', array_fill(0, count($allowed), '?'));
            $upd = $db->prepare("UPDATE client_folders SET deleted_at = NULL, deleted_by = NULL WHERE client_id = ? AND id IN ({$ph2})");
            $upd->execute(array_merge([$clientId], $allowed));
            $restoredFolders = $upd->rowCount();
            dbnDmsLogAudit($clientId, $userId ?: null, 'restore_folder', ['ids' => $allowed]);
        }
    }

    dbnToolsRespond(['ok' => true, 'restored_documents' => $restoredDocs, 'restored_folders' => $restoredFolders]);
}

function purgeTrash(PDO $db, int $clientId, int $userId, string $tenantRole): void
{
    if (!in_array($tenantRole, ['admin','owner'], true)) {
        dbnToolsError('Permanent purge requires admin role.', 403, 'forbidden');
    }
    $input = dbnToolsJsonInput(20_000);
    $all   = !empty($input['all']);
    $docIds    = sanitizeIdList($input['document_ids'] ?? []);
    $folderIds = sanitizeIdList($input['folder_ids'] ?? []);

    $purgedDocs = 0;
    $purgedFolders = 0;

    if ($all) {
        // Documents
        $docs = $db->prepare("SELECT id, storage_path FROM client_documents WHERE client_id = ? AND deleted_at IS NOT NULL");
        $docs->execute([$clientId]);
        foreach ($docs->fetchAll() as $row) {
            purgeDocument($db, $clientId, (int)$row['id'], $row['storage_path'] ?? null);
            $purgedDocs++;
        }
        $delFolders = $db->prepare("DELETE FROM client_folders WHERE client_id = ? AND deleted_at IS NOT NULL");
        $delFolders->execute([$clientId]);
        $purgedFolders = $delFolders->rowCount();
        dbnDmsLogAudit($clientId, $userId ?: null, 'purge_all', ['documents' => $purgedDocs, 'folders' => $purgedFolders]);
    } else {
        if ($docIds) {
            $ph = implode(',', array_fill(0, count($docIds), '?'));
            $rows = $db->prepare("SELECT id, storage_path FROM client_documents WHERE client_id = ? AND id IN ({$ph}) AND deleted_at IS NOT NULL");
            $rows->execute(array_merge([$clientId], $docIds));
            foreach ($rows->fetchAll() as $row) {
                purgeDocument($db, $clientId, (int)$row['id'], $row['storage_path'] ?? null);
                $purgedDocs++;
            }
        }
        if ($folderIds) {
            $ph = implode(',', array_fill(0, count($folderIds), '?'));
            $del = $db->prepare("DELETE FROM client_folders WHERE client_id = ? AND id IN ({$ph}) AND deleted_at IS NOT NULL");
            $del->execute(array_merge([$clientId], $folderIds));
            $purgedFolders = $del->rowCount();
        }
        dbnDmsLogAudit($clientId, $userId ?: null, 'purge', ['documents' => $purgedDocs, 'folders' => $purgedFolders]);
    }

    dbnToolsRespond(['ok' => true, 'purged_documents' => $purgedDocs, 'purged_folders' => $purgedFolders]);
}

function purgeDocument(PDO $db, int $clientId, int $docId, ?string $storagePath): void
{
    // Delete chunks + Qdrant points + on-disk file + versions
    try {
        $verRows = $db->prepare('SELECT storage_path FROM client_document_versions WHERE document_id = ? AND client_id = ?');
        $verRows->execute([$docId, $clientId]);
        foreach ($verRows->fetchAll() as $vr) {
            if (!empty($vr['storage_path']) && is_file($vr['storage_path'])) {
                @unlink($vr['storage_path']);
            }
        }
    } catch (Throwable $e) { /* tolerated */ }

    try {
        $db->prepare('DELETE FROM client_chunks WHERE client_id = ? AND document_id = ?')->execute([$clientId, $docId]);
    } catch (Throwable $e) { /* tolerated */ }

    // Best-effort Qdrant cleanup — issue a delete-by-filter
    try {
        dbnToolsBootCaveau();
        if (class_exists('QdrantClient')) {
            $qd = new QdrantClient();
            $qd->deleteByFilter('bnl_client_chunks', [
                'must' => [
                    ['key' => 'client_id',   'match' => ['value' => $clientId]],
                    ['key' => 'document_id', 'match' => ['value' => $docId]],
                ],
            ]);
        }
    } catch (Throwable $e) { /* tolerated */ }

    if ($storagePath && is_file($storagePath)) {
        @unlink($storagePath);
    }
    // Also remove the versions folder if it exists.
    if ($storagePath) {
        $verDir = dirname($storagePath) . '/' . $docId . '_versions';
        if (is_dir($verDir)) {
            foreach (glob($verDir . '/*') ?: [] as $f) { @unlink($f); }
            @rmdir($verDir);
        }
    }

    $db->prepare('DELETE FROM client_documents WHERE id = ? AND client_id = ?')->execute([$docId, $clientId]);
}

function sanitizeIdList(mixed $raw): array
{
    if (!is_array($raw)) return [];
    $ids = array_values(array_unique(array_filter(array_map('intval', $raw), fn($v) => $v > 0)));
    return array_slice($ids, 0, 500);
}
