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

const setSchema = z.object({
  reps: z.number().int().positive().optional(),
  weight: z.number().positive().optional(),
  weightUnit: z.string().optional(),
  durationSeconds: z.number().int().positive().optional(),
  distance: z.number().positive().optional(),
  distanceUnit: z.string().optional(),
  calories: z.number().int().positive().optional(),
  rpe: z.number().int().min(1).max(10).optional(),
  notes: z.string().optional(),
});

const exerciseSchema = z.object({
  name: z.string().min(1),
  type: z.string().optional(),
  existingExerciseId: z.string().optional(),
  sets: z.array(setSchema),
});

const workoutSchema = z.object({
  date: z.string(),
  name: z.string().optional(),
  notes: z.string().optional(),
  exercises: z.array(exerciseSchema),
});

const saveImportSchema = z.object({
  workouts: z.array(workoutSchema).min(1),
});

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

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

    // Load all user exercises for matching
    const existingExercises = await prisma.exercise.findMany({
      where: { userId: user.id },
    });

    // Build a case-insensitive lookup map
    const exerciseMap = new Map<string, typeof existingExercises[0]>();
    for (const ex of existingExercises) {
      exerciseMap.set(ex.name.toLowerCase(), ex);
    }

    const createdWorkoutIds: string[] = [];

    for (const workoutData of validated.workouts) {
      // Resolve exercise IDs (match existing or create new)
      const resolvedExercises: Array<{
        exerciseId: string;
        sets: z.infer<typeof setSchema>[];
      }> = [];

      for (const ex of workoutData.exercises) {
        let exerciseId: string;

        if (ex.existingExerciseId) {
          // User explicitly matched this to an existing exercise
          exerciseId = ex.existingExerciseId;
        } else {
          // Try case-insensitive match
          const matched = exerciseMap.get(ex.name.toLowerCase());
          if (matched) {
            exerciseId = matched.id;
          } else {
            // Create new exercise
            const newExercise = await prisma.exercise.create({
              data: {
                userId: user.id,
                name: ex.name,
                type: ex.type || "other",
                muscleGroups: JSON.stringify([]),
                isCustom: true,
              } as any,
            });
            exerciseId = newExercise.id;
            // Add to map so subsequent references can find it
            exerciseMap.set(ex.name.toLowerCase(), newExercise);
          }
        }

        resolvedExercises.push({ exerciseId, sets: ex.sets });
      }

      // Create the workout with all sets
      const setLogsData: any[] = [];
      for (const resolved of resolvedExercises) {
        resolved.sets.forEach((set, index) => {
          setLogsData.push({
            exerciseId: resolved.exerciseId,
            setNumber: index + 1,
            reps: set.reps || null,
            weight: set.weight || null,
            weightUnit: set.weightUnit || "lbs",
            rpe: set.rpe || null,
            durationSeconds: set.durationSeconds || null,
            distance: set.distance || null,
            distanceUnit: set.distanceUnit || null,
            calories: set.calories || null,
            notes: set.notes || null,
          });
        });
      }

      const workout = await prisma.workout.create({
        data: {
          userId: user.id,
          date: new Date(workoutData.date),
          name: workoutData.name || null,
          notes: workoutData.notes || null,
          setLogs: {
            create: setLogsData,
          },
        } as any,
      });

      createdWorkoutIds.push(workout.id);
    }

    return NextResponse.json({
      created: createdWorkoutIds,
      count: createdWorkoutIds.length,
    });
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { error: "Invalid request data", details: error.errors },
        { status: 400 }
      );
    }

    console.error("POST /api/workouts/import/save error:", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    );
  }
}
