import { unlink, writeFile } from "fs/promises";
import path from "path";
import { NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import {
  CAPTURE_MAX_UPLOAD_BYTES,
  CAPTURE_UPLOAD_DIR,
  createCaptureStoredFilename,
  ensureCaptureUploadDir,
  getCaptureEvidenceKindFromMimeType,
  isAllowedCaptureMimeType,
} from "@/lib/capture";
import { createCaptureEvidenceUpload } from "@/lib/capture";

function isUploadLikeFile(value: FormDataEntryValue | null): value is File {
  if (!value || typeof value === "string") {
    return false;
  }

  const candidate = value as Partial<File>;
  return (
    typeof candidate.size === "number" &&
    typeof candidate.type === "string" &&
    typeof candidate.arrayBuffer === "function"
  );
}

export async function POST(request: Request) {
  const session = await getServerSession(authOptions);
  if (!session?.user) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const formData = await request.formData();
  const title = String(formData.get("title") ?? "").trim();
  const note = String(formData.get("note") ?? "").trim() || null;
  const weekStart = String(formData.get("weekStart") ?? "").trim() || undefined;
  const department = String(formData.get("department") ?? "").trim() || undefined;
  const rowId = String(formData.get("rowId") ?? "").trim() || undefined;
  const initiativeId = String(formData.get("initiativeId") ?? "").trim() || undefined;
  const taskId = String(formData.get("taskId") ?? "").trim() || undefined;
  const fileValue = formData.get("file");

  if (!title) {
    return NextResponse.json({ error: "title is required." }, { status: 400 });
  }

  if (!isUploadLikeFile(fileValue)) {
    return NextResponse.json({ error: "file is required." }, { status: 400 });
  }

  if (fileValue.size <= 0) {
    return NextResponse.json({ error: "file is empty." }, { status: 400 });
  }

  if (fileValue.size > CAPTURE_MAX_UPLOAD_BYTES) {
    return NextResponse.json({ error: "file exceeds 10 MB limit." }, { status: 400 });
  }

  if (!isAllowedCaptureMimeType(fileValue.type)) {
    return NextResponse.json({ error: "Unsupported file type." }, { status: 400 });
  }

  await ensureCaptureUploadDir();
  const storagePath = createCaptureStoredFilename(fileValue.type);
  const absolutePath = path.join(CAPTURE_UPLOAD_DIR, storagePath);
  const bytes = Buffer.from(await fileValue.arrayBuffer());

  try {
    await writeFile(absolutePath, bytes);

    const evidence = await createCaptureEvidenceUpload({
      viewer: {
        userId: session.user.id,
        role: session.user.role,
        department: session.user.department ?? null,
      },
      weekStartInput: weekStart,
      department,
      rowId,
      initiativeId,
      taskId,
      title,
      note,
      storagePath,
      mimeType: fileValue.type,
      sizeBytes: fileValue.size,
      kind: getCaptureEvidenceKindFromMimeType(fileValue.type),
    });

    return NextResponse.json({ ok: true, evidence });
  } catch (error) {
    await unlink(absolutePath).catch(() => {
      // best effort cleanup
    });

    const message = error instanceof Error ? error.message : "Unable to upload evidence.";
    if (message === "Forbidden") {
      return NextResponse.json({ error: "Forbidden" }, { status: 403 });
    }

    if (message.includes("not found")) {
      return NextResponse.json({ error: message }, { status: 404 });
    }

    return NextResponse.json({ error: message }, { status: 400 });
  }
}
