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

const addSetsSchema = z.object({
  exerciseId: z.string().min(1),
  sets: z.array(
    z.object({
      setNumber: z.number().int().positive(),
      reps: z.number().int().positive().optional(),
      weight: z.number().optional(),
      weightUnit: z.string().default("lbs"),
      rpe: z.number().int().min(1).max(10).optional(),
      durationSeconds: z.number().int().positive().optional(),
      distance: z.number().positive().optional(),
      distanceUnit: z.string().optional(),
      calories: z.number().int().positive().optional(),
      customMetrics: z.record(z.string()).optional(),
      notes: z.string().optional(),
    })
  ),
});

// POST: Add an exercise's sets to an existing workout
export async function POST(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const user = await getCurrentUser();
    if (!user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const workout = await prisma.workout.findFirst({
      where: { id: params.id, deletedAt: null },
      select: { userId: true },
    });

    if (!workout) {
      return NextResponse.json({ error: "Workout not found" }, { status: 404 });
    }

    if (workout.userId !== user.id) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 403 });
    }

    const body = await request.json();
    const validated = addSetsSchema.parse(body);

    // Delete existing sets for this exercise in this workout (replace mode)
    await prisma.setLog.deleteMany({
      where: {
        workoutId: params.id,
        exerciseId: validated.exerciseId,
      },
    });

    // Create new sets
    await prisma.setLog.createMany({
      data: validated.sets.map((set) => ({
        workoutId: params.id,
        exerciseId: validated.exerciseId,
        setNumber: set.setNumber,
        reps: set.reps,
        weight: set.weight,
        weightUnit: set.weightUnit,
        rpe: set.rpe,
        durationSeconds: set.durationSeconds,
        distance: set.distance,
        distanceUnit: set.distanceUnit,
        calories: set.calories,
        customMetrics:
          set.customMetrics && Object.keys(set.customMetrics).length > 0
            ? JSON.stringify(set.customMetrics)
            : undefined,
        notes: set.notes,
      } as any)),
    });

    // Return updated workout
    const updated = await prisma.workout.findFirst({
      where: { id: params.id, deletedAt: null },
      include: {
        setLogs: {
          include: { exercise: true },
          orderBy: { setNumber: "asc" },
        },
      },
    });

    return NextResponse.json(updated, { status: 201 });
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { error: "Invalid data", details: error.errors },
        { status: 400 }
      );
    }
    console.error("Failed to add sets:", error);
    return NextResponse.json(
      { error: "Failed to add sets" },
      { status: 500 }
    );
  }
}

// DELETE: Remove all sets for a specific exercise from a workout
export async function DELETE(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const user = await getCurrentUser();
    if (!user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const workout = await prisma.workout.findFirst({
      where: { id: params.id, deletedAt: null },
      select: { userId: true },
    });

    if (!workout) {
      return NextResponse.json({ error: "Workout not found" }, { status: 404 });
    }

    if (workout.userId !== user.id) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 403 });
    }

    const { searchParams } = new URL(request.url);
    const exerciseId = searchParams.get("exerciseId");

    if (!exerciseId) {
      return NextResponse.json(
        { error: "exerciseId query param required" },
        { status: 400 }
      );
    }

    await prisma.setLog.deleteMany({
      where: {
        workoutId: params.id,
        exerciseId,
      },
    });

    return NextResponse.json({ success: true });
  } catch (error) {
    console.error("Failed to delete sets:", error);
    return NextResponse.json(
      { error: "Failed to delete sets" },
      { status: 500 }
    );
  }
}
