import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { db, webhooks, eq, and } from "@epicure/db";
import { requireDeveloper } from "@/lib/api-auth";
import { validateWebhookUrl } from "@/lib/validate-webhook-url";
import { WEBHOOK_EVENTS } from "@/lib/webhooks";

const UpdateWebhookBody = z.object({
  url: z.string().min(1).max(2048).optional(),
  events: z.array(z.enum(WEBHOOK_EVENTS)).optional(),
  active: z.boolean().optional(),
});

export async function DELETE(
  _req: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const { session, response } = await requireDeveloper();
  if (response) return response;

  const { id } = await params;

  const existing = await db
    .select({ id: webhooks.id })
    .from(webhooks)
    .where(and(eq(webhooks.id, id), eq(webhooks.userId, session!.user.id)))
    .limit(1);

  if (existing.length === 0) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }

  await db
    .delete(webhooks)
    .where(and(eq(webhooks.id, id), eq(webhooks.userId, session!.user.id)));

  return new NextResponse(null, { status: 204 });
}

export async function PATCH(
  req: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const { session, response } = await requireDeveloper();
  if (response) return response;

  const { id } = await params;

  const existing = await db
    .select({ id: webhooks.id })
    .from(webhooks)
    .where(and(eq(webhooks.id, id), eq(webhooks.userId, session!.user.id)))
    .limit(1);

  if (existing.length === 0) {
    return NextResponse.json({ error: "Not found" }, { status: 404 });
  }

  const body = await req.json() as unknown;
  const parsed = UpdateWebhookBody.safeParse(body);
  if (!parsed.success) {
    return NextResponse.json(
      { error: "Validation error", issues: parsed.error.issues },
      { status: 400 }
    );
  }

  if (parsed.data.url) {
    const ssrfError = await validateWebhookUrl(parsed.data.url);
    if (ssrfError) {
      return NextResponse.json({ error: ssrfError }, { status: 400 });
    }
  }

  const updates: Partial<{ url: string; events: string[]; active: boolean }> = {};
  if (parsed.data.url !== undefined) updates.url = parsed.data.url;
  if (parsed.data.events !== undefined) updates.events = parsed.data.events;
  if (parsed.data.active !== undefined) updates.active = parsed.data.active;

  if (Object.keys(updates).length === 0) {
    return NextResponse.json({ error: "No fields to update" }, { status: 400 });
  }

  await db
    .update(webhooks)
    .set(updates)
    .where(and(eq(webhooks.id, id), eq(webhooks.userId, session!.user.id)));

  const updated = await db
    .select({
      id: webhooks.id,
      userId: webhooks.userId,
      url: webhooks.url,
      events: webhooks.events,
      active: webhooks.active,
      createdAt: webhooks.createdAt,
    })
    .from(webhooks)
    .where(eq(webhooks.id, id))
    .limit(1);

  return NextResponse.json(updated[0]);
}
