import { logApiError } from "@/lib/api/security";
import { NextResponse } from "next/server";
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
import { uploadAttachmentBuffer } from "@/lib/attachments/server";
import { createRouteClient } from "@/lib/supabase/route";
import type { Attachment } from "@/types";

function getSupabaseAdmin() {
  return createSupabaseClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!,
  );
}

async function resolveEntity(entityType: Attachment["entity_type"], entityId: string) {
  const admin = getSupabaseAdmin();

  if (entityType === "chat_message") {
    const { data: message } = await admin
      .from("chat_messages")
      .select("id,sender_id,thread_id")
      .eq("id", entityId)
      .single();
    if (!message) return null;

    const { data: thread } = await admin
      .from("chat_threads")
      .select("team_id,context_type,context_id")
      .eq("id", message.thread_id)
      .single();

    return {
      id: message.id as string,
      sender_id: message.sender_id as string,
      team_id: (thread?.team_id as string | null) ?? null,
      project_id:
        thread?.context_type === "project" && typeof thread.context_id === "string"
          ? thread.context_id
          : null,
    };
  }

  if (entityType === "project") {
    const { data } = await admin
      .from("projects")
      .select("id,team_id,user_id")
      .eq("id", entityId)
      .single();
    return data ?? null;
  }

  if (entityType === "task") {
    const { data } = await admin
      .from("tasks")
      .select("id,team_id,user_id,project_id")
      .eq("id", entityId)
      .single();
    return data ?? null;
  }

  if (entityType === "invoice") {
    const { data } = await admin
      .from("invoices")
      .select("id,team_id,user_id")
      .eq("id", entityId)
      .single();
    return data ?? null;
  }

  const { data } = await admin
    .from("notes")
    .select("id,team_id,user_id,project_id")
    .eq("id", entityId)
    .single();
  return data ?? null;
}

export async function POST(req: Request) {
  try {
    const supabase = await createRouteClient();
    const { data: { user } } = await supabase.auth.getUser();
    if (!user) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });

    const formData = await req.formData();
    const entityType = formData.get("entityType");
    const entityId = formData.get("entityId");
    const file = formData.get("file");

    if (
      (entityType !== "project" && entityType !== "task" && entityType !== "note" &&
        entityType !== "chat_message" && entityType !== "invoice") ||
      typeof entityId !== "string" ||
      !(file instanceof File)
    ) {
      return NextResponse.json({ error: "Invalid attachment upload payload." }, { status: 400 });
    }

    const entity = await resolveEntity(entityType, entityId);
    if (!entity) {
      return NextResponse.json(
        { error: "You do not have access to the target item for this upload." },
        { status: 403 },
      );
    }

    if (entityType === "chat_message" && "sender_id" in entity && entity.sender_id !== user.id) {
      return NextResponse.json(
        { error: "You can only upload files to your own chat messages." },
        { status: 403 },
      );
    }

    const projectId =
      entityType === "project"
        ? entity.id
        : "project_id" in entity
          ? (entity.project_id as string | null) ?? null
          : null;

    const fileBuffer = Buffer.from(await file.arrayBuffer());
    const data = await uploadAttachmentBuffer({
      userId: user.id,
      teamId: (entity.team_id as string | null) ?? null,
      projectId,
      entityType,
      entityId,
      fileName: file.name,
      mimeType: file.type || null,
      buffer: fileBuffer,
    });

    return NextResponse.json({ attachment: data });
  } catch (error) {
    logApiError("Attachment upload error", error);
    return NextResponse.json(
      { error: error instanceof Error ? error.message : "Attachment upload failed." },
      { status: 500 },
    );
  }
}

export async function DELETE(req: Request) {
  try {
    const supabase = await createRouteClient();
    const { data: { user } } = await supabase.auth.getUser();
    if (!user) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });

    const body = await req.json();
    const attachmentId = typeof body.attachmentId === "string" ? body.attachmentId : null;
    if (!attachmentId) return NextResponse.json({ error: "Attachment id is required." }, { status: 400 });

    const admin = getSupabaseAdmin();
    const { data: attachment } = await admin
      .from("attachments")
      .select("id,storage_path")
      .eq("id", attachmentId)
      .eq("user_id", user.id)
      .single();

    if (!attachment) {
      return NextResponse.json({ error: "Attachment not found or not accessible." }, { status: 404 });
    }

    await admin.from("attachments").delete().eq("id", attachmentId);

    const { error: storageError } = await admin.storage
      .from("attachments")
      .remove([attachment.storage_path as string]);
    if (storageError) logApiError("Attachment storage cleanup error", storageError);

    return NextResponse.json({ success: true });
  } catch (error) {
    logApiError("Attachment delete error", error);
    return NextResponse.json(
      { error: error instanceof Error ? error.message : "Attachment delete failed." },
      { status: 500 },
    );
  }
}
