import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { and, eq } from "@epicure/db";
import { db, recipes, recipeIngredients, recipeSteps } from "@epicure/db";
import { requireSessionOrApiKey } from "@/lib/api-auth";
import { applyRateLimit } from "@/lib/rate-limit";
import { withAiQuota, resolveAiConfigOrError } from "@/lib/ai/ai-error";
import { translateRecipe } from "@/lib/ai/features/translate-recipe";
import { withUserKey } from "@/lib/ai/resolve-user-key";
import { checkTierLimitInTransaction, TierLimitError } from "@/lib/tiers";

const Schema = z.object({
  targetLanguage: z.string().min(2).max(50),
  provider: z.enum(["openai", "anthropic", "openrouter", "ollama"]).optional(),
  model: z.string().optional(),
});

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

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

  const limited = await applyRateLimit(`rl:ai:${session!.user.id}`, 10, 60);
  if (limited) return limited;

  const { id } = await params;
  const recipe = await db.query.recipes.findFirst({
    where: and(eq(recipes.id, id), eq(recipes.authorId, session!.user.id)),
    with: {
      ingredients: { orderBy: (t, { asc }) => asc(t.order) },
      steps: { orderBy: (t, { asc }) => asc(t.order) },
    },
  });

  if (!recipe) return NextResponse.json({ error: "Not found" }, { status: 404 });

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

  const configResult = await resolveAiConfigOrError(() =>
    withUserKey(session!.user.id, { provider: parsed.data.provider, model: parsed.data.model })
  );
  if (!configResult.ok) return configResult.response;
  const aiConfig = configResult.data;

  const result = await withAiQuota(session!.user.id, session!.user.tier as "free" | "pro" | "family", () =>
    translateRecipe(
      {
        title: recipe.title,
        description: recipe.description,
        ingredients: recipe.ingredients,
        steps: recipe.steps,
      },
      parsed.data.targetLanguage,
      aiConfig
    ), { skipQuota: aiConfig.isByok }
  );
  if (!result.ok) return result.response;
  const translation = result.data;

  // Save as new draft recipe
  const newId = crypto.randomUUID();
  const now = new Date();

  try {
    await db.transaction(async (tx) => {
    await checkTierLimitInTransaction(tx, session!.user.id, session!.user.tier as "free" | "pro" | "family", "recipe");
    await tx.insert(recipes).values({
      id: newId,
      authorId: session!.user.id,
      title: translation.title,
      description: translation.description,
      baseServings: recipe.baseServings,
      visibility: "private",
      difficulty: recipe.difficulty,
      prepMins: recipe.prepMins,
      cookMins: recipe.cookMins,
      dietaryTags: recipe.dietaryTags ?? {},
      aiGenerated: true,
      createdAt: now,
      updatedAt: now,
    });

    if (translation.ingredients.length > 0) {
      await tx.insert(recipeIngredients).values(
        translation.ingredients.map((ing, i) => ({
          id: crypto.randomUUID(),
          recipeId: newId,
          rawName: ing.rawName,
          quantity: recipe.ingredients[i]?.quantity ?? undefined,
          unit: recipe.ingredients[i]?.unit ?? undefined,
          note: ing.note ?? undefined,
          order: i,
        }))
      );
    }

    if (translation.steps.length > 0) {
      await tx.insert(recipeSteps).values(
        translation.steps.map((step, i) => ({
          id: crypto.randomUUID(),
          recipeId: newId,
          instruction: step.instruction,
          timerSeconds: recipe.steps[i]?.timerSeconds ?? undefined,
          order: i,
        }))
      );
    }
    });
  } catch (err) {
    if (err instanceof TierLimitError) {
      return NextResponse.json({ error: "Recipe limit reached for your tier" }, { status: 403 });
    }
    throw err;
  }

  return NextResponse.json({ id: newId });
}
