import { NextRequest, NextResponse } from "next/server";
import { connectDB } from "@/lib/db";
import { ClientPhotoFolder } from "@/models/ClientPhotoFolder";
import { Order } from "@/models/Order";
import { PhotoRating } from "@/models/PhotoRating";
import { getSessionClientId } from "@/lib/auth";
import { hasPermission } from "@/lib/adminAuth";
import { fetchPreviewSafe, fetchOriginal } from "@/lib/nextcloud";
import { applyWatermark, needsPhotoWatermark } from "@/lib/watermark";

export async function GET(
  req: NextRequest,
  { params }: { params: Promise<{ folderId: string; filename: string }> }
) {
  const { folderId, filename } = await params;
  // filename kommt direkt aus der URL — ohne diese Prüfung könnte ein
  // eingeschleustes "../" (z. B. per %2F-Segment) Dateien außerhalb des
  // zugewiesenen Ordners auf demselben Nextcloud-Share erreichen.
  if (filename.includes("/") || filename.includes("\\") || filename.includes("..")) {
    return new NextResponse("Not found", { status: 404 });
  }
  const [clientId, isAdmin] = await Promise.all([getSessionClientId(), hasPermission("orders_view")]);
  if (!clientId && !isAdmin) return new NextResponse("Unauthorized", { status: 401 });

  await connectDB();
  const folder = await ClientPhotoFolder.findById(folderId).lean();
  if (!folder || (!isAdmin && String(folder.clientId) !== clientId)) {
    return new NextResponse("Not found", { status: 404 });
  }

  // Kunden dürfen auch über die direkte Bild-URL nicht an noch nicht
  // freigegebene Fotos kommen — nicht nur die Galerie blendet sie aus.
  // Admins sehen weiterhin alles, unabhängig vom Freigabestatus.
  if (!isAdmin) {
    const rating = await PhotoRating.findOne({ folderId, fileName: filename }).select("approvedForDownload").lean();
    if (!rating?.approvedForDownload) {
      return new NextResponse("Not found", { status: 404 });
    }
  }

  // Nur Fotos aus einem noch nicht bezahlten Auftrag bekommen ein
  // Wasserzeichen — Ordner ohne Auftragsbezug (orderId null) sind davon nie
  // betroffen, ebenso TFP-Aufträge (siehe needsPhotoWatermark). Admins sehen
  // die Fotos bewusst genauso wasserzeichenbehaftet wie der Kunde, damit
  // sofort auffällt, ob eine Zahlung noch aussteht.
  let needsWatermark = false;
  if (folder.orderId) {
    const order = await Order.findById(folder.orderId).select("paid compensationType").lean();
    needsWatermark = needsPhotoWatermark(order);
  }

  const variant = req.nextUrl.searchParams.get("variant") === "full" ? "full" : "thumb";
  const filePath = `${folder.nextcloudPath}/${filename}`;

  try {
    if (variant === "thumb") {
      let buffer = await fetchPreviewSafe(filePath, 480);
      if (needsWatermark) buffer = await applyWatermark(buffer);
      return new NextResponse(new Uint8Array(buffer), {
        headers: { "Content-Type": "image/jpeg", "Cache-Control": "private, max-age=3600" },
      });
    }

    let buffer = await fetchOriginal(filePath);
    let mime: string;
    let downloadFilename = filename;
    if (needsWatermark) {
      buffer = await applyWatermark(buffer);
      mime = "image/jpeg";
      // Wasserzeichen rendert immer als JPEG — Dateiname mit der ursprünglichen
      // Endung (z. B. .png) würde sonst nicht zu den tatsächlichen Bytes passen.
      downloadFilename = filename.replace(/\.[^.]+$/, "") + ".jpg";
    } else {
      const ext = filename.split(".").pop()?.toLowerCase();
      mime = ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : "image/jpeg";
    }
    const download = req.nextUrl.searchParams.get("download") === "1";
    return new NextResponse(new Uint8Array(buffer), {
      headers: {
        "Content-Type": mime,
        "Cache-Control": "private, max-age=0, no-store",
        ...(download ? { "Content-Disposition": `attachment; filename="${encodeURIComponent(downloadFilename)}"` } : {}),
      },
    });
  } catch {
    return new NextResponse("Not found", { status: 404 });
  }
}
