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

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

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

  const plan = await db.query.mealPlans.findFirst({
    where: and(eq(mealPlans.userId, session!.user.id), eq(mealPlans.weekStart, weekStart)),
    with: {
      entries: {
        with: {
          recipe: {
            with: { photos: true },
          },
        },
      },
    },
  });

  if (!plan) return NextResponse.json({ weekStart, entries: [] });
  return NextResponse.json(plan);
}

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

  const existing = await db.query.mealPlans.findFirst({
    where: and(eq(mealPlans.userId, session!.user.id), eq(mealPlans.weekStart, weekStart)),
  });

  if (existing) return NextResponse.json(existing);

  const id = crypto.randomUUID();
  await db.insert(mealPlans).values({ id, userId: session!.user.id, weekStart });
  return NextResponse.json({ id, weekStart }, { status: 201 });
}

const PatchSchema = z.object({
  isPublic: z.boolean(),
});

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

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

  const existing = await db.query.mealPlans.findFirst({
    where: and(eq(mealPlans.userId, session!.user.id), eq(mealPlans.weekStart, weekStart)),
  });

  const id = existing?.id ?? crypto.randomUUID();
  if (!existing) {
    await db.insert(mealPlans).values({ id, userId: session!.user.id, weekStart, isPublic: parsed.data.isPublic });
  } else {
    await db.update(mealPlans).set({ isPublic: parsed.data.isPublic }).where(eq(mealPlans.id, id));
  }

  return NextResponse.json({ id, weekStart, isPublic: parsed.data.isPublic });
}
