import { NextRequest, NextResponse } from "next/server";
import fs from "fs";
import path from "path";
import {
  readMetadata, writeMetadata, getUploadsDir,
  sanitizeFilename, safeUploadPath, thumbPathFor,
} from "@/lib/store";

const ALLOWED_PATCH_KEYS = new Set([
  "name", "categoryId", "tags", "starred", "note", "documentDate", "frist", "deletedAt",
]);

export async function GET() {
  const metadata = readMetadata();
  return NextResponse.json(metadata);
}

export async function PATCH(req: NextRequest) {
  const body = await req.json();
  const { id, ...rawUpdates } = body ?? {};

  if (typeof id !== "string") {
    return NextResponse.json({ error: "id required" }, { status: 400 });
  }

  // Accept only known fields — block clients from setting things like
  // `storedName`, `size`, `id` etc.
  const updates: Record<string, unknown> = {};
  for (const k of Object.keys(rawUpdates)) {
    if (ALLOWED_PATCH_KEYS.has(k)) updates[k] = rawUpdates[k];
  }

  const metadata = readMetadata();
  if (!metadata.files[id]) {
    return NextResponse.json({ error: "File not found" }, { status: 404 });
  }

  const file       = metadata.files[id];
  const uploadsDir = getUploadsDir();

  if (typeof updates.name === "string" && updates.name !== file.name) {
    const oldStoredName = file.storedName ?? (id + path.extname(file.name));
    const oldResolved   = safeUploadPath(oldStoredName);
    const oldExt        = path.extname(oldStoredName);
    const requestedBase = path.basename(updates.name as string, path.extname(updates.name as string));
    const sanitizedName = sanitizeFilename(requestedBase + oldExt, oldExt);

    let candidate = sanitizedName;
    let counter   = 1;
    while (
      counter < 10_000 &&
      fs.existsSync(path.join(uploadsDir, candidate)) &&
      candidate !== oldStoredName
    ) {
      const base = path.basename(sanitizedName, oldExt);
      candidate  = `${base}_${counter}${oldExt}`;
      counter++;
    }

    const newResolved = safeUploadPath(candidate);
    if (!newResolved) {
      return NextResponse.json({ error: "Invalid name" }, { status: 400 });
    }

    if (oldResolved && fs.existsSync(oldResolved)) {
      fs.renameSync(oldResolved, newResolved);
    }
    updates.storedName = candidate;
    updates.name       = candidate;
  }

  metadata.files[id] = { ...file, ...updates };
  writeMetadata(metadata);
  return NextResponse.json(metadata.files[id]);
}

// DELETE moves to trash (soft delete) by default.
// Pass ?permanent=1 to actually remove the file from disk.
export async function DELETE(req: NextRequest) {
  const { searchParams } = new URL(req.url);
  const id        = searchParams.get("id");
  const permanent = searchParams.get("permanent") === "1";

  if (!id) return NextResponse.json({ error: "No id" }, { status: 400 });

  const metadata = readMetadata();
  const file = metadata.files[id];
  if (!file) return NextResponse.json({ error: "Not found" }, { status: 404 });

  if (!permanent) {
    metadata.files[id] = { ...file, deletedAt: new Date().toISOString() };
    writeMetadata(metadata);
    return NextResponse.json({ success: true, softDeleted: true });
  }

  const storedName = file.storedName ?? (id + path.extname(file.originalName));
  const filePath   = safeUploadPath(storedName);
  if (filePath && fs.existsSync(filePath)) fs.unlinkSync(filePath);

  const thumb = thumbPathFor(id);
  if (fs.existsSync(thumb)) fs.unlinkSync(thumb);

  delete metadata.files[id];
  writeMetadata(metadata);
  return NextResponse.json({ success: true, softDeleted: false });
}
