import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { db, shoppingLists, shoppingListMembers, users, eq, and } from "@epicure/db";
import { requireSessionOrApiKey } from "@/lib/api-auth";

type Params = { params: Promise<{ id: string }> };

// ─── GET /api/v1/shopping-lists/[id]/members ─────────────────────────────────
// Owner only — returns members joined with basic user info.
export async function GET(req: NextRequest, { params }: Params) {
  const { session, response } = await requireSessionOrApiKey(req);
  if (response) return response;

  const { id } = await params;

  const list = await db.query.shoppingLists.findFirst({
    where: and(eq(shoppingLists.id, id), eq(shoppingLists.userId, session!.user.id)),
  });
  if (!list) return NextResponse.json({ error: "Not found" }, { status: 404 });

  const members = await db.query.shoppingListMembers.findMany({
    where: eq(shoppingListMembers.listId, id),
    with: { user: true },
  });

  const result = members.map((m) => ({
    id: m.id,
    userId: m.userId,
    role: m.role,
    createdAt: m.createdAt,
    user: {
      name: m.user.name,
      username: m.user.username,
      avatarUrl: m.user.avatarUrl,
    },
  }));

  return NextResponse.json(result);
}

// ─── POST /api/v1/shopping-lists/[id]/members ────────────────────────────────
// Owner only — invite by email or userId.
const InviteSchema = z
  .object({
    email: z.string().email().optional(),
    userId: z.string().optional(),
    role: z.enum(["viewer", "editor"]),
  })
  .refine((d) => d.email !== undefined || d.userId !== undefined, {
    message: "Provide either email or userId",
  });

export async function POST(req: NextRequest, { params }: Params) {
  const { session, response } = await requireSessionOrApiKey(req);
  if (response) return response;

  const { id } = await params;

  const list = await db.query.shoppingLists.findFirst({
    where: and(eq(shoppingLists.id, id), eq(shoppingLists.userId, session!.user.id)),
  });
  if (!list) return NextResponse.json({ error: "Not found" }, { status: 404 });

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

  const { email, userId, role } = parsed.data;

  const targetUser = await db.query.users.findFirst({
    where: email ? eq(users.email, email) : eq(users.id, userId!),
  });
  if (!targetUser) return NextResponse.json({ error: "User not found" }, { status: 404 });

  if (targetUser.id === session!.user.id) {
    return NextResponse.json({ error: "Cannot invite yourself" }, { status: 400 });
  }

  const existing = await db.query.shoppingListMembers.findFirst({
    where: and(
      eq(shoppingListMembers.listId, id),
      eq(shoppingListMembers.userId, targetUser.id),
    ),
  });
  if (existing) return NextResponse.json({ error: "Already a member" }, { status: 409 });

  const memberId = crypto.randomUUID();
  await db.insert(shoppingListMembers).values({
    id: memberId,
    listId: id,
    userId: targetUser.id,
    role,
  });

  return NextResponse.json({ id: memberId }, { status: 201 });
}

// ─── DELETE /api/v1/shopping-lists/[id]/members?memberId=… ───────────────────
// Owner OR the member themselves can remove.
export async function DELETE(req: NextRequest, { params }: Params) {
  const { session, response } = await requireSessionOrApiKey(req);
  if (response) return response;

  const { id } = await params;
  const memberId = req.nextUrl.searchParams.get("memberId");
  if (!memberId) return NextResponse.json({ error: "memberId required" }, { status: 400 });

  const member = await db.query.shoppingListMembers.findFirst({
    where: and(eq(shoppingListMembers.id, memberId), eq(shoppingListMembers.listId, id)),
  });
  if (!member) return NextResponse.json({ error: "Not found" }, { status: 404 });

  const list = await db.query.shoppingLists.findFirst({
    where: eq(shoppingLists.id, id),
  });

  const isOwner = list?.userId === session!.user.id;
  const isSelf = member.userId === session!.user.id;

  if (!isOwner && !isSelf) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  await db.delete(shoppingListMembers).where(eq(shoppingListMembers.id, memberId));

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