import "dotenv/config";
import bcrypt from "bcryptjs";
// Use the shared, adapter-wired client (Prisma 7 needs a driver adapter).
// dotenv is imported first so DATABASE_URL is set before database.ts reads it.
import prisma from "../src/config/database";

const PERMISSIONS: {
  name: string;
  display_name: string;
  module: string;
  description: string;
}[] = [
  // Docházka
  {
    name: "attendance.record",
    display_name: "Záznam docházky",
    module: "attendance",
    description: "Zapisovat příchody/odchody",
  },
  {
    name: "attendance.history",
    display_name: "Historie docházky",
    module: "attendance",
    description: "Prohlížet vlastní historii docházky",
  },
  {
    name: "attendance.approve",
    display_name: "Schvalování docházky",
    module: "attendance",
    description: "Schvalovat žádosti o dovolenou/nemoc",
  },
  {
    name: "attendance.manage",
    display_name: "Správa docházky",
    module: "attendance",
    description: "Spravovat všechny záznamy, vytvářet/editovat/mazat",
  },
  {
    name: "attendance.balances",
    display_name: "Správa bilancí",
    module: "attendance",
    description: "Spravovat zůstatky dovolené a sick days",
  },

  // Kniha jízd
  {
    name: "trips.record",
    display_name: "Záznam jízd",
    module: "trips",
    description: "Zapisovat jízdy",
  },
  {
    name: "trips.history",
    display_name: "Historie jízd",
    module: "trips",
    description: "Prohlížet vlastní historii jízd",
  },
  {
    name: "trips.manage",
    display_name: "Správa jízd",
    module: "trips",
    description: "Spravovat všechny jízdy",
  },

  // Vozidla
  {
    name: "vehicles.manage",
    display_name: "Správa vozidel",
    module: "vehicles",
    description: "Spravovat vozový park",
  },

  // Nabídky
  {
    name: "offers.view",
    display_name: "Zobrazit nabídky",
    module: "offers",
    description: "Prohlížet seznam nabídek",
  },
  {
    name: "offers.create",
    display_name: "Vytvořit nabídku",
    module: "offers",
    description: "Vytvářet nové nabídky",
  },
  {
    name: "offers.edit",
    display_name: "Upravit nabídku",
    module: "offers",
    description: "Upravovat existující nabídky",
  },
  {
    name: "offers.delete",
    display_name: "Smazat nabídku",
    module: "offers",
    description: "Mazat nabídky",
  },

  // Objednávky
  {
    name: "orders.view",
    display_name: "Zobrazit objednávky",
    module: "orders",
    description: "Prohlížet seznam objednávek",
  },
  {
    name: "orders.create",
    display_name: "Vytvořit objednávku",
    module: "orders",
    description: "Vytvářet nové objednávky",
  },
  {
    name: "orders.edit",
    display_name: "Upravit objednávku",
    module: "orders",
    description: "Upravovat existující objednávky",
  },
  {
    name: "orders.delete",
    display_name: "Smazat objednávku",
    module: "orders",
    description: "Mazat objednávky",
  },

  // Faktury
  {
    name: "invoices.view",
    display_name: "Zobrazit faktury",
    module: "invoices",
    description: "Prohlížet seznam faktur",
  },
  {
    name: "invoices.create",
    display_name: "Vytvořit fakturu",
    module: "invoices",
    description: "Vytvářet nové faktury",
  },
  {
    name: "invoices.edit",
    display_name: "Upravit fakturu",
    module: "invoices",
    description: "Upravovat existující faktury",
  },
  {
    name: "invoices.delete",
    display_name: "Smazat fakturu",
    module: "invoices",
    description: "Mazat faktury",
  },

  // Projekty
  {
    name: "projects.view",
    display_name: "Zobrazit projekty",
    module: "projects",
    description: "Prohlížet seznam projektů",
  },
  {
    name: "projects.create",
    display_name: "Vytvořit projekt",
    module: "projects",
    description: "Ručně vytvářet projekty",
  },
  {
    name: "projects.edit",
    display_name: "Upravit projekt",
    module: "projects",
    description: "Upravovat existující projekty",
  },
  {
    name: "projects.delete",
    display_name: "Smazat projekt",
    module: "projects",
    description: "Mazat projekty",
  },
  {
    name: "projects.files",
    display_name: "Soubory projektu",
    module: "projects",
    description: "Spravovat soubory a složky projektu",
  },

  // Zákazníci
  {
    name: "customers.view",
    display_name: "Zobrazit zákazníky",
    module: "customers",
    description: "Prohlížet seznam zákazníků",
  },
  {
    name: "customers.create",
    display_name: "Vytvořit zákazníka",
    module: "customers",
    description: "Vytvářet nové zákazníky",
  },
  {
    name: "customers.edit",
    display_name: "Upravit zákazníka",
    module: "customers",
    description: "Upravovat existující zákazníky",
  },
  {
    name: "customers.delete",
    display_name: "Smazat zákazníka",
    module: "customers",
    description: "Mazat zákazníky",
  },

  // Uživatelé
  {
    name: "users.view",
    display_name: "Zobrazit uživatele",
    module: "users",
    description: "Prohlížet seznam uživatelů",
  },
  {
    name: "users.create",
    display_name: "Vytvořit uživatele",
    module: "users",
    description: "Vytvářet nové uživatele",
  },
  {
    name: "users.edit",
    display_name: "Upravit uživatele",
    module: "users",
    description: "Upravovat existující uživatele",
  },
  {
    name: "users.delete",
    display_name: "Smazat uživatele",
    module: "users",
    description: "Mazat uživatele",
  },

  // Nastavení
  {
    name: "settings.company",
    display_name: "Nastavení společnosti",
    module: "settings",
    description: "Upravovat údaje o společnosti, logo",
  },
  {
    name: "settings.system",
    display_name: "Systémová nastavení",
    module: "settings",
    description: "Spravovat systémová nastavení, 2FA, e-maily, limity",
  },
  {
    name: "settings.banking",
    display_name: "Bankovní účty",
    module: "settings",
    description: "Spravovat bankovní účty společnosti",
  },
  {
    name: "settings.roles",
    display_name: "Role a oprávnění",
    module: "settings",
    description: "Spravovat role a přiřazovat oprávnění",
  },
  {
    name: "settings.templates",
    display_name: "Šablony",
    module: "settings",
    description: "Spravovat šablony nabídek a položek",
  },
  {
    name: "settings.audit",
    display_name: "Audit log",
    module: "settings",
    description: "Prohlížet auditní logy",
  },

  // Sklad
  {
    name: "warehouse.view",
    display_name: "Zobrazit sklad",
    module: "warehouse",
    description: "Prohlížet stav skladu, položky, reporty a historii pohybů",
  },
  {
    name: "warehouse.operate",
    display_name: "Příjem a výdej",
    module: "warehouse",
    description: "Vytvářet a potvrzovat příjmy, výdeje a rezervace",
  },
  {
    name: "warehouse.manage",
    display_name: "Správa skladu",
    module: "warehouse",
    description: "Spravovat katalog materiálů, dodavatele, lokace a kategorie",
  },
  {
    name: "warehouse.inventory",
    display_name: "Inventura",
    module: "warehouse",
    description: "Vytvářet a potvrzovat inventurní sčítkání",
  },
];

async function main() {
  // HARD PRODUCTION GUARD: this seed unconditionally wipes ALL permissions and
  // role_permissions (and seeds an admin/admin user) — purely dev-convenience
  // behavior. Production baseline data must come from tracked Prisma migrations,
  // never from the seed (see CLAUDE.md "Database Migrations"). Refuse to run on
  // production so the destructive wipe can never hit a live database.
  if (process.env.APP_ENV === "production") {
    throw new Error(
      "Odmítnuto: prisma/seed.ts NESMÍ běžet na produkci (APP_ENV=production). " +
        "Seed maže všechna oprávnění a je určen pouze pro vývoj. " +
        "Produkční data musí být zavedena migrací.\n" +
        "Refusing to run: prisma/seed.ts must NEVER run on production " +
        "(APP_ENV=production). It wipes all permissions and is dev-only; " +
        "seed production baseline data via a migration instead.",
    );
  }

  console.log("Seeding permissions...");

  // 1. Clear existing permissions and re-insert current set
  await prisma.role_permissions.deleteMany({});
  await prisma.permissions.deleteMany({});
  console.log("  Cleared old permissions");

  for (const perm of PERMISSIONS) {
    await prisma.permissions.create({ data: perm });
  }
  console.log(`  Inserted ${PERMISSIONS.length} permissions`);

  // 2. Ensure admin role exists
  let adminRole = await prisma.roles.findFirst({ where: { name: "admin" } });
  if (!adminRole) {
    adminRole = await prisma.roles.create({
      data: {
        name: "admin",
        display_name: "Administrátor",
        description: "Hlavní administrátor s plným přístupem",
      },
    });
    console.log("  Created admin role");
  } else {
    console.log("  Admin role already exists (id=" + adminRole.id + ")");
  }

  // 3. Assign all permissions to admin role
  const allPerms = await prisma.permissions.findMany();
  const existingAssignments = await prisma.role_permissions.findMany({
    where: { role_id: adminRole.id },
  });

  // Delete stale assignments (permissions no longer in the list)
  const validIds = new Set(allPerms.map((p) => p.id));
  const staleIds = existingAssignments.filter(
    (a) => !validIds.has(a.permission_id),
  );
  if (staleIds.length > 0) {
    for (const s of staleIds) {
      await prisma.role_permissions.delete({
        where: {
          role_id_permission_id: {
            role_id: adminRole.id,
            permission_id: s.permission_id,
          },
        },
      });
    }
    console.log(`  Removed ${staleIds.length} stale role_permissions`);
  }

  // Add missing assignments
  const existingIds = new Set(existingAssignments.map((a) => a.permission_id));
  let added = 0;
  for (const perm of allPerms) {
    if (!existingIds.has(perm.id)) {
      await prisma.role_permissions.create({
        data: { role_id: adminRole.id, permission_id: perm.id },
      });
      added++;
    }
  }
  if (added > 0) console.log(`  Added ${added} role_permission assignments`);
  console.log(`  Admin role now has all ${allPerms.length} permissions`);

  // 4. Ensure admin user exists
  let adminUser = await prisma.users.findFirst({
    where: { username: "admin" },
  });
  if (!adminUser) {
    const hash = bcrypt.hashSync("admin", 10);
    adminUser = await prisma.users.create({
      data: {
        username: "admin",
        email: "admin@boha.local",
        password_hash: hash,
        first_name: "Admin",
        last_name: "BOHA",
        role_id: adminRole.id,
        is_active: true,
      },
    });
    console.log("  Created admin user (admin / admin)");
  } else if (adminUser.role_id !== adminRole.id) {
    await prisma.users.update({
      where: { id: adminUser.id },
      data: { role_id: adminRole.id },
    });
    console.log("  Updated admin user role_id to admin role");
  } else {
    console.log("  Admin user already exists with correct role");
  }

  // 5. Create default company_settings if not exists
  const existingSettings = await prisma.company_settings.findFirst();
  if (!existingSettings) {
    await prisma.company_settings.create({
      data: {
        company_name: "BOHA s.r.o.",
        default_currency: "CZK",
        default_vat_rate: 21.0,
        available_vat_rates: JSON.stringify([0, 10, 15, 21]),
        available_currencies: JSON.stringify(["CZK", "EUR"]),
        offer_number_pattern: "NAB-{YYYY}-{NNN}",
        order_number_pattern: "OBJ-{YYYY}-{NNN}",
        invoice_number_pattern: "FV-{YYYY}-{NNN}",
        break_threshold_hours: 6.0,
        break_duration_short: 15,
        break_duration_long: 30,
        clock_rounding_minutes: 15,
        require_2fa: false,
        max_login_attempts: 5,
        lockout_minutes: 15,
        max_requests_per_minute: 300,
      },
    });
    console.log("  Created default company_settings");
  } else {
    console.log("  company_settings already exists");
  }

  // 6. Initialize number_sequences for current year
  const year = new Date().getFullYear();
  const types = [
    "quotation",
    "order",
    "invoice",
    "warehouse_receipt",
    "warehouse_issue",
    "warehouse_inventory",
  ];
  for (const type of types) {
    const existing = await prisma.number_sequences.findFirst({
      where: { type, year },
    });
    if (!existing) {
      await prisma.number_sequences.create({
        data: { type, year, last_number: 0 },
      });
      console.log(`  Created number_sequence: ${type}/${year}`);
    }
  }
  console.log("  number_sequences ready");

  console.log(
    "\nSeed complete — " +
      PERMISSIONS.length +
      " permissions, 1 admin role, company_settings + number_sequences ready.",
  );
}

main()
  .catch((e) => {
    console.error("Seed failed:", e);
    process.exit(1);
  })
  .finally(() => prisma.$disconnect());
