import { NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import { mkdir, writeFile, unlink } from "fs/promises";
import { join } from "path";
import { randomUUID } from "crypto";

export async function GET(
  request: NextRequest,
  { params }: { params: { projectId: string } }
) {
  try {
    const session = await getServerSession(authOptions);

    if (!session?.user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const projectId = params.projectId;
    if (!projectId) {
      return NextResponse.json(
        { error: "Project ID is required" },
        { status: 400 }
      );
    }

    const project = await prisma.project.findFirst({
      where: {
        id: projectId,
        clientId: session.user.id,
      },
      include: {
        category: true,
        country: true,
      },
    });

    if (!project) {
      return NextResponse.json(
        { error: "Project not found or access denied" },
        { status: 404 }
      );
    }

    return NextResponse.json({
      success: true,
      data: {
        ...project,
        attachments: project.attachments ? JSON.parse(project.attachments) : [],
      },
    });
  } catch (error) {
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    );
  }
}

export async function PUT(
  request: NextRequest,
  { params }: { params: { projectId: string } }
) {
  try {
    const session = await getServerSession(authOptions);
    if (!session?.user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }
    const user = session.user as any;
    const formData = await request.formData();

    const projectId = params.projectId;
    if (!projectId)
      return NextResponse.json(
        { error: "Project ID is required" },
        { status: 400 }
      );

    const existingProject = await prisma.project.findUnique({
      where: { id: projectId },
    });
    if (!existingProject)
      return NextResponse.json({ error: "Project not found" }, { status: 404 });

    const title = (formData.get("title") as string) || existingProject.title;
    const description =
      (formData.get("description") as string) || existingProject.description;
    const budget =
      parseFloat(formData.get("budget") as string) || existingProject.budget;
    const duration =
      parseInt(formData.get("duration") as string) || existingProject.duration;
    const categoryId =
      (formData.get("categoryId") as string) || existingProject.categoryId;
    const countryId =
      (formData.get("countryId") as string) || existingProject.countryId;
    const city = (formData.get("city") as string) || existingProject.city;
    const zipCode =
      (formData.get("zipCode") as string) || existingProject.zipCode;

    let skills = existingProject.skills;
    const skillsInput = formData.get("skills") as string;
    if (skillsInput?.trim()) {
      try {
        skills = JSON.stringify(JSON.parse(skillsInput));
      } catch {
        skills = JSON.stringify([skillsInput]);
      }
    }

    const attachments = formData.getAll("attachments") as File[];
    const uploadedFiles: any[] = [];

    if (attachments?.length) {
      const uploadDir = join(process.cwd(), "public", "uploads", "projects");
      await mkdir(uploadDir, { recursive: true });

      for (const file of attachments) {
        if (file.size <= 0) continue;
        const buffer = Buffer.from(await file.arrayBuffer());
        const ext = file.name.split(".").pop();
        const fileName = `${randomUUID()}.${ext}`;
        const filePath = join(uploadDir, fileName);
        await writeFile(filePath, buffer);

        uploadedFiles.push({
          id: `file-${randomUUID()}`,
          name: file.name,
          originalName: file.name,
          size: `${(file.size / (1024 * 1024)).toFixed(1)} MB`,
          type: file.type,
          url: `/uploads/projects/${fileName}`,
          uploadedBy: user.email || "Unknown",
          createdAt: new Date().toISOString(),
        });
      }
    }

    const removedFiles = (formData.getAll("removedFiles") as string[]) || [];
    const oldAttachments = existingProject.attachments
      ? JSON.parse(existingProject.attachments)
      : [];

    const normalize = (url: string) => url.replace(/^\/+/, "");

    for (const file of oldAttachments) {
      if (removedFiles.some((url) => normalize(url) === normalize(file.url))) {
        const filePath = join(process.cwd(), "public", normalize(file.url));
        await unlink(filePath).catch(() => {}); // ignore if not found
      }
    }

    const filteredOldAttachments = oldAttachments.filter(
      (file: any) =>
        !removedFiles.some((url) => normalize(url) === normalize(file.url))
    );
    const updatedAttachments = [...filteredOldAttachments, ...uploadedFiles];

    const updatedProject = await prisma.project.update({
      where: { id: projectId },
      data: {
        title,
        description,
        budget,
        duration,
        categoryId,
        countryId,
        city,
        zipCode,
        skills,
        attachments: JSON.stringify(updatedAttachments),
      },
      include: { category: true, country: true },
    });

    return NextResponse.json({
      success: true,
      message: "Project updated successfully",
      project: updatedProject,
    });
  } catch (error) {
    return NextResponse.json(
      {
        error: "Error processing request",
        details: error instanceof Error ? error.message : error,
      },
      { status: 500 }
    );
  }
}
