import {
  AbsenceReason,
  AuditTargetType,
  EventParticipationStatus,
  InvitationStatus,
  NotdienstAlertStatus,
  NotdienstPlanStatus,
  PrismaClient,
  TerminStatus,
  TerminType,
  UserRole,
} from "@prisma/client";
import { hash } from "bcryptjs";

// =====================================================================
// Kita-Planer · Dev-Seed
// ---------------------------------------------------------------------
// Default: nicht destruktiv. Seed-Daten werden nur angelegt, wenn die DB
// noch keine Kita und keine User enthaelt.
//
// Reset: `npm run db:seed:reset` loescht gezielt die Demo-Daten und baut
// sie neu auf. Production wird nur mit ALLOW_DATABASE_SEED=true erlaubt.
// =====================================================================

const prisma = new PrismaClient();

const DEMO_KITA_SLUG = "waldameisen";
const DEFAULT_PASSWORD = "password123";
const PRIVACY_POLICY_VERSION = "2026-05-01";
const RESET_MODE = process.argv.includes("--reset");

const DEMO_USER_EMAILS = [
  "super@kita-planer.local",
  "admin@waldameisen.local",
  "erzieher@waldameisen.local",
  "mueller@waldameisen.local",
  "schmidt@waldameisen.local",
  "yilmaz@waldameisen.local",
  "pending@waldameisen.local",
  "fischer@waldameisen.local",
  "kowalski@waldameisen.local",
  "weber@waldameisen.local",
];

const DEMO_VERIFICATION_TOKENS = [
  "demo-pending-parent-token",
  "demo-invite-token",
];

type SeedContext = Awaited<ReturnType<typeof createDemoUsers>>;

function dateOnly(date: Date) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}

function addDays(date: Date, days: number) {
  const next = new Date(date);
  next.setDate(next.getDate() + days);
  return dateOnly(next);
}

function addWeeks(date: Date, weeks: number) {
  return addDays(date, weeks * 7);
}

function startOfIsoWeek(date: Date) {
  const normalized = dateOnly(date);
  const day = normalized.getDay() || 7;
  return addDays(normalized, 1 - day);
}

function startOfMonth(date: Date) {
  return new Date(date.getFullYear(), date.getMonth(), 1);
}

function getPreviousMonth(date: Date) {
  return new Date(date.getFullYear(), date.getMonth() - 1, 1);
}

function getLastDayOfPreviousMonth(date: Date) {
  return dateOnly(new Date(date.getFullYear(), date.getMonth(), 0));
}

function getTargetMonth(date: Date) {
  return new Date(date.getFullYear(), date.getMonth() + 1, 1);
}

function getWorkingDays(year: number, month: number, limit?: number) {
  const days: Date[] = [];
  const cursor = new Date(year, month - 1, 1);

  while (cursor.getMonth() === month - 1) {
    const day = cursor.getDay();
    if (day !== 0 && day !== 6) {
      days.push(dateOnly(cursor));
    }
    cursor.setDate(cursor.getDate() + 1);
  }

  return typeof limit === "number" ? days.slice(0, limit) : days;
}

function isSeedAllowed() {
  if (
    process.env.NODE_ENV === "development" ||
    process.env.ALLOW_DATABASE_SEED === "true"
  ) {
    return true;
  }

  console.log(
    "Seed uebersprungen: NODE_ENV ist nicht development. Setze ALLOW_DATABASE_SEED=true, wenn das bewusst gewuenscht ist.",
  );
  return false;
}

async function isDatabaseEmpty() {
  const [kitaCount, userCount] = await Promise.all([
    prisma.kita.count(),
    prisma.user.count(),
  ]);

  return kitaCount === 0 && userCount === 0;
}

async function resetDemoData() {
  const demoUsers = await prisma.user.findMany({
    where: {
      OR: [
        { email: { in: DEMO_USER_EMAILS } },
        { kita: { slug: DEMO_KITA_SLUG } },
      ],
    },
    select: { id: true },
  });

  await prisma.verificationToken.deleteMany({
    where: {
      OR: [
        { token: { in: DEMO_VERIFICATION_TOKENS } },
        { identifier: { in: demoUsers.map((user) => user.id) } },
      ],
    },
  });

  await prisma.kita.deleteMany({ where: { slug: DEMO_KITA_SLUG } });
  await prisma.user.deleteMany({ where: { email: { in: DEMO_USER_EMAILS } } });
}

async function createDemoUsers(passwordHash: string, consentAt: Date) {
  const superAdmin = await prisma.user.create({
    data: {
      email: "super@kita-planer.local",
      passwordHash,
      firstName: "Sys",
      lastName: "Admin",
      role: UserRole.SUPERADMIN,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      emailVerifiedAt: consentAt,
    },
  });

  const kita = await prisma.kita.create({
    data: {
      name: "Waldameisen e.V.",
      slug: DEMO_KITA_SLUG,
      notdienstModuleEnabled: true,
      terminModuleEnabled: true,
      adressbuchModuleEnabled: true,
      notdienstMinPerChildPerMonth: 2,
      notdienstReminderDaysBefore: 7,
    },
  });

  const familyMueller = await prisma.family.create({
    data: {
      kitaId: kita.id,
      name: "Familie Mueller",
    },
  });

  const familySchmidtYilmaz = await prisma.family.create({
    data: {
      kitaId: kita.id,
      name: "Familie Schmidt-Yilmaz",
    },
  });

  const familyFischer = await prisma.family.create({
    data: {
      kitaId: kita.id,
      name: "Familie Fischer",
    },
  });

  const admin = await prisma.user.create({
    data: {
      kitaId: kita.id,
      email: "admin@waldameisen.local",
      passwordHash,
      firstName: "Anna",
      lastName: "Vorstand",
      role: UserRole.ADMIN,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      directoryOptInAt: consentAt,
      emailVerifiedAt: consentAt,
      phone: "+49 30 1000 1000",
      street: "Kitaweg 1",
      postalCode: "10115",
      city: "Berlin",
    },
  });

  const erzieherUser = await prisma.user.create({
    data: {
      kitaId: kita.id,
      email: "erzieher@waldameisen.local",
      passwordHash,
      firstName: "Eva",
      lastName: "Erzieherin",
      role: UserRole.ERZIEHER,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      emailVerifiedAt: consentAt,
      phone: "+49 30 1000 2000",
      street: "Kitaweg 1",
      postalCode: "10115",
      city: "Berlin",
    },
  });

  const koordinator = await prisma.user.create({
    data: {
      kitaId: kita.id,
      familyId: familyMueller.id,
      email: "mueller@waldameisen.local",
      passwordHash,
      firstName: "Maria",
      lastName: "Mueller",
      role: UserRole.KOORDINATOR,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      directoryOptInAt: consentAt,
      emailVerifiedAt: consentAt,
      phone: "+49 30 1234 5678",
      street: "Beispielweg 1",
      postalCode: "10115",
      city: "Berlin",
    },
  });

  const elternSchmidt = await prisma.user.create({
    data: {
      kitaId: kita.id,
      familyId: familySchmidtYilmaz.id,
      email: "schmidt@waldameisen.local",
      passwordHash,
      firstName: "Lukas",
      lastName: "Schmidt",
      role: UserRole.ELTERN,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      emailVerifiedAt: consentAt,
    },
  });

  const elternYilmaz = await prisma.user.create({
    data: {
      kitaId: kita.id,
      familyId: familySchmidtYilmaz.id,
      email: "yilmaz@waldameisen.local",
      passwordHash,
      firstName: "Aylin",
      lastName: "Yilmaz",
      role: UserRole.ELTERN,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      directoryOptInAt: consentAt,
      emailVerifiedAt: consentAt,
      phone: "+49 30 9876 5432",
      street: "Parkstrasse 8",
      postalCode: "10405",
      city: "Berlin",
    },
  });

  const pendingParent = await prisma.user.create({
    data: {
      kitaId: kita.id,
      familyId: familyFischer.id,
      email: "pending@waldameisen.local",
      passwordHash: "",
      firstName: "Lena",
      lastName: "Fischer",
      role: UserRole.ELTERN,
    },
  });

  const familyKowalski = await prisma.family.create({
    data: {
      kitaId: kita.id,
      name: "Familie Kowalski",
    },
  });

  const familyWeber = await prisma.family.create({
    data: {
      kitaId: kita.id,
      name: "Familie Weber",
    },
  });

  const elternFischer = await prisma.user.create({
    data: {
      kitaId: kita.id,
      familyId: familyFischer.id,
      email: "fischer@waldameisen.local",
      passwordHash,
      firstName: "Frank",
      lastName: "Fischer",
      role: UserRole.ELTERN,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      directoryOptInAt: consentAt,
      emailVerifiedAt: consentAt,
      phone: "+49 30 5555 1234",
      street: "Fischerweg 4",
      postalCode: "10247",
      city: "Berlin",
    },
  });

  const elternKowalski = await prisma.user.create({
    data: {
      kitaId: kita.id,
      familyId: familyKowalski.id,
      email: "kowalski@waldameisen.local",
      passwordHash,
      firstName: "Jan",
      lastName: "Kowalski",
      role: UserRole.ELTERN,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      directoryOptInAt: consentAt,
      emailVerifiedAt: consentAt,
      phone: "+49 30 5555 5678",
      street: "Grenzallee 12",
      postalCode: "12057",
      city: "Berlin",
    },
  });

  const elternWeber = await prisma.user.create({
    data: {
      kitaId: kita.id,
      familyId: familyWeber.id,
      email: "weber@waldameisen.local",
      passwordHash,
      firstName: "Sabine",
      lastName: "Weber",
      role: UserRole.ELTERN,
      privacyPolicyAcceptedAt: consentAt,
      privacyPolicyVersion: PRIVACY_POLICY_VERSION,
      directoryOptInAt: consentAt,
      emailVerifiedAt: consentAt,
      phone: "+49 30 5555 9012",
      street: "Weberstrasse 7",
      postalCode: "10249",
      city: "Berlin",
    },
  });

  return {
    kita,
    familyMueller,
    familySchmidtYilmaz,
    familyFischer,
    familyKowalski,
    familyWeber,
    superAdmin,
    admin,
    erzieherUser,
    koordinator,
    elternSchmidt,
    elternYilmaz,
    pendingParent,
    elternFischer,
    elternKowalski,
    elternWeber,
  };
}

async function createChildren({
  kita,
  familyMueller,
  familySchmidtYilmaz,
  familyFischer,
  familyKowalski,
  familyWeber,
}: SeedContext) {
  const anna = await prisma.child.create({
    data: {
      kitaId: kita.id,
      familyId: familyMueller.id,
      firstName: "Anna",
      lastName: "Mueller",
      dateOfBirth: new Date("2021-03-15"),
    },
  });

  const ben = await prisma.child.create({
    data: {
      kitaId: kita.id,
      familyId: familyMueller.id,
      firstName: "Ben",
      lastName: "Mueller",
      dateOfBirth: new Date("2023-07-22"),
      notes: "Geschwisterkind von Anna.",
    },
  });

  const clara = await prisma.child.create({
    data: {
      kitaId: kita.id,
      familyId: familySchmidtYilmaz.id,
      firstName: "Clara",
      lastName: "Schmidt",
      dateOfBirth: new Date("2022-11-03"),
    },
  });

  const emil = await prisma.child.create({
    data: {
      kitaId: kita.id,
      familyId: familySchmidtYilmaz.id,
      firstName: "Emil",
      lastName: "Yilmaz",
      dateOfBirth: new Date("2021-09-09"),
    },
  });

  const nina = await prisma.child.create({
    data: {
      kitaId: kita.id,
      familyId: familyFischer.id,
      firstName: "Nina",
      lastName: "Fischer",
      dateOfBirth: new Date("2022-05-30"),
    },
  });

  const leo = await prisma.child.create({
    data: {
      kitaId: kita.id,
      familyId: familyKowalski.id,
      firstName: "Leo",
      lastName: "Kowalski",
      dateOfBirth: new Date("2022-08-12"),
    },
  });

  const mia = await prisma.child.create({
    data: {
      kitaId: kita.id,
      familyId: familyWeber.id,
      firstName: "Mia",
      lastName: "Weber",
      dateOfBirth: new Date("2021-05-18"),
    },
  });

  return { anna, ben, clara, emil, nina, leo, mia };
}

async function createEducators(kitaId: string) {
  const sabine = await prisma.educator.create({
    data: { kitaId, firstName: "Sabine", lastName: "Schulze" },
  });
  const petra = await prisma.educator.create({
    data: { kitaId, firstName: "Petra", lastName: "Klein" },
  });
  const jonas = await prisma.educator.create({
    data: { kitaId, firstName: "Jonas", lastName: "Wagner" },
  });
  const norbert = await prisma.educator.create({
    data: {
      kitaId,
      firstName: "Norbert",
      lastName: "Altmann",
      active: false,
    },
  });

  return { sabine, petra, jonas, norbert };
}

async function createParentDuties({
  kita,
  koordinator,
  elternSchmidt,
  elternYilmaz,
}: SeedContext) {
  const waesche = await prisma.parentDuty.create({
    data: {
      kitaId: kita.id,
      name: "Waeschedienst",
      description: "Kita-Waesche waschen und zurueckbringen.",
    },
  });

  const einkauf = await prisma.parentDuty.create({
    data: {
      kitaId: kita.id,
      name: "Einkauf",
      description: "Woechentlicher Einkauf fuer die Kita-Kueche.",
    },
  });

  const garten = await prisma.parentDuty.create({
    data: {
      kitaId: kita.id,
      name: "Gartendienst",
      description: "Aussenbereich pflegen und Spielmaterial pruefen.",
    },
  });

  await prisma.parentDutyAssignment.createMany({
    data: [
      { kitaId: kita.id, dutyId: waesche.id, userId: elternSchmidt.id },
      { kitaId: kita.id, dutyId: einkauf.id, userId: koordinator.id },
      { kitaId: kita.id, dutyId: garten.id, userId: elternYilmaz.id },
    ],
  });
}

async function createAbsences(
  { kita }: SeedContext,
  children: Awaited<ReturnType<typeof createChildren>>,
) {
  const today = dateOnly(new Date());

  await prisma.absence.createMany({
    data: [
      {
        kitaId: kita.id,
        childId: children.nina.id,
        startDate: today,
        endDate: today,
        reason: AbsenceReason.ILLNESS,
        note: "Fieber, bleibt heute zuhause.",
      },
      {
        kitaId: kita.id,
        childId: children.emil.id,
        startDate: addDays(today, 1),
        endDate: addDays(today, 2),
        reason: AbsenceReason.VACATION,
        note: "Familienbesuch.",
      },
    ],
  });
}

async function createDutyPlan({
  kita,
  familyMueller,
  familySchmidtYilmaz,
  familyFischer,
}: SeedContext) {
  const waesche = await prisma.dutyType.create({
    data: {
      kitaId: kita.id,
      name: "Waeschedienst",
      description: "Woechentlicher Dienstplan fuer Kita-Waesche.",
    },
  });

  const einkauf = await prisma.dutyType.create({
    data: {
      kitaId: kita.id,
      name: "Einkauf",
      description: "Woechentlicher Einkauf nach Kita-Liste.",
    },
  });

  const families = [familyMueller, familySchmidtYilmaz, familyFischer];
  const currentWeek = startOfIsoWeek(new Date());

  await prisma.dutyAssignment.createMany({
    data: Array.from({ length: 8 }).flatMap((_, index) => {
      const startDate = addWeeks(currentWeek, index);
      const endDate = addDays(startDate, 6);
      return [
        {
          kitaId: kita.id,
          dutyTypeId: waesche.id,
          familyId: families[index % families.length].id,
          startDate,
          endDate,
        },
        {
          kitaId: kita.id,
          dutyTypeId: einkauf.id,
          familyId: families[(index + 1) % families.length].id,
          startDate,
          endDate,
        },
      ];
    }),
  });
}

async function createInvites({ kita, admin, pendingParent }: SeedContext) {
  const expires = addDays(new Date(), 7);

  await prisma.invitation.create({
    data: {
      kitaId: kita.id,
      email: "invite@waldameisen.local",
      role: UserRole.ELTERN,
      token: "demo-invite-token",
      status: InvitationStatus.PENDING,
      expiresAt: expires,
      invitedById: admin.id,
    },
  });

  await prisma.verificationToken.create({
    data: {
      identifier: pendingParent.id,
      token: "demo-pending-parent-token",
      expires,
    },
  });
}

async function createAnnouncements(context: SeedContext) {
  const { kita, admin, koordinator, elternSchmidt, elternYilmaz, elternFischer } = context;

  const sommerfest = await prisma.announcement.create({
    data: {
      kitaId: kita.id,
      title: "Sommerfest: Helferliste und Ablauf",
      content:
        "## Liebe Familien,\n\nunser Sommerfest findet naechsten Monat im Kita-Garten statt. Bitte merkt euch den Termin vor. Details zu Aufbau, Kuchen und Getraenken folgen ueber das Schwarze Brett.",
      authorId: admin.id,
    },
  });

  const garderobe = await prisma.announcement.create({
    data: {
      kitaId: kita.id,
      title: "Neue Garderoben-Regelung",
      content:
        "Ab Montag bitten wir alle Familien, Wechselkleidung wieder in die beschrifteten Boxen zu legen. So bleibt der Morgen fuer Kinder und Team entspannter.",
      authorId: admin.id,
    },
  });

  await prisma.attachment.create({
    data: {
      announcementId: sommerfest.id,
      fileName: "sommerfest_ablauf.pdf",
      fileUrl: "https://example.com/sommerfest_ablauf.pdf",
      fileType: "application/pdf",
    },
  });

  await prisma.announcementRead.createMany({
    data: [
      { userId: koordinator.id, announcementId: sommerfest.id },
      { userId: elternSchmidt.id, announcementId: sommerfest.id },
      { userId: elternYilmaz.id, announcementId: sommerfest.id },
      { userId: elternFischer.id, announcementId: garderobe.id },
    ],
  });
}

async function createTermine(
  context: SeedContext,
  children: Awaited<ReturnType<typeof createChildren>>,
) {
  const { kita, admin, koordinator, elternSchmidt, elternYilmaz, elternFischer, elternKowalski } = context;
  const now = new Date();

  const elternabend = await prisma.termin.create({
    data: {
      kitaId: kita.id,
      title: "Elternabend Fruehling",
      description: "Austausch zu Terminen, Notdienst und Sommerplanung.",
      type: TerminType.ELTERNABEND,
      status: TerminStatus.CONFIRMED,
      startDate: addDays(now, 10),
      endDate: addDays(now, 10),
      allDay: false,
      mitbringselListEnabled: true,
      createdById: admin.id,
      approvedById: admin.id,
      approvedAt: now,
    },
  });

  await prisma.termin.create({
    data: {
      kitaId: kita.id,
      title: "Teamtag",
      description: "Die Kita bleibt wegen interner Fortbildung geschlossen.",
      type: TerminType.TEAMTAG,
      status: TerminStatus.CONFIRMED,
      startDate: addDays(now, 18),
      endDate: addDays(now, 18),
      allDay: true,
      createdById: admin.id,
      approvedById: admin.id,
      approvedAt: now,
    },
  });

  await prisma.termin.create({
    data: {
      kitaId: kita.id,
      title: "Elterncafe im Garten",
      description: "Anfrage eines Elternteils, noch nicht bestaetigt.",
      type: TerminType.ELTERNCAFE,
      status: TerminStatus.PENDING,
      startDate: addDays(now, 24),
      endDate: addDays(now, 24),
      allDay: false,
      createdById: elternSchmidt.id,
    },
  });

  await prisma.termin.create({
    data: {
      kitaId: kita.id,
      title: "Spontaner Ausflug",
      description: "Beispiel fuer eine abgelehnte Terminanfrage.",
      type: TerminType.SONSTIGES,
      status: TerminStatus.REJECTED,
      startDate: addDays(now, -6),
      endDate: addDays(now, -6),
      allDay: true,
      createdById: elternYilmaz.id,
      approvedById: koordinator.id,
      approvedAt: addDays(now, -5),
      rejectionReason: "Zu kurzfristig fuer die Gruppe.",
    },
  });

  const zooAusflug = await prisma.termin.create({
    data: {
      kitaId: kita.id,
      title: "Ausflug in den Zoo",
      description: "Gemeinsamer Ausflug der gesamten Kita-Gruppe in den Berliner Zoo.",
      type: TerminType.SONSTIGES,
      status: TerminStatus.CONFIRMED,
      startDate: addDays(now, 15),
      endDate: addDays(now, 15),
      allDay: true,
      requiresRsvp: true,
      rsvpDeadline: addDays(now, 5),
      participantInfo: "Bitte wetterfeste Kleidung und Rucksack-Verpflegung mitbringen.",
      createdById: admin.id,
      approvedById: admin.id,
      approvedAt: now,
    },
  });

  await prisma.eventParticipation.createMany({
    data: [
      { kitaId: kita.id, eventId: zooAusflug.id, childId: children.anna.id, status: EventParticipationStatus.ATTENDING },
      { kitaId: kita.id, eventId: zooAusflug.id, childId: children.clara.id, status: EventParticipationStatus.ATTENDING },
      { kitaId: kita.id, eventId: zooAusflug.id, childId: children.emil.id, status: EventParticipationStatus.NOT_ATTENDING },
      { kitaId: kita.id, eventId: zooAusflug.id, childId: children.leo.id, status: EventParticipationStatus.ATTENDING },
    ],
  });

  await prisma.termin.create({
    data: {
      kitaId: kita.id,
      title: "Mitmach-Tag (Garten)",
      description: "Gemeinsames Herrichten des Gartens fuer die warme Jahreszeit. (Abgesagt wegen Dauerregen)",
      type: TerminType.MITMACH_TAG,
      status: TerminStatus.CANCELLED,
      startDate: addDays(now, 2),
      endDate: addDays(now, 2),
      allDay: false,
      createdById: admin.id,
    },
  });

  const sommerfestEvent = await prisma.termin.create({
    data: {
      kitaId: kita.id,
      title: "Sommerfest Waldameisen",
      description: "Unser jaehrliches grosses Sommerfest im Kita-Garten mit Buffet und Spielstationen.",
      type: TerminType.KITA_FEST,
      status: TerminStatus.CONFIRMED,
      startDate: addDays(now, 30),
      endDate: addDays(now, 30),
      allDay: false,
      mitbringselListEnabled: true,
      createdById: admin.id,
      approvedById: admin.id,
      approvedAt: now,
    },
  });

  await prisma.mitbringselItem.createMany({
    data: [
      {
        kitaId: kita.id,
        terminId: elternabend.id,
        userId: koordinator.id,
        content: "Obstplatte",
      },
      {
        kitaId: kita.id,
        terminId: elternabend.id,
        userId: elternSchmidt.id,
        content: "Brot und Aufstrich",
      },
      {
        kitaId: kita.id,
        terminId: sommerfestEvent.id,
        userId: elternYilmaz.id,
        content: "Nudelsalat (vegan)",
      },
      {
        kitaId: kita.id,
        terminId: sommerfestEvent.id,
        userId: elternFischer.id,
        content: "Mehrweg-Becher (ca. 30 Stk.)",
      },
      {
        kitaId: kita.id,
        terminId: sommerfestEvent.id,
        userId: elternKowalski.id,
        content: "Apfelsaft & Wasser",
      },
    ],
  });
}

async function createNotdienstData(
  context: SeedContext,
  children: Awaited<ReturnType<typeof createChildren>>,
  educators: Awaited<ReturnType<typeof createEducators>>,
) {
  const { kita, koordinator, elternSchmidt, elternYilmaz, elternWeber, elternKowalski } = context;
  const today = dateOnly(new Date());
  const currentMonth = startOfMonth(today);
  const previousMonth = getPreviousMonth(today);
  const previousAssignmentDate = getLastDayOfPreviousMonth(today);
  const targetMonth = getTargetMonth(today);

  const availabilityPairs = [
    { childId: children.anna.id, userId: koordinator.id },
    { childId: children.clara.id, userId: elternSchmidt.id },
    { childId: children.emil.id, userId: elternYilmaz.id },
    { childId: children.ben.id, userId: koordinator.id },
    { childId: children.leo.id, userId: elternKowalski.id },
    { childId: children.mia.id, userId: elternWeber.id },
  ];

  const targetWorkingDays = getWorkingDays(
    targetMonth.getFullYear(),
    targetMonth.getMonth() + 1,
    12,
  );

  await prisma.notdienstAvailability.createMany({
    data: targetWorkingDays.map((date, index) => {
      const pair = availabilityPairs[index % availabilityPairs.length];
      return {
        kitaId: kita.id,
        childId: pair.childId,
        userId: pair.userId,
        date,
      };
    }),
  });

  const currentPlan = await prisma.notdienstPlan.create({
    data: {
      kitaId: kita.id,
      year: currentMonth.getFullYear(),
      month: currentMonth.getMonth() + 1,
      status: NotdienstPlanStatus.PUBLISHED,
      createdById: koordinator.id,
      publishedAt: new Date(),
    },
  });

  await prisma.notdienstAssignment.create({
    data: {
      kitaId: kita.id,
      planId: currentPlan.id,
      childId: children.anna.id,
      date: today,
    },
  });

  const alertAssignmentDate = addDays(today, 3);
  const pendingAlertAssignment = await prisma.notdienstAssignment.create({
    data: {
      kitaId: kita.id,
      planId: currentPlan.id,
      childId: children.emil.id,
      date: alertAssignmentDate,
    },
  });

  await prisma.notdienstAlert.create({
    data: {
      kitaId: kita.id,
      assignmentId: pendingAlertAssignment.id,
      parentUserId: elternYilmaz.id,
      triggeredById: koordinator.id,
      educatorId: educators.petra.id,
      status: NotdienstAlertStatus.PENDING,
      confirmationToken: "demo-pending-alert-token",
      triggeredAt: today,
      notes: "Es fehlen zwei Kraefte. Bitte Notdienst besetzen.",
    },
  });

  const previousPlan = await prisma.notdienstPlan.create({
    data: {
      kitaId: kita.id,
      year: previousMonth.getFullYear(),
      month: previousMonth.getMonth() + 1,
      status: NotdienstPlanStatus.PUBLISHED,
      createdById: koordinator.id,
      publishedAt: addDays(today, -10),
    },
  });

  const pastAssignment = await prisma.notdienstAssignment.create({
    data: {
      kitaId: kita.id,
      planId: previousPlan.id,
      childId: children.clara.id,
      date: previousAssignmentDate,
    },
  });

  await prisma.notdienstAlert.create({
    data: {
      kitaId: kita.id,
      assignmentId: pastAssignment.id,
      parentUserId: elternSchmidt.id,
      triggeredById: koordinator.id,
      educatorId: educators.sabine.id,
      status: NotdienstAlertStatus.CONFIRMED,
      confirmationToken: "demo-confirmed-alert-token",
      triggeredAt: previousAssignmentDate,
      confirmedAt: previousAssignmentDate,
      notes: "Beispiel-Alarm aus Seed-Daten.",
    },
  });

  const draftPlan = await prisma.notdienstPlan.create({
    data: {
      kitaId: kita.id,
      year: targetMonth.getFullYear(),
      month: targetMonth.getMonth() + 1,
      status: NotdienstPlanStatus.DRAFT,
      createdById: koordinator.id,
    },
  });
}

async function createAuditLogs({ kita, superAdmin, admin }: SeedContext) {
  await prisma.auditLog.createMany({
    data: [
      {
        actorUserId: superAdmin.id,
        actorEmail: superAdmin.email,
        action: "KITA_CREATE",
        targetType: AuditTargetType.KITA,
        targetId: kita.id,
        targetLabel: kita.name,
        targetKitaId: kita.id,
        metadata: { name: kita.name, slug: kita.slug },
        createdAt: addDays(new Date(), -30),
      },
      {
        actorUserId: superAdmin.id,
        actorEmail: superAdmin.email,
        action: "USER_ROLE_UPDATE",
        targetType: AuditTargetType.USER,
        targetId: admin.id,
        targetLabel: admin.email,
        targetKitaId: kita.id,
        metadata: { oldRole: "ELTERN", newRole: "ADMIN" },
        createdAt: addDays(new Date(), -28),
      },
      {
        actorUserId: admin.id,
        actorEmail: admin.email,
        action: "KITA_MODULE_UPDATE",
        targetType: AuditTargetType.KITA,
        targetId: kita.id,
        targetLabel: kita.name,
        targetKitaId: kita.id,
        metadata: {
          notdienstModuleEnabled: true,
          terminModuleEnabled: true,
          adressbuchModuleEnabled: true,
        },
        createdAt: addDays(new Date(), -25),
      },
    ],
  });
}

async function createDemoData() {
  console.log("Seeding Kita-Planer demo data...");

  const passwordHash = await hash(DEFAULT_PASSWORD, 12);
  const consentAt = new Date();
  const context = await createDemoUsers(passwordHash, consentAt);
  const children = await createChildren(context);
  const educators = await createEducators(context.kita.id);

  await createParentDuties(context);
  await createDutyPlan(context);
  await createAbsences(context, children);
  await createInvites(context);
  await createAnnouncements(context);
  await createTermine(context, children);
  await createNotdienstData(context, children, educators);
  await createAuditLogs(context);

  printSummary(context, children);
}

async function seedIfEmpty() {
  if (!(await isDatabaseEmpty())) {
    console.log("Seed uebersprungen: Datenbank enthaelt bereits Kita- oder User-Daten.");
    return;
  }

  await createDemoData();
}

function printSummary(
  context: SeedContext,
  children: Awaited<ReturnType<typeof createChildren>>,
) {
  const {
    kita,
    superAdmin,
    admin,
    erzieherUser,
    koordinator,
    elternSchmidt,
    elternYilmaz,
    elternFischer,
    elternKowalski,
    elternWeber,
    pendingParent,
  } = context;
  console.log("Seed complete");
  console.log("");
  console.log(`   Kita:           ${kita.name} (${kita.slug})`);
  console.log("");
  console.log(`   Logins (Passwort jeweils: ${DEFAULT_PASSWORD})`);
  console.log(`     Superadmin:    ${superAdmin.email}`);
  console.log(`     Admin:         ${admin.email}`);
  console.log(`     Erzieherin:    ${erzieherUser.email}`);
  console.log(`     Koordinator:   ${koordinator.email}`);
  console.log(`     Eltern:        ${elternSchmidt.email}`);
  console.log(`     Eltern:        ${elternYilmaz.email}`);
  console.log(`     Eltern (Fischer): ${elternFischer.email}`);
  console.log(`     Eltern (Kowalski): ${elternKowalski.email}`);
  console.log(`     Eltern (Weber):   ${elternWeber.email}`);
  console.log("");
  console.log(
    `   Offener Invite: ${pendingParent.email} -> /invite/demo-pending-parent-token`,
  );
  console.log(
    `   Kinder: ${Object.values(children)
      .map((child) => `${child.firstName} ${child.lastName}`)
      .join(", ")}`,
  );
}

async function main() {
  if (!isSeedAllowed()) {
    return;
  }

  if (RESET_MODE) {
    console.log("Reset demo seed data...");
    await resetDemoData();
    await createDemoData();
    return;
  }

  await seedIfEmpty();
}

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