import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";

/**
 * POST /api/programs/[id]/days/[dayId]/start
 *
 * Creates a new Workout for the actor pre-populated with the
 * ProgramDay's exercise list — one SetLog per planned set, with
 * empty reps/weight that the user fills in as they actually log
 * the session. Stamps `Workout.programDayId` for adherence
 * tracking.
 *
 * Body (optional): { date?: string (ISO) }
 *   - date defaults to today
 */

const bodySchema = z.object({
  date: z.string().optional(),
});

export async function POST(
  request: NextRequest,
  { params }: { params: { id: string; dayId: string } },
) {
  try {
    const user = await getCurrentUser();
    if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

    let body: unknown = {};
    try {
      body = await request.json();
    } catch {
      // Empty body is fine.
    }
    const parsed = bodySchema.safeParse(body);
    const dateStr = parsed.success ? parsed.data.date : undefined;

    const day = await prisma.programDay.findFirst({
      where: {
        id: params.dayId,
        week: { programId: params.id, program: { userId: user.id } },
      },
      include: {
        exercises: {
          orderBy: { order: "asc" },
          include: { exercise: true },
        },
        week: { include: { program: { select: { name: true } } } },
      },
    });
    if (!day) {
      return NextResponse.json(
        { error: "Program day not found" },
        { status: 404 },
      );
    }

    // v1.1.0:4: pull the user's preferred weight unit so we can fall
    // back to it when the program day didn't specify one.
    const prefs = await prisma.userPreferences.findUnique({
      where: { userId: user.id },
      select: { defaultWeightUnit: true },
    });
    const userPrefUnit = prefs?.defaultWeightUnit ?? "lbs";

    // Build SetLog rows: for each planned exercise, pre-create N
    // empty sets where N = exercise.sets ?? 1. The user fills in
    // reps/weight when they actually do them. v1.1.0:4: if the
    // ProgramExercise has a `suggestedWeight`, seed it on every set
    // so the user starts with a target instead of a blank field.
    const setLogsCreate: {
      exerciseId: string;
      setNumber: number;
      weight: number | null;
      weightUnit: string;
    }[] = [];
    for (const ex of day.exercises) {
      const setCount = ex.sets ?? 1;
      const unit =
        ex.suggestedWeightUnit ?? ex.exercise.defaultWeightUnit ?? userPrefUnit;
      for (let n = 1; n <= setCount; n++) {
        setLogsCreate.push({
          exerciseId: ex.exerciseId,
          setNumber: n,
          weight: ex.suggestedWeight ?? null,
          weightUnit: unit,
        });
      }
    }

    const workoutDate = dateStr ? new Date(dateStr) : new Date();
    const workoutName =
      day.name ??
      `${day.week.program.name} · Week ${day.week.weekNumber} Day ${day.dayOfWeek}`;

    const workout = await prisma.workout.create({
      data: {
        userId: user.id,
        date: workoutDate,
        name: workoutName,
        programDayId: day.id,
        setLogs: setLogsCreate.length > 0 ? { create: setLogsCreate } : undefined,
      },
      include: {
        setLogs: {
          include: { exercise: true },
          orderBy: { setNumber: "asc" },
        },
      },
    });

    return NextResponse.json(workout, { status: 201 });
  } catch (err) {
    console.error("POST /api/programs/[id]/days/[dayId]/start error:", err);
    return NextResponse.json({ error: "Internal server error" }, { status: 500 });
  }
}
