import { NextResponse } from "next/server";
import { createClient as createSupabaseClient } from "@supabase/supabase-js";
import { logApiError } from "@/lib/api/security";
import { createRouteClient } from "@/lib/supabase/route";
import { ensureAttachmentsBucket, sanitizeAttachmentFileName } from "@/lib/attachments/server";
import { NOTE_COVER_CATEGORIES } from "@/lib/notes/note-covers";

const MAX_FILE_SIZE = 8 * 1024 * 1024; // 8MB

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

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

    const admin = getSupabaseAdmin();
    const { data: designs } = await admin
      .from("note_designs")
      .select("*")
      .eq("creator_id", user.id)
      .order("created_at", { ascending: false });

    const ids = (designs || []).map((d) => d.id as string);
    const counts: Record<string, number> = {};
    if (ids.length > 0) {
      const { data: purchases } = await admin
        .from("note_design_purchases")
        .select("design_id")
        .in("design_id", ids);
      for (const purchase of purchases || []) {
        const key = purchase.design_id as string;
        counts[key] = (counts[key] || 0) + 1;
      }
    }

    const result = (designs || []).map((d) => ({ ...d, purchase_count: counts[d.id as string] || 0 }));
    return NextResponse.json({ designs: result });
  } catch (error) {
    logApiError("Note design GET (mine) error", error);
    return NextResponse.json({ error: "Could not load your designs" }, { status: 500 });
  }
}

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

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

    const admin = getSupabaseAdmin();
    const { data: existing } = await admin
      .from("note_designs")
      .select("id")
      .eq("id", id)
      .eq("creator_id", user.id)
      .maybeSingle();
    if (!existing) return NextResponse.json({ error: "Design not found" }, { status: 404 });

    const updates: Record<string, unknown> = {};
    if (body.price_euros !== undefined) {
      const priceEuros = Number(body.price_euros);
      updates.price_cents = Number.isFinite(priceEuros) && priceEuros > 0 ? Math.round(priceEuros * 100) : 0;
    }
    if (typeof body.is_published === "boolean") {
      updates.is_published = body.is_published;
    }

    const { data, error } = await admin.from("note_designs").update(updates).eq("id", id).select().single();
    if (error) throw error;

    return NextResponse.json({ design: data });
  } catch (error) {
    logApiError("Note design PATCH error", error);
    return NextResponse.json({ error: "Design could not be updated" }, { status: 500 });
  }
}

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

    const formData = await req.formData();
    const name = String(formData.get("name") || "").trim();
    const categoryRaw = String(formData.get("category") || "custom");
    const category = NOTE_COVER_CATEGORIES.includes(categoryRaw as (typeof NOTE_COVER_CATEGORIES)[number])
      ? categoryRaw
      : "custom";
    const tone = formData.get("tone") === "light" ? "light" : "dark";
    const editor_surface = formData.get("editor_surface") === "solid" ? "solid" : "glass";
    const textColorRaw = String(formData.get("text_color") || "").trim();
    const text_color = /^#[0-9a-fA-F]{6}$/.test(textColorRaw) ? textColorRaw : null;
    const priceEuros = Number(formData.get("price_euros") || 0);
    const price_cents = Number.isFinite(priceEuros) && priceEuros > 0 ? Math.round(priceEuros * 100) : 0;
    const file = formData.get("file");

    if (!name) return NextResponse.json({ error: "Name is required" }, { status: 400 });
    if (!(file instanceof File)) return NextResponse.json({ error: "An image is required" }, { status: 400 });
    if (!file.type.startsWith("image/")) {
      return NextResponse.json({ error: "Only image files are supported" }, { status: 400 });
    }
    if (file.size > MAX_FILE_SIZE) {
      return NextResponse.json({ error: "Image must be 8MB or smaller" }, { status: 400 });
    }

    await ensureAttachmentsBucket();
    const admin = getSupabaseAdmin();
    const safeFileName = sanitizeAttachmentFileName(file.name);
    const storagePath = `note-designs/${user.id}/${Date.now()}-${safeFileName}`;
    const buffer = Buffer.from(await file.arrayBuffer());

    const { error: uploadError } = await admin.storage
      .from("attachments")
      .upload(storagePath, buffer, { contentType: file.type, upsert: false });
    if (uploadError) throw uploadError;

    const {
      data: { publicUrl },
    } = admin.storage.from("attachments").getPublicUrl(storagePath);
    const background_css = `center / cover no-repeat url("${publicUrl}")`;

    const { data, error } = await admin
      .from("note_designs")
      .insert({
        creator_id: user.id,
        name,
        category,
        tone,
        editor_surface,
        text_color,
        price_cents,
        background_css,
        image_url: publicUrl,
        storage_path: storagePath,
        is_published: true,
      })
      .select()
      .single();

    if (error) {
      await admin.storage.from("attachments").remove([storagePath]);
      throw error;
    }

    return NextResponse.json({ design: data }, { status: 201 });
  } catch (error) {
    logApiError("Note design upload POST error", error);
    return NextResponse.json({ error: "Design could not be uploaded" }, { 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: "Unauthorized" }, { status: 401 });

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

    const admin = getSupabaseAdmin();
    const { data: design } = await admin
      .from("note_designs")
      .select("id, storage_path")
      .eq("id", id)
      .eq("creator_id", user.id)
      .maybeSingle();
    if (!design) return NextResponse.json({ error: "Design not found" }, { status: 404 });

    await admin.from("note_designs").delete().eq("id", id);
    if (design.storage_path) {
      const { error: storageError } = await admin.storage.from("attachments").remove([design.storage_path]);
      if (storageError) logApiError("Note design storage cleanup error", storageError);
    }

    return NextResponse.json({ success: true });
  } catch (error) {
    logApiError("Note design DELETE error", error);
    return NextResponse.json({ error: "Design could not be deleted" }, { status: 500 });
  }
}
