import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import { getCurrentUser } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { aiProgramSchema, type AIProgram } from '@/lib/ai/programSchema';
import { applyAIProgram } from '@/lib/ai/apply';

/**
 * POST /api/ai/apply
 *
 * Body: { generationId: string, program: AIProgram, startDate?: string,
 *         isActive?: boolean }
 *
 * Materializes the (possibly user-edited) AIProgram into a real
 * Program row + nested Weeks/Days/Exercises. Updates the
 * AIGeneration row to status='applied' and stores the new program id
 * in appliedProgramId.
 *
 * The caller is the preview UI: after the user fixes any unresolved
 * exercises and tweaks fields they don't like, they POST the cleaned
 * AIProgram back here.
 */

const bodySchema = z.object({
  generationId: z.string().min(1),
  program: aiProgramSchema,
  startDate: z.string().optional(),
  isActive: z.boolean().optional(),
});

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

    const body = await request.json().catch(() => ({}));
    const parsed = bodySchema.safeParse(body);
    if (!parsed.success) {
      return NextResponse.json(
        { error: 'Invalid body', details: parsed.error.errors },
        { status: 400 },
      );
    }

    const generation = await prisma.aIGeneration.findFirst({
      where: { id: parsed.data.generationId, userId: user.id },
    });
    if (!generation) {
      return NextResponse.json(
        { error: 'Generation not found' },
        { status: 404 },
      );
    }
    if (generation.status === 'applied') {
      return NextResponse.json(
        {
          error: 'This generation has already been applied to a program.',
          appliedProgramId: generation.appliedProgramId,
        },
        { status: 409 },
      );
    }

    const startDate = parsed.data.startDate
      ? new Date(parsed.data.startDate)
      : new Date();

    const result = await applyAIProgram(
      prisma,
      parsed.data.program as AIProgram,
      {
        userId: user.id,
        startDate,
        isActive: parsed.data.isActive ?? false,
      },
    );

    await prisma.aIGeneration.update({
      where: { id: generation.id },
      data: {
        status: 'applied',
        appliedProgramId: result.programId,
        // Stash the user-edited version so history reflects what was
        // actually written (vs the raw model output which is also kept).
        parsedProgram: JSON.stringify(parsed.data.program),
      },
    });

    return NextResponse.json({
      programId: result.programId,
      weeksCreated: result.weeksCreated,
      daysCreated: result.daysCreated,
      exercisesCreated: result.exercisesCreated,
    });
  } catch (err) {
    console.error('POST /api/ai/apply error:', err);
    return NextResponse.json(
      { error: (err as Error).message ?? 'Internal server error' },
      { status: 500 },
    );
  }
}
