import { config } from "dotenv";
import path from "node:path";
config({ path: path.resolve(process.cwd(), ".env.local") });

// Seeds the full FRCS SBA bank (~1,575 questions covering basic sciences
// and clinical sub-specialties) from src/data/frcs-bank.json into
// orthoprep_questions.
// Idempotent on `number` — re-running refreshes stems/explanations
// without creating duplicates, and any leftover rows with numbers
// outside the current bank are pruned.

type SourceQuestion = {
  number: number;
  stem: string;
  options: string[];
  answer: string;
  explanation?: string;
  distractors?: string;
  takeHome?: string;
  difficulty?: string;
  tags?: string[];
};

type SourceChapter = {
  title: string;
  range?: string;
  questions: SourceQuestion[];
};

type SourcePart = {
  title: string;
  chapters: SourceChapter[];
};

type SourceBank = {
  title: string;
  subtitle?: string;
  parts: SourcePart[];
};

async function main() {
  const databaseUrl = process.env.DATABASE_URL;
  if (!databaseUrl) throw new Error("DATABASE_URL not set");

  const postgres = (await import("postgres")).default;
  const { drizzle } = await import("drizzle-orm/postgres-js");
  const { eq, notInArray } = await import("drizzle-orm");
  const schema = await import("./schema");
  const bank = (await import("../../data/frcs-bank.json")).default as unknown as SourceBank;

  const sql = postgres(databaseUrl, { max: 1 });
  const db = drizzle(sql, { schema });

  let inserted = 0;
  let updated = 0;

  const bankNumbers = bank.parts
    .flatMap((p) => p.chapters)
    .flatMap((c) => c.questions.map((q) => q.number));

  const validDifficulties = new Set(["Easy", "Medium", "Hard"] as const);
  type Difficulty = "Easy" | "Medium" | "Hard";

  for (const part of bank.parts) {
    for (const chapter of part.chapters) {
      for (const q of chapter.questions) {
        const difficulty: Difficulty = validDifficulties.has(q.difficulty as Difficulty)
          ? (q.difficulty as Difficulty)
          : "Medium";

        const values = {
          number: q.number,
          part: part.title,
          chapter: chapter.title,
          stem: q.stem ?? "",
          options: q.options ?? [],
          answer: (q.answer ?? "A").toUpperCase(),
          explanation: q.explanation ?? "",
          distractors: q.distractors ?? "",
          takeHome: q.takeHome ?? "",
          difficulty,
          tags: q.tags ?? [],
          status: "published" as const,
        };

        const [existing] = await db
          .select({ id: schema.orthoprepQuestions.id })
          .from(schema.orthoprepQuestions)
          .where(eq(schema.orthoprepQuestions.number, q.number))
          .limit(1);

        if (existing) {
          await db
            .update(schema.orthoprepQuestions)
            .set({ ...values, updatedAt: new Date() })
            .where(eq(schema.orthoprepQuestions.id, existing.id));
          updated += 1;
        } else {
          await db.insert(schema.orthoprepQuestions).values(values);
          inserted += 1;
        }
      }
    }
  }

  // Prune rows whose `number` is not in the current bank. This handles the
  // migration from the old 1,300-item bank to the 300-item bank — stale rows
  // beyond the new range would otherwise linger in production.
  const pruned = await db
    .delete(schema.orthoprepQuestions)
    .where(notInArray(schema.orthoprepQuestions.number, bankNumbers))
    .returning({ number: schema.orthoprepQuestions.number });

  console.log(
    `orthoprep_questions seed complete — ${inserted} inserted, ${updated} updated, ${pruned.length} pruned`,
  );
  await sql.end();
  process.exit(0);
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});
