import { randomBytes } from "crypto";
import { mkdir, writeFile } from "fs/promises";
import { join } from "path";
import { NextResponse } from "next/server";
import sharp from "sharp";
import { detectImageMime } from "@/lib/image-magic";
import { prisma } from "@/lib/prisma";
import { getSessionUserId } from "@/lib/session";
import { SITE_CONTENT_ID } from "@/lib/site-content-defaults";

const MAX_BYTES = 10 * 1024 * 1024;
const ALLOWED = new Map([
  ["image/jpeg", ".jpg"],
  ["image/png", ".png"],
  ["image/webp", ".webp"],
  ["image/gif", ".gif"],
]);

export async function POST(request: Request) {
  const userId = await getSessionUserId();
  if (!userId) {
    return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
  }

  let formData: FormData;
  try {
    formData = await request.formData();
  } catch {
    return NextResponse.json({ error: "Corps invalide" }, { status: 400 });
  }

  const file = formData.get("file");
  if (!file || !(file instanceof File)) {
    return NextResponse.json({ error: "Fichier manquant" }, { status: 400 });
  }

  if (file.size > MAX_BYTES) {
    return NextResponse.json(
      { error: "Fichier trop volumineux (max 10 Mo)" },
      { status: 400 }
    );
  }

  const ab = await file.arrayBuffer();
  const originalBuf: Buffer = Buffer.from(new Uint8Array(ab));
  const detected = detectImageMime(originalBuf);
  if (!detected || !ALLOWED.has(detected)) {
    return NextResponse.json(
      {
        error:
          "Fichier non reconnu comme image (JPEG, PNG, WebP ou GIF attendu)",
      },
      { status: 400 }
    );
  }
  const ext = ALLOWED.get(detected)!;

  const settings = await prisma.siteContent.findUnique({
    where: { id: SITE_CONTENT_ID },
    select: { uploadImageWidth: true, uploadImageHeight: true },
  });
  const width =
    typeof settings?.uploadImageWidth === "number" && settings.uploadImageWidth > 0
      ? settings.uploadImageWidth
      : 1920;
  const height =
    typeof settings?.uploadImageHeight === "number" && settings.uploadImageHeight > 0
      ? settings.uploadImageHeight
      : 1080;

  let buf: Buffer = originalBuf;
  if (detected !== "image/gif") {
    try {
      let pipeline = sharp(originalBuf, { failOn: "none" }).rotate();
      pipeline = pipeline.resize({
        width,
        height,
        fit: "cover",
        withoutEnlargement: true,
      });

      if (detected === "image/jpeg") {
        buf = await pipeline.jpeg({ quality: 82 }).toBuffer();
      } else if (detected === "image/png") {
        buf = await pipeline.png({ compressionLevel: 9 }).toBuffer();
      } else if (detected === "image/webp") {
        buf = await pipeline.webp({ quality: 82 }).toBuffer();
      } else {
        buf = await pipeline.toBuffer();
      }
    } catch {
      return NextResponse.json(
        { error: "Impossible de traiter cette image" },
        { status: 400 }
      );
    }
  }

  const name = `${randomBytes(16).toString("hex")}${ext}`;
  const dir = join(process.cwd(), "public", "uploads");
  await mkdir(dir, { recursive: true });
  await writeFile(join(dir, name), buf);

  const url = `/uploads/${name}`;
  return NextResponse.json({ url });
}
