"use server";

import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { eq, sql } from "drizzle-orm";
import { z } from "zod";
import { db } from "@/lib/db/client";
import { orthoprepQuestions } from "@/lib/db/schema";
import { requireAdmin } from "@/lib/auth/admin-guard";
import { logAdminAction } from "@/lib/audit";

async function ensureAdmin() {
  const session = await requireAdmin();
  return (session.user as { id?: string }).id!;
}

const difficultyValues = ["Easy", "Medium", "Hard"] as const;
const statusValues = ["draft", "published", "archived"] as const;

const createSchema = z.object({
  stem: z.string().min(10).max(4000),
  part: z.string().min(1).max(200),
  chapter: z.string().max(200),
  difficulty: z.enum(difficultyValues),
});

export async function createQuestion(formData: FormData) {
  const adminId = await ensureAdmin();
  const parsed = createSchema.parse({
    stem: formData.get("stem"),
    part: formData.get("part") ?? "Part 1",
    chapter: formData.get("chapter") ?? "",
    difficulty: formData.get("difficulty") ?? "Medium",
  });

  const [{ maxNumber }] = await db
    .select({ maxNumber: sql<number>`coalesce(max(${orthoprepQuestions.number}), 0)::int` })
    .from(orthoprepQuestions);
  const nextNumber = Number(maxNumber ?? 0) + 1;

  const [row] = await db
    .insert(orthoprepQuestions)
    .values({
      number: nextNumber,
      stem: parsed.stem,
      part: parsed.part,
      chapter: parsed.chapter,
      difficulty: parsed.difficulty,
      options: ["", "", "", "", ""],
      answer: "A",
    })
    .returning({ id: orthoprepQuestions.id });

  await logAdminAction({
    adminUserId: adminId,
    action: "create_orthoprep_question",
    targetId: row.id,
  });

  revalidatePath("/admin/orthoprep");
  redirect(`/admin/orthoprep/${row.id}`);
}

const updateSchema = z.object({
  id: z.string().uuid(),
  number: z.coerce.number().int().min(1).max(10_000),
  part: z.string().min(1).max(200),
  chapter: z.string().max(200),
  stem: z.string().min(10).max(4000),
  optionA: z.string().max(1000),
  optionB: z.string().max(1000),
  optionC: z.string().max(1000),
  optionD: z.string().max(1000),
  optionE: z.string().max(1000),
  answer: z.enum(["A", "B", "C", "D", "E"]),
  explanation: z.string().max(6000),
  distractors: z.string().max(3000),
  takeHome: z.string().max(2000),
  difficulty: z.enum(difficultyValues),
  tags: z.string().max(500),
});

export async function updateQuestion(formData: FormData) {
  const adminId = await ensureAdmin();
  const parsed = updateSchema.parse({
    id: formData.get("id"),
    number: formData.get("number") ?? 0,
    part: formData.get("part") ?? "",
    chapter: formData.get("chapter") ?? "",
    stem: formData.get("stem") ?? "",
    optionA: formData.get("optionA") ?? "",
    optionB: formData.get("optionB") ?? "",
    optionC: formData.get("optionC") ?? "",
    optionD: formData.get("optionD") ?? "",
    optionE: formData.get("optionE") ?? "",
    answer: formData.get("answer") ?? "A",
    explanation: formData.get("explanation") ?? "",
    distractors: formData.get("distractors") ?? "",
    takeHome: formData.get("takeHome") ?? "",
    difficulty: formData.get("difficulty") ?? "Medium",
    tags: formData.get("tags") ?? "",
  });

  const options = [parsed.optionA, parsed.optionB, parsed.optionC, parsed.optionD, parsed.optionE]
    .map((o) => o.trim())
    .filter((_, i, arr) => {
      // Keep all first-5 positions even if empty to preserve A-E ordering
      return i < arr.length;
    });

  const tags = parsed.tags
    .split(",")
    .map((t) => t.trim())
    .filter(Boolean);

  await db
    .update(orthoprepQuestions)
    .set({
      number: parsed.number,
      part: parsed.part,
      chapter: parsed.chapter,
      stem: parsed.stem,
      options,
      answer: parsed.answer,
      explanation: parsed.explanation,
      distractors: parsed.distractors,
      takeHome: parsed.takeHome,
      difficulty: parsed.difficulty,
      tags,
      updatedAt: new Date(),
    })
    .where(eq(orthoprepQuestions.id, parsed.id));

  await logAdminAction({
    adminUserId: adminId,
    action: "update_orthoprep_question",
    targetId: parsed.id,
  });

  revalidatePath("/admin/orthoprep");
  revalidatePath(`/admin/orthoprep/${parsed.id}`);
  revalidatePath("/products/orthoprep/question-bank");
}

const setStatusSchema = z.object({
  id: z.string().uuid(),
  status: z.enum(statusValues),
});

export async function setQuestionStatus(formData: FormData) {
  const adminId = await ensureAdmin();
  const parsed = setStatusSchema.parse({
    id: formData.get("id"),
    status: formData.get("status"),
  });

  await db
    .update(orthoprepQuestions)
    .set({ status: parsed.status, updatedAt: new Date() })
    .where(eq(orthoprepQuestions.id, parsed.id));

  await logAdminAction({
    adminUserId: adminId,
    action: `orthoprep_question_${parsed.status}`,
    targetId: parsed.id,
  });

  revalidatePath("/admin/orthoprep");
  revalidatePath(`/admin/orthoprep/${parsed.id}`);
  revalidatePath("/products/orthoprep/question-bank");
}

export async function deleteQuestion(formData: FormData) {
  const adminId = await ensureAdmin();
  const id = z.string().uuid().parse(formData.get("id"));
  await db.delete(orthoprepQuestions).where(eq(orthoprepQuestions.id, id));
  await logAdminAction({
    adminUserId: adminId,
    action: "delete_orthoprep_question",
    targetId: id,
  });
  revalidatePath("/admin/orthoprep");
  revalidatePath("/products/orthoprep/question-bank");
  redirect("/admin/orthoprep");
}
