import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import * as schema from "../schema/index.js";
import type { Tx } from "../../lib/audit.js";
import { MERKMALE } from "./data/merkmale.js";
import { VEHICLE_TEMPLATES } from "./data/vehicle-templates.js";
import { EQUIPMENT_CATEGORIES } from "./data/equipment-categories.js";
import {
  upsertMerkmal,
  upsertVehicleTemplate,
  upsertTemplateMerkmal,
  upsertTemplateAlias,
  upsertEquipmentCategory,
  upsertCategoryMerkmal,
  pruneTemplateAliasse,
} from "./upsert.js";

/**
 * Katalog-Seed (Workstream 9): füllt Merkmale, Enum-Optionen, Fahrzeug-Vorlagen,
 * deren Pflichtmerkmale + Aliasse sowie Geräte-Kategorien aus dem NÖ-Katalog.
 *
 * Idempotent (Querschnittsstandard 7): ausschließlich Upserts auf Natural Keys;
 * mehrfaches Ausführen ändert keine Counts. Läuft in EINER Transaktion in der
 * Reihenfolge Merkmale → Optionen → Vorlagen → Vorlagen-Merkmale → Aliasse →
 * Kategorien (sequenzielle Awaits, Slug→ID-Map).
 *
 * Liest `DATABASE_URL` direkt aus der Umgebung (keine Next.js-Env-Validierung,
 * wie scripts/migrate.ts und scripts/seed-auth.ts).
 */

/** Reine Seed-Logik gegen eine bestehende Transaktion (für Tests injizierbar). */
export async function seedCatalog(tx: Tx): Promise<void> {
  // 1. Merkmale (+ Optionen) → Slug→ID-Map.
  const merkmalIdBySlug = new Map<string, string>();
  for (const m of MERKMALE) {
    const id = await upsertMerkmal(tx, m);
    merkmalIdBySlug.set(m.slug, id);
  }

  // 2. Vorlagen → Pflichtmerkmale → Aliasse.
  for (let i = 0; i < VEHICLE_TEMPLATES.length; i++) {
    const t = VEHICLE_TEMPLATES[i]!;
    const templateId = await upsertVehicleTemplate(tx, t, i);

    for (let j = 0; j < t.merkmale.length; j++) {
      const tm = t.merkmale[j]!;
      const merkmalId = merkmalIdBySlug.get(tm.slug);
      if (!merkmalId) {
        throw new Error(
          `Vorlage ${t.code} referenziert unbekanntes Merkmal '${tm.slug}'`,
        );
      }
      await upsertTemplateMerkmal(tx, templateId, merkmalId, tm, j);
    }

    for (const a of t.aliasse) {
      await upsertTemplateAlias(tx, templateId, a.alias, a.bestaetigt);
    }
    await pruneTemplateAliasse(
      tx,
      templateId,
      t.aliasse.map((a) => a.alias),
    );
  }

  // 3. Geräte-Kategorien (+ optionale Merkmal-Verknüpfungen).
  for (const c of EQUIPMENT_CATEGORIES) {
    const categoryId = await upsertEquipmentCategory(tx, c);
    const slugs = c.merkmalSlugs ?? [];
    for (let k = 0; k < slugs.length; k++) {
      const merkmalId = merkmalIdBySlug.get(slugs[k]!);
      if (!merkmalId) {
        throw new Error(
          `Kategorie ${c.name} referenziert unbekanntes Merkmal '${slugs[k]}'`,
        );
      }
      await upsertCategoryMerkmal(tx, categoryId, merkmalId, k);
    }
  }
}

/** Standalone-Runner (npm run db:seed). */
export async function main(): Promise<void> {
  const connectionString = process.env.DATABASE_URL;
  if (!connectionString) {
    throw new Error("DATABASE_URL ist nicht gesetzt.");
  }

  const pool = new Pool({ connectionString, max: 1 });
  const db = drizzle(pool, { schema });

  try {
    await db.transaction(async (tx) => {
      await seedCatalog(tx as Tx);
    });

    console.log("Katalog-Seed erfolgreich (idempotent).");
    console.log(`  Merkmale:          ${MERKMALE.length}`);
    console.log(`  Fahrzeug-Vorlagen: ${VEHICLE_TEMPLATES.length}`);
    console.log(`  Geräte-Kategorien: ${EQUIPMENT_CATEGORIES.length}`);
  } finally {
    await pool.end();
  }
}

// Nur ausführen, wenn direkt gestartet (nicht beim Import in Tests).
const isMain =
  typeof process !== "undefined" &&
  process.argv[1] !== undefined &&
  import.meta.url === `file://${process.argv[1]}`;

if (isMain) {
  main().catch((err: unknown) => {
    console.error("Katalog-Seed fehlgeschlagen:", err);
    process.exit(1);
  });
}
