import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { db, shoppingListItems, eq, and } from "@epicure/db";
import { getOptionalSession } from "@/lib/api-auth";
import { getShoppingListAccess, canWriteShoppingList } from "@/lib/shopping-list-access";
import { notifyShoppingListMembers } from "@/lib/shopping-list-notify";

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

const UpdateItemSchema = z.object({
  checked: z.boolean().optional(),
  rawName: z.string().min(1).optional(),
  quantity: z.string().nullable().optional(),
  unit: z.string().nullable().optional(),
  aisle: z.string().nullable().optional(),
  sortOrder: z.number().int().optional(),
});

export async function PUT(req: NextRequest, { params }: Params) {
  const { id, itemId } = await params;
  const session = await getOptionalSession();

  const access = await getShoppingListAccess(id, session?.user.id ?? null);
  if (!access) return NextResponse.json({ error: "Not found" }, { status: 404 });
  if (!canWriteShoppingList(access.role)) return NextResponse.json({ error: "Forbidden" }, { status: 403 });

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

  const data = parsed.data;
  const patch: Partial<typeof shoppingListItems.$inferInsert> = {};
  if (data.checked !== undefined) patch.checked = data.checked;
  if (data.rawName !== undefined) patch.rawName = data.rawName;
  if (data.quantity !== undefined) patch.quantity = data.quantity;
  if (data.unit !== undefined) patch.unit = data.unit;
  if (data.aisle !== undefined) patch.aisle = data.aisle;
  if (data.sortOrder !== undefined) patch.sortOrder = data.sortOrder;

  if (Object.keys(patch).length > 0) {
    await db.update(shoppingListItems)
      .set(patch)
      .where(and(eq(shoppingListItems.id, itemId), eq(shoppingListItems.listId, id)));
  }

  // Only checking an item OFF is worth pinging other members about (the
  // "someone's shopping right now" coordination signal) — unchecking,
  // renames, reordering, and aisle edits are too noisy for a push.
  if (data.checked === true) {
    const item = await db.query.shoppingListItems.findFirst({
      where: eq(shoppingListItems.id, itemId),
      columns: { rawName: true },
    });
    if (item) {
      void notifyShoppingListMembers(id, session?.user.id ?? "", session?.user.name ?? null, {
        type: "checked",
        itemName: item.rawName,
        listName: access.list.name,
      }).catch(() => {});
    }
  }

  return NextResponse.json({ updated: true });
}

export async function DELETE(_req: NextRequest, { params }: Params) {
  const { id, itemId } = await params;
  const session = await getOptionalSession();

  const access = await getShoppingListAccess(id, session?.user.id ?? null);
  if (!access) return NextResponse.json({ error: "Not found" }, { status: 404 });
  if (!canWriteShoppingList(access.role)) return NextResponse.json({ error: "Forbidden" }, { status: 403 });

  await db.delete(shoppingListItems)
    .where(and(eq(shoppingListItems.id, itemId), eq(shoppingListItems.listId, id)));

  return NextResponse.json({ deleted: true });
}
