/* IncrelogEMS database seed */
import { PrismaClient } from "@prisma/client";
import bcrypt from "bcryptjs";
import { seedMonitoring } from "./seed-monitoring";
import { seedFinalExams } from "./seed-final-exams";
import { seedPatternPlans } from "./seed-pattern-plans";
import { seedCompetitions } from "./seed-competitions";
import { seedHighSchool } from "./seed-highschool";
import { seedCampus } from "./seed-campus";
import { seedCampusExtra } from "./seed-campus-extra";
import { resetBoardSubjects } from "./reset-subjects";

const prisma = new PrismaClient();

type PlanSeed = {
  name: string;
  nameBn: string;
  institutionType: string;
  price: number;
  durationMonths: number;
  maxStudents: number;
  features: string[];
  featuresBn: string[];
};

const basicFeatures = [
  "Up to {N} students",
  "Class & section setup",
  "Subject management",
  "Student attendance",
  "Basic reports",
];
const basicFeaturesBn = [
  "সর্বোচ্চ {N} জন শিক্ষার্থী",
  "শ্রেণি ও শাখা সেটআপ",
  "বিষয় ব্যবস্থাপনা",
  "শিক্ষার্থী হাজিরা",
  "প্রাথমিক রিপোর্ট",
];
const premiumFeatures = [
  "Up to {N} students",
  "Everything in Basic",
  "Exam & results management",
  "Payment tracking",
  "SMS & email notifications",
  "Priority support",
];
const premiumFeaturesBn = [
  "সর্বোচ্চ {N} জন শিক্ষার্থী",
  "বেসিকের সবকিছু",
  "পরীক্ষা ও ফলাফল ব্যবস্থাপনা",
  "পেমেন্ট ট্র্যাকিং",
  "এসএমএস ও ইমেইল নোটিফিকেশন",
  "প্রায়োরিটি সাপোর্ট",
];

function plan(
  type: string,
  typeName: string,
  typeNameBn: string,
  tier: "Basic" | "Premium",
  tierBn: string,
  price: number,
  maxStudents: number
): PlanSeed {
  const isPremium = tier === "Premium";
  const feats = (isPremium ? premiumFeatures : basicFeatures).map((f) => f.replace("{N}", maxStudents.toLocaleString("en-US")));
  const featsBn = (isPremium ? premiumFeaturesBn : basicFeaturesBn).map((f) =>
    f.replace("{N}", maxStudents.toLocaleString("en-US"))
  );
  return {
    name: `${typeName} ${tier}`,
    nameBn: `${typeNameBn} ${tierBn}`,
    institutionType: type,
    price,
    durationMonths: 12,
    maxStudents,
    features: feats,
    featuresBn: featsBn,
  };
}

const packagePlans: PlanSeed[] = [
  plan("KINDERGARTEN", "Kindergarten", "কিন্ডারগার্টেন", "Basic", "বেসিক", 8000, 300),
  plan("KINDERGARTEN", "Kindergarten", "কিন্ডারগার্টেন", "Premium", "প্রিমিয়াম", 15000, 1000),
  plan("PRIMARY", "Primary", "প্রাথমিক", "Basic", "বেসিক", 12000, 500),
  plan("PRIMARY", "Primary", "প্রাথমিক", "Premium", "প্রিমিয়াম", 22000, 1500),
  plan("HIGH_SCHOOL", "High School", "হাই স্কুল", "Basic", "বেসিক", 18000, 800),
  plan("HIGH_SCHOOL", "High School", "হাই স্কুল", "Premium", "প্রিমিয়াম", 35000, 2500),
  plan("COLLEGE", "College", "কলেজ", "Basic", "বেসিক", 25000, 1200),
  plan("COLLEGE", "College", "কলেজ", "Premium", "প্রিমিয়াম", 45000, 3000),
  plan("UNIVERSITY", "University", "বিশ্ববিদ্যালয়", "Basic", "বেসিক", 60000, 3000),
  plan("UNIVERSITY", "University", "বিশ্ববিদ্যালয়", "Premium", "প্রিমিয়াম", 120000, 10000),
  plan("COACHING", "Coaching", "কোচিং", "Basic", "বেসিক", 10000, 600),
  plan("COACHING", "Coaching", "কোচিং", "Premium", "প্রিমিয়াম", 20000, 2000),
  plan("MADRASHA", "Madrasha", "মাদ্রাসা", "Basic", "বেসিক", 10000, 600),
  plan("MADRASHA", "Madrasha", "মাদ্রাসা", "Premium", "প্রিমিয়াম", 20000, 2000),
];

type ItemSeed = { category: string; name: string; nameBn: string };

const academicItems: ItemSeed[] = [
  // Class
  { category: "CLASS", name: "Play", nameBn: "প্লে" },
  { category: "CLASS", name: "Nursery", nameBn: "নার্সারি" },
  { category: "CLASS", name: "KG", nameBn: "কেজি" },
  ...[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((n) => ({
    category: "CLASS",
    name: `Class ${n}`,
    nameBn: `শ্রেণি ${n}`,
  })),
  { category: "CLASS", name: "Class 11", nameBn: "একাদশ শ্রেণি" },
  { category: "CLASS", name: "Class 12", nameBn: "দ্বাদশ শ্রেণি" },
  // Section
  ...["A", "B", "C", "D", "E"].map((s, i) => ({
    category: "SECTION",
    name: `Section ${s}`,
    nameBn: `শাখা ${["ক", "খ", "গ", "ঘ", "ঙ"][i]}`,
  })),
  // Department
  { category: "DEPARTMENT", name: "Science", nameBn: "বিজ্ঞান" },
  { category: "DEPARTMENT", name: "Commerce", nameBn: "ব্যবসায় শিক্ষা" },
  { category: "DEPARTMENT", name: "Arts & Humanities", nameBn: "কলা ও মানবিক" },
  { category: "DEPARTMENT", name: "Computer Science", nameBn: "কম্পিউটার বিজ্ঞান" },
  { category: "DEPARTMENT", name: "Business Administration", nameBn: "ব্যবসায় প্রশাসন" },
  { category: "DEPARTMENT", name: "Electrical Engineering", nameBn: "তড়িৎ প্রকৌশল" },
  // Session
  { category: "SESSION", name: "2024-25", nameBn: "শিক্ষাবর্ষ ২০২৪-২৫" },
  { category: "SESSION", name: "2025-26", nameBn: "শিক্ষাবর্ষ ২০২৫-২৬" },
  { category: "SESSION", name: "2026-27", nameBn: "শিক্ষাবর্ষ ২০২৬-২৭" },
  // Subject
  { category: "SUBJECT", name: "Bangla", nameBn: "বাংলা" },
  { category: "SUBJECT", name: "English", nameBn: "ইংরেজি" },
  { category: "SUBJECT", name: "Mathematics", nameBn: "গণিত" },
  { category: "SUBJECT", name: "Science", nameBn: "সাধারণ বিজ্ঞান" },
  { category: "SUBJECT", name: "Physics", nameBn: "পদার্থবিজ্ঞান" },
  { category: "SUBJECT", name: "Chemistry", nameBn: "রসায়ন" },
  { category: "SUBJECT", name: "Biology", nameBn: "জীববিজ্ঞান" },
  { category: "SUBJECT", name: "Higher Mathematics", nameBn: "উচ্চতর গণিত" },
  { category: "SUBJECT", name: "ICT", nameBn: "তথ্য ও যোগাযোগ প্রযুক্তি" },
  { category: "SUBJECT", name: "Religion & Moral Education", nameBn: "ধর্ম ও নৈতিক শিক্ষা" },
  { category: "SUBJECT", name: "Social Science", nameBn: "সমাজ বিজ্ঞান" },
  { category: "SUBJECT", name: "Accounting", nameBn: "হিসাববিজ্ঞান" },
  { category: "SUBJECT", name: "Arabic", nameBn: "আরবি" },
  // Group
  { category: "GROUP", name: "Science", nameBn: "বিজ্ঞান" },
  { category: "GROUP", name: "Humanities", nameBn: "মানবিক" },
  { category: "GROUP", name: "Business Studies", nameBn: "ব্যবসায় শিক্ষা" },
  // Shift
  { category: "SHIFT", name: "Morning", nameBn: "সকাল" },
  { category: "SHIFT", name: "Day", nameBn: "দিন" },
  { category: "SHIFT", name: "Evening", nameBn: "সন্ধ্যা" },
  // Room
  ...["101", "102", "103", "201", "202", "203", "301", "302"].map((r) => ({
    category: "ROOM",
    name: `Room ${r}`,
    nameBn: `কক্ষ ${r}`,
  })),
  { category: "ROOM", name: "Science Lab", nameBn: "বিজ্ঞান ল্যাব" },
  { category: "ROOM", name: "Computer Lab", nameBn: "কম্পিউটার ল্যাব" },
];

async function main() {
  console.log("🌱 Seeding IncrelogEMS database…");

  // Clean existing data (dependency order)
  await prisma.classSchedule.deleteMany();
  await prisma.committeeMember.deleteMany();
  await prisma.committee.deleteMany();
  await prisma.eventItem.deleteMany();
  await prisma.complaint.deleteMany();
  await prisma.notice.deleteMany();
  await prisma.hostelAttendance.deleteMany();
  await prisma.hostelMember.deleteMany();
  await prisma.hostelRoom.deleteMany();
  await prisma.hostel.deleteMany();
  await prisma.transportPayment.deleteMany();
  await prisma.transportMember.deleteMany();
  await prisma.transportStop.deleteMany();
  await prisma.transportRoute.deleteMany();
  await prisma.transportVehicle.deleteMany();
  await prisma.smsPurchase.deleteMany();
  await prisma.commSetting.deleteMany();
  await prisma.stockMovement.deleteMany();
  await prisma.inventoryItem.deleteMany();
  await prisma.bookIssue.deleteMany();
  await prisma.book.deleteMany();
  await prisma.broadcastRecipient.deleteMany();
  await prisma.broadcast.deleteMany();
  await prisma.salaryPayment.deleteMany();
  await prisma.examSchedule.deleteMany();
  await prisma.exam.deleteMany();
  await prisma.studentActivityRecipient.deleteMany();
  await prisma.studentActivity.deleteMany();
  await prisma.studentAttendance.deleteMany();
  await prisma.accountEntry.deleteMany();
  await prisma.accountHead.deleteMany();
  await prisma.leaveRequest.deleteMany();
  await prisma.identityManager.deleteMany();
  await prisma.staffAttendance.deleteMany();
  await prisma.staff.deleteMany();
  await prisma.message.deleteMany();
  await prisma.feeCollection.deleteMany();
  await prisma.feeSchedule.deleteMany();
  await prisma.feeHead.deleteMany();
  await prisma.student.deleteMany();
  await prisma.admission.deleteMany();
  await prisma.academicSelection.deleteMany();
  await prisma.payment.deleteMany();
  await prisma.subscription.deleteMany();
  await prisma.packageRequest.deleteMany();
  await prisma.user.deleteMany();
  await prisma.institution.deleteMany();
  await prisma.packagePlan.deleteMany();
  await prisma.academicItem.deleteMany();

  // ---- Central controller (IncrelogEMS) ----
  const centralPassword = await bcrypt.hash("Admin@123", 10);
  const central = await prisma.user.create({
    data: {
      name: "IncrelogEMS Admin",
      email: "admin@increlogems.com",
      passwordHash: centralPassword,
      role: "SUPER_ADMIN",
    },
  });
  console.log("  ✔ Central controller: admin@increlogems.com / Admin@123");

  // ---- Package plans ----
  const createdPlans: Record<string, { id: number }> = {};
  for (const p of packagePlans) {
    const created = await prisma.packagePlan.create({
      data: {
        name: p.name,
        nameBn: p.nameBn,
        institutionType: p.institutionType as never,
        price: p.price,
        durationMonths: p.durationMonths,
        maxStudents: p.maxStudents,
        features: p.features,
        featuresBn: p.featuresBn,
        isActive: true,
      },
    });
    createdPlans[p.name] = created;
  }
  console.log(`  ✔ ${packagePlans.length} package plans`);

  // ---- Academic catalog ----
  for (const item of academicItems) {
    await prisma.academicItem.create({
      data: { category: item.category as never, name: item.name, nameBn: item.nameBn },
    });
  }
  console.log(`  ✔ ${academicItems.length} academic items`);

  const demoPassword = await bcrypt.hash("School@123", 10);
  const demoPassword2 = await bcrypt.hash("Demo@123", 10);

  // ---- Demo High School (ACTIVE, fully paid) ----
  const school = await prisma.institution.create({
    data: {
      name: "Demo High School",
      code: "HS-1001",
      type: "PRIMARY_AND_HIGH_SCHOOL",
      email: "school@demo.com",
      phone: "+880 1711-000111",
      address: "12/B, Dhanmondi, Dhaka",
      district: "Dhaka",
      subDistrict: "Dhaka Metropolitan",
      status: "ACTIVE",
      createdAt: new Date("2026-01-15"),
      users: {
        create: {
          name: "School Admin",
          email: "school@demo.com",
          passwordHash: demoPassword,
          role: "INSTITUTION_ADMIN",
        },
      },
    },
  });

  const schoolPlan = createdPlans["High School Premium"];
  const schoolRequest = await prisma.packageRequest.create({
    data: {
      institutionId: school.id,
      packagePlanId: schoolPlan.id,
      note: "We need the premium package for the new academic year.",
      status: "APPROVED",
      createdAt: new Date("2026-02-20"),
      decidedAt: new Date("2026-02-25"),
    },
  });
  const schoolSubscription = await prisma.subscription.create({
    data: {
      institutionId: school.id,
      packagePlanId: schoolPlan.id,
      requestId: schoolRequest.id,
      startDate: new Date("2026-03-01"),
      endDate: new Date("2027-02-28"),
      totalAmount: 35000,
      status: "ACTIVE",
      createdAt: new Date("2026-02-25"),
    },
  });
  await prisma.payment.createMany({
    data: [
      {
        invoiceNo: "INV-000001",
        subscriptionId: schoolSubscription.id,
        institutionId: school.id,
        amount: 20000,
        method: "BKASH",
        transactionRef: "BKX8H2K9LQ",
        collectedById: central.id,
        paidAt: new Date("2026-03-05"),
      },
      {
        invoiceNo: "INV-000002",
        subscriptionId: schoolSubscription.id,
        institutionId: school.id,
        amount: 15000,
        method: "NAGAD",
        transactionRef: "NGD7P3M8TR",
        collectedById: central.id,
        paidAt: new Date("2026-05-10"),
      },
    ],
  });

  // Academic selections for the school
  const allItems = await prisma.academicItem.findMany();
  const wantedNames = new Set([
    "Class 6", "Class 7", "Class 8", "Class 9", "Class 10",
    "Section A", "Section B", "Section C",
    "Science", "Commerce", "Arts & Humanities",
    "2026-27",
    "Bangla", "English", "Mathematics", "Physics", "Chemistry", "Biology", "Higher Mathematics", "ICT",
    "Humanities", "Business Studies",
    "Morning", "Day",
    "Room 101", "Room 102", "Room 201", "Science Lab",
  ]);
  await prisma.academicSelection.createMany({
    data: allItems
      .filter((i) => wantedNames.has(i.name))
      .map((i) => ({ institutionId: school.id, academicItemId: i.id })),
  });

  // ---- Sunrise Kindergarten (ACTIVE, partially paid) ----
  const kg = await prisma.institution.create({
    data: {
      name: "Sunrise Kindergarten",
      code: "KG-1002",
      type: "PRIMARY_AND_HIGH_SCHOOL",
      email: "kindergarten@demo.com",
      phone: "+880 1811-222333",
      address: "House 45, Uttara Sector 7, Dhaka",
      district: "Dhaka",
      subDistrict: "Dhaka Metropolitan",
      status: "ACTIVE",
      createdAt: new Date("2026-04-02"),
      users: {
        create: {
          name: "Nusrat Jahan",
          email: "kindergarten@demo.com",
          passwordHash: demoPassword2,
          role: "INSTITUTION_ADMIN",
        },
      },
    },
  });
  const kgPlan = createdPlans["Kindergarten Premium"];
  const kgRequest = await prisma.packageRequest.create({
    data: {
      institutionId: kg.id,
      packagePlanId: kgPlan.id,
      status: "APPROVED",
      createdAt: new Date("2026-05-20"),
      decidedAt: new Date("2026-05-25"),
    },
  });
  const kgSubscription = await prisma.subscription.create({
    data: {
      institutionId: kg.id,
      packagePlanId: kgPlan.id,
      requestId: kgRequest.id,
      startDate: new Date("2026-06-01"),
      endDate: new Date("2027-05-31"),
      totalAmount: 15000,
      status: "ACTIVE",
      createdAt: new Date("2026-05-25"),
    },
  });
  await prisma.payment.create({
    data: {
      invoiceNo: "INV-000003",
      subscriptionId: kgSubscription.id,
      institutionId: kg.id,
      amount: 7000,
      method: "BKASH",
      transactionRef: "BKX2R9T4WP",
      collectedById: central.id,
      paidAt: new Date("2026-06-05"),
    },
  });

  // ---- Prime College (PENDING, with pending package request) ----
  const college = await prisma.institution.create({
    data: {
      name: "Prime College",
      code: "CO-1003",
      type: "COLLEGE_AND_UNIVERSITY",
      email: "college@demo.com",
      phone: "+880 1911-444555",
      address: "College Road, Chattogram",
      district: "Chattogram",
      subDistrict: "Chattogram Sadar",
      status: "PENDING",
      createdAt: new Date("2026-08-10"),
      users: {
        create: {
          name: "Rafiq Islam",
          email: "college@demo.com",
          passwordHash: demoPassword2,
          role: "INSTITUTION_ADMIN",
        },
      },
    },
  });
  await prisma.packageRequest.create({
    data: {
      institutionId: college.id,
      packagePlanId: createdPlans["College Basic"].id,
      note: "Please approve us for the upcoming admission season.",
      status: "PENDING",
      createdAt: new Date("2026-08-15"),
    },
  });

  /* ================================================================
   *  Institution operations demo data (Demo High School)
   *  Fee heads → Students → Fee schedules → Collections,
   *  Admissions (pending + approved) → Messages
   * ================================================================ */

  const schoolAdminUser = await prisma.user.findUnique({
    where: { email: "school@demo.com" },
  });

  // ---- Fee heads ----
  const admissionHead = await prisma.feeHead.create({
    data: { institutionId: school.id, name: "Admission Fee", nameBn: "ভর্তি ফি", type: "ADMISSION", defaultAmount: 5000 },
  });
  const tuitionHead = await prisma.feeHead.create({
    data: { institutionId: school.id, name: "Monthly Tuition", nameBn: "মাসিক বেতন", type: "TUITION", defaultAmount: 1500 },
  });
  const examHead = await prisma.feeHead.create({
    data: { institutionId: school.id, name: "Exam Fee", nameBn: "পরীক্ষার ফি", type: "EXAM", defaultAmount: 800 },
  });

  // ---- Students (6) ----
  const classByName = new Map(allItems.filter((i) => i.category === "CLASS").map((i) => [i.name, i.id]));
  const sectionByName = new Map(allItems.filter((i) => i.category === "SECTION").map((i) => [i.name, i.id]));
  const shiftByName = new Map(allItems.filter((i) => i.category === "SHIFT").map((i) => [i.name, i.id]));

  const studentSeed = [
    { roll: "1001", name: "Arif Hasan", nameBn: "আরিফ হাসান", gender: "MALE", cls: "Class 9", sec: "Section A", shift: "Morning", guardian: "Kamal Hasan", phone: "+880 1711-111111" },
    { roll: "1002", name: "Nadia Islam", nameBn: "নাদিয়া ইসলাম", gender: "FEMALE", cls: "Class 9", sec: "Section A", shift: "Morning", guardian: "Rafiq Islam", phone: "+880 1711-222222" },
    { roll: "1003", name: "Tanvir Ahmed", nameBn: "তানভীর আহমেদ", gender: "MALE", cls: "Class 8", sec: "Section B", shift: "Day", guardian: "Jamal Ahmed", phone: "+880 1711-333333" },
    { roll: "1004", name: "Sadia Rahman", nameBn: "সাদিয়া রহমান", gender: "FEMALE", cls: "Class 8", sec: "Section B", shift: "Day", guardian: "Mahbub Rahman", phone: "+880 1711-444444" },
    { roll: "1005", name: "Rakib Hossain", nameBn: "রাকিব হোসেন", gender: "MALE", cls: "Class 7", sec: "Section A", shift: null, guardian: "Sohel Hossain", phone: "+880 1711-555555" },
    { roll: "1006", name: "Mim Akter", nameBn: "মিম আক্তার", gender: "FEMALE", cls: "Class 7", sec: "Section A", shift: "Evening", guardian: "Nasir Akter", phone: "+880 1711-666666" },
  ];

  const students: { id: number; roll: string; name: string; cls: string }[] = [];
  // identity data for the Student Identity page / ID-card printing demo
  const identityByRoll: Record<string, { reg: string; card: string; blood: string }> = {
    "1001": { reg: "DHA-9-2026-001", card: "DHS-IDC-1001", blood: "B+" },
    "1002": { reg: "DHA-9-2026-002", card: "DHS-IDC-1002", blood: "O+" },
    "1003": { reg: "DHA-9-2026-003", card: "DHS-IDC-1003", blood: "A+" },
    "1004": { reg: "DHA-9-2026-004", card: "DHS-IDC-1004", blood: "AB+" },
  };
  for (const s of studentSeed) {
    const ident = identityByRoll[s.roll];
    const created = await prisma.student.create({
      data: {
        institutionId: school.id,
        roll: s.roll,
        name: s.name,
        nameBn: s.nameBn,
        gender: s.gender,
        dob: new Date("2011-03-15"),
        guardianName: s.guardian,
        guardianPhone: s.phone,
        address: "Dhanmondi, Dhaka",
        classItemId: classByName.get(s.cls) ?? null,
        sectionItemId: sectionByName.get(s.sec) ?? null,
        shiftItemId: s.shift ? shiftByName.get(s.shift) ?? null : null,
        registrationNo: ident?.reg,
        cardNo: ident?.card,
        bloodGroup: ident?.blood,
        cardIssuedAt: ident ? new Date("2026-01-20") : null,
        cardValidTill: ident ? new Date("2026-12-31") : null,
        createdAt: new Date("2026-01-20"),
      },
    });
    students.push({ id: created.id, roll: created.roll, name: created.name, cls: s.cls });
  }

  // ---- Today's student attendance (5th absent, 6th on leave; later admissions stay unmarked) ----
  const attendanceByRoll: Record<string, string> = {
    "1001": "PRESENT",
    "1002": "PRESENT",
    "1003": "PRESENT",
    "1004": "PRESENT",
    "1005": "ABSENT",
    "1006": "LEAVE",
  };
  for (const s of students) {
    const status = attendanceByRoll[s.roll];
    if (!status) continue;
    await prisma.studentAttendance.create({
      data: {
        institutionId: school.id,
        studentId: s.id,
        date: new Date(new Date().toISOString().slice(0, 10)),
        status: status as never,
      },
    });
  }

  // ---- Today's subject-wise attendance (Mathematics + English) ----
  const attSubjectByName = new Map(allItems.filter((i) => i.category === "SUBJECT").map((i) => [i.name, i.id]));
  const subjectAttToday: { roll: string; subject: string; status: string }[] = [
    { roll: "1001", subject: "Mathematics", status: "PRESENT" },
    { roll: "1002", subject: "Mathematics", status: "PRESENT" },
    { roll: "1003", subject: "Mathematics", status: "PRESENT" },
    { roll: "1004", subject: "Mathematics", status: "PRESENT" },
    { roll: "1005", subject: "Mathematics", status: "ABSENT" },
    { roll: "1001", subject: "English", status: "PRESENT" },
    { roll: "1002", subject: "English", status: "PRESENT" },
    { roll: "1003", subject: "English", status: "LEAVE" },
  ];
  for (const row of subjectAttToday) {
    const student = students.find((s) => s.roll === row.roll);
    const subjectId = attSubjectByName.get(row.subject);
    if (!student || !subjectId) continue;
    await prisma.studentAttendance.create({
      data: {
        institutionId: school.id,
        studentId: student.id,
        date: new Date(new Date().toISOString().slice(0, 10)),
        status: row.status as never,
        subjectItemId: subjectId,
      },
    });
  }

  // ---- Today's activities (all students + selected students) ----
  const actAll = await prisma.studentActivity.create({
    data: {
      institutionId: school.id,
      title: "Morning Assembly & National Anthem",
      description: "Daily morning assembly with the national anthem and a short speech by the head teacher.",
      activityDate: new Date(new Date().toISOString().slice(0, 10)),
      isForAll: true,
      createdById: schoolAdminUser?.id ?? central.id,
    },
  });
  void actAll;
  const actSelectedRolls = ["1001", "1003"];
  const actSelected = await prisma.studentActivity.create({
    data: {
      institutionId: school.id,
      title: "Science Club Project Preparation",
      description: "Preparing the Science Fair 2026 project — bring materials and notes.",
      activityDate: new Date(new Date().toISOString().slice(0, 10)),
      isForAll: false,
      createdById: schoolAdminUser?.id ?? central.id,
      recipients: {
        create: students
          .filter((s) => actSelectedRolls.includes(s.roll))
          .map((s) => ({ studentId: s.id })),
      },
    },
  });
  void actSelected;

  // ---- Fee schedules + collections ----
  let invoiceSeq = 0;
  async function collect(studentId: number, scheduleId: number | null, amount: number, method: string, when: Date) {
    invoiceSeq += 1;
    await prisma.feeCollection.create({
      data: {
        invoiceNo: `FEE-${String(invoiceSeq).padStart(6, "0")}`,
        institutionId: school.id,
        studentId,
        feeScheduleId: scheduleId,
        amount,
        method: method as never,
        collectedById: schoolAdminUser?.id ?? central.id,
        paidAt: when,
      },
    });
  }

  const months = [
    { m: "2026-03", date: new Date("2026-03-10") },
    { m: "2026-04", date: new Date("2026-04-10") },
    { m: "2026-05", date: new Date("2026-05-10") },
    { m: "2026-06", date: new Date("2026-06-10") },
    { m: "2026-07", date: new Date("2026-07-10") },
    { m: "2026-08", date: new Date("2026-08-10") },
  ];

  for (const [idx, s] of students.entries()) {
    // Admission fee — paid by first 4 students
    const admSchedule = await prisma.feeSchedule.create({
      data: {
        institutionId: school.id, feeHeadId: admissionHead.id, studentId: s.id,
        classItemId: classByName.get(s.cls) ?? null,
        title: `Admission 2026 — ${s.name}`, amount: 5000,
        dueDate: new Date("2026-02-05"),
      },
    });
    if (idx < 4) await collect(s.id, admSchedule.id, 5000, "BKASH", new Date("2026-02-08"));

    // Monthly tuition — earlier months paid by all, recent months partially
    for (const [mi, month] of months.entries()) {
      const schedule = await prisma.feeSchedule.create({
        data: {
          institutionId: school.id, feeHeadId: tuitionHead.id, studentId: s.id,
          title: `Tuition ${month.m} — ${s.name}`, amount: 1500,
          dueDate: month.date, month: month.m,
        },
      });
      if (mi < 4) {
        await collect(s.id, schedule.id, 1500, mi % 2 === 0 ? "CASH" : "BKASH", new Date(month.date.getTime() + 3 * 86400000));
      } else if (mi === 4 && idx < 5) {
        await collect(s.id, schedule.id, 1500, "NAGAD", new Date(month.date.getTime() + 2 * 86400000));
      }
    }

    // Exam fee — half term, paid by first 3
    const examSchedule = await prisma.feeSchedule.create({
      data: {
        institutionId: school.id, feeHeadId: examHead.id, studentId: s.id,
        title: `Half-Yearly Exam — ${s.name}`, amount: 800,
        dueDate: new Date("2026-06-01"),
      },
    });
    if (idx < 3) await collect(s.id, examSchedule.id, 800, "CASH", new Date("2026-06-03"));
  }

  // ---- Pending admissions (with applicant messages) ----
  const adm1 = await prisma.admission.create({
    data: {
      institutionId: school.id,
      studentName: "Rifat Chowdhury",
      studentNameBn: "রিফাত চৌধুরী",
      gender: "MALE",
      dob: new Date("2013-05-20"),
      guardianName: "Ashraf Chowdhury",
      guardianPhone: "+880 1811-777888",
      email: "ashraf@example.com",
      address: "Mohammadpur, Dhaka",
      classItemId: classByName.get("Class 6") ?? null,
      note: "We want to admit our son in Class 6. When does the admission test take place?",
      createdAt: new Date("2026-08-18"),
    },
  });
  await prisma.message.create({
    data: {
      institutionId: school.id, admissionId: adm1.id,
      sender: "APPLICANT", senderName: "Ashraf Chowdhury",
      body: adm1.note!, createdAt: new Date("2026-08-18"),
    },
  });
  await prisma.message.create({
    data: {
      institutionId: school.id, admissionId: adm1.id,
      sender: "INSTITUTION", senderName: "School Admin",
      body: "Welcome! The admission test is on 5 September at 10 AM. Please bring 2 copies of the birth certificate.",
      createdAt: new Date("2026-08-19"),
    },
  });

  const adm2 = await prisma.admission.create({
    data: {
      institutionId: school.id,
      studentName: "Farzana Haque",
      studentNameBn: "ফারজানা হক",
      gender: "FEMALE",
      dob: new Date("2011-11-02"),
      guardianName: "Mizanur Haque",
      guardianPhone: "+880 1911-999000",
      address: "Uttara, Dhaka",
      classItemId: classByName.get("Class 9") ?? null,
      note: "Interested in Class 9 with Science group. Please share the fee structure.",
      createdAt: new Date("2026-08-22"),
    },
  });
  await prisma.message.create({
    data: {
      institutionId: school.id, admissionId: adm2.id,
      sender: "APPLICANT", senderName: "Mizanur Haque",
      body: adm2.note!, createdAt: new Date("2026-08-22"),
    },
  });

  // A message thread with an enrolled student's guardian
  await prisma.message.create({
    data: {
      institutionId: school.id, studentId: students[0].id,
      sender: "INSTITUTION", senderName: "School Admin",
      body: "Dear guardian, the half-yearly exam routine has been published. Please check the notice board.",
      createdAt: new Date("2026-08-20"),
    },
  });
  await prisma.message.create({
    data: {
      institutionId: school.id, studentId: students[1].id,
      sender: "INSTITUTION", senderName: "School Admin",
      body: "August tuition is due on the 10th. Please pay via bKash or at the office.",
      createdAt: new Date("2026-08-24"),
    },
  });

  /* ================================================================
   *  Institution-owned academic items (class selection managed
   *  under the institution's own credential)
   * ================================================================ */
  const ownClass = await prisma.academicItem.create({
    data: {
      category: "CLASS",
      name: "Class 9 (English Version)",
      nameBn: "নবম শ্রেণি (ইংরেজি সংস্করণ)",
      institutionId: school.id,
    },
  });
  const ownSubject = await prisma.academicItem.create({
    data: {
      category: "SUBJECT",
      name: "Agriculture Studies",
      nameBn: "কৃষিশিক্ষা",
      institutionId: school.id,
    },
  });
  await prisma.academicSelection.createMany({
    data: [
      { institutionId: school.id, academicItemId: ownClass.id },
      { institutionId: school.id, academicItemId: ownSubject.id },
    ],
  });

  /* ================================================================
   *  Human Resource demo data
   * ================================================================ */
  const staffSeed = [
    { code: "EMP-001", name: "Anisur Rahman", nameBn: "আনিসুর রহমান", gender: "MALE", phone: "+880 1711-300001", designation: "PRINCIPAL", department: "ACADEMIC", salary: 45000, join: "2018-01-10" },
    { code: "EMP-002", name: "Farhana Yasmin", nameBn: "ফারহানা ইয়াসমিন", gender: "FEMALE", phone: "+880 1711-300002", designation: "TEACHER", department: "SCIENCE", salary: 28000, join: "2019-03-05" },
    { code: "EMP-003", name: "Mahmudul Hasan", nameBn: "মাহমুদুল হাসান", gender: "MALE", phone: "+880 1711-300003", designation: "TEACHER", department: "ARTS", salary: 26000, join: "2020-07-15" },
    { code: "EMP-004", name: "Rashedul Islam", nameBn: "রাশেদুল ইসলাম", gender: "MALE", phone: "+880 1711-300004", designation: "LIBRARIAN", department: "LIBRARY", salary: 18000, join: "2021-02-01" },
    { code: "EMP-005", name: "Shirin Sultana", nameBn: "শিরিন সুলতানা", gender: "FEMALE", phone: "+880 1711-300005", designation: "ACCOUNTANT", department: "ACCOUNTS", salary: 20000, join: "2022-08-20" },
  ];

  const staff: { id: number; code: string; name: string }[] = [];
  for (const s of staffSeed) {
    const created = await prisma.staff.create({
      data: {
        institutionId: school.id,
        employeeCode: s.code,
        name: s.name,
        nameBn: s.nameBn,
        gender: s.gender,
        phone: s.phone,
        email: `${s.code.toLowerCase()}@demohigh.edu`,
        designation: s.designation as never,
        department: s.department as never,
        joinDate: new Date(s.join),
        monthlySalary: s.salary,
        status: "ACTIVE",
      },
    });
    staff.push({ id: created.id, code: created.employeeCode, name: created.name });
  }

  // Today's attendance (1 on leave)
  const today = new Date(new Date().toISOString().slice(0, 10));
  const attendanceToday: Record<string, string> = {
    "EMP-001": "PRESENT", "EMP-002": "PRESENT", "EMP-003": "LEAVE",
    "EMP-004": "ABSENT", "EMP-005": "PRESENT",
  };
  for (const s of staff) {
    await prisma.staffAttendance.create({
      data: {
        institutionId: school.id,
        staffId: s.id,
        date: today,
        status: attendanceToday[s.code] as never,
      },
    });
  }

  // Leave requests (1 pending, 1 approved)
  const nextWeek = new Date(today);
  nextWeek.setDate(nextWeek.getDate() + 7);
  const leaveEnd = new Date(nextWeek);
  leaveEnd.setDate(leaveEnd.getDate() + 2);
  await prisma.leaveRequest.create({
    data: {
      institutionId: school.id,
      staffId: staff[1].id,
      fromDate: nextWeek,
      toDate: leaveEnd,
      days: 3,
      reason: "Family wedding in Chattogram — requesting 3 days of casual leave.",
      status: "PENDING",
      createdAt: new Date(Date.now() - 2 * 86400000),
    },
  });
  const lastMonth = new Date(today);
  lastMonth.setMonth(lastMonth.getMonth() - 1);
  const lmFrom = new Date(lastMonth);
  lmFrom.setDate(12);
  const lmTo = new Date(lmFrom);
  lmTo.setDate(lmTo.getDate() + 1);
  await prisma.leaveRequest.create({
    data: {
      institutionId: school.id,
      staffId: staff[2].id,
      fromDate: lmFrom,
      toDate: lmTo,
      days: 2,
      reason: "Medical checkup.",
      status: "APPROVED",
      createdAt: new Date(lmFrom.getTime() - 5 * 86400000),
      decidedAt: new Date(lmFrom.getTime() - 3 * 86400000),
    },
  });

  // Salaries — last month fully paid, this month partially
  const monthStr = (d: Date) => d.toISOString().slice(0, 7);
  const prevMonth = new Date(today);
  prevMonth.setMonth(prevMonth.getMonth() - 1);
  for (const s of staff) {
    await prisma.salaryPayment.create({
      data: {
        institutionId: school.id,
        staffId: s.id,
        month: monthStr(prevMonth),
        amount: staffSeed.find((x) => x.code === s.code)!.salary,
        method: "BKASH",
        paidById: schoolAdminUser?.id ?? central.id,
        paidAt: new Date(prevMonth.getFullYear(), prevMonth.getMonth(), 5),
      },
    });
  }
  for (const s of staff.slice(0, 2)) {
    await prisma.salaryPayment.create({
      data: {
        institutionId: school.id,
        staffId: s.id,
        month: monthStr(today),
        amount: staffSeed.find((x) => x.code === s.code)!.salary,
        method: "BKASH",
        paidById: schoolAdminUser?.id ?? central.id,
        paidAt: new Date(today.getFullYear(), today.getMonth(), 5),
      },
    });
  }

  /* ================================================================
   *  Accounts management demo data (chart of accounts + vouchers)
   * ================================================================ */
  const accHeads = [
    { name: "Book & Stationery Sale", nameBn: "বই ও স্টেশনারি বিক্রয়", type: "INCOME" as const },
    { name: "Examination Fee", nameBn: "পরীক্ষা ফি", type: "INCOME" as const },
    { name: "Donation & Gift", nameBn: "অনুদান ও উপহার", type: "INCOME" as const },
    { name: "Salaries & Wages", nameBn: "বেতন ও মজুরি", type: "EXPENSE" as const },
    { name: "Utilities", nameBn: "ইউটিলিটি (বিদ্যুৎ / পানি / ইন্টারনেট)", type: "EXPENSE" as const },
    { name: "Building Maintenance", nameBn: "ভবন রক্ষণাবেক্ষণ", type: "EXPENSE" as const },
    { name: "Transport Fuel", nameBn: "পরিবহন জ্বালানি", type: "EXPENSE" as const },
  ];
  const accHeadIds: Record<string, number> = {};
  for (const h of accHeads) {
    const created = await prisma.accountHead.create({
      data: { institutionId: school.id, name: h.name, nameBn: h.nameBn, type: h.type },
    });
    accHeadIds[h.name] = created.id;
  }

  const accNow = new Date();
  let incSeq = 0;
  let expSeq = 0;
  async function addVoucher(
    head: string,
    monthsAgo: number,
    day: number,
    amount: number,
    method: string,
    party: string | null,
  ) {
    const type = accHeads.find((h) => h.name === head)!.type;
    const seq = type === "INCOME" ? ++incSeq : ++expSeq;
    await prisma.accountEntry.create({
      data: {
        institutionId: school.id,
        headId: accHeadIds[head],
        type,
        voucherNo: `${type === "INCOME" ? "INC" : "EXP"}-${String(seq).padStart(6, "0")}`,
        amount,
        date: new Date(accNow.getFullYear(), accNow.getMonth() - monthsAgo, day),
        method: method as never,
        party,
        createdById: schoolAdminUser?.id ?? central.id,
      },
    });
  }

  // recurring income / expense across the last 12 months (deterministic amounts)
  for (let m = 11; m >= 0; m--) {
    await addVoucher("Salaries & Wages", m, 5, 148000 + (11 - m) * 2000, "BANK_TRANSFER", "Staff payroll");
    await addVoucher("Utilities", m, 12, 14500 + ((11 - m) % 4) * 900, "BKASH", "DESCO / WASA / ISP");
    if (m % 2 === 0) await addVoucher("Transport Fuel", m, 18, 8200, "CASH", "Petrol pump");
    if (m % 3 === 0) await addVoucher("Building Maintenance", m, 22, 12000, "CASH", "Contractor");
    if (m % 2 === 1) await addVoucher("Book & Stationery Sale", m, 20, 130000 + m * 3500, "CASH", "Counter sales");
    if (m % 3 === 1) await addVoucher("Examination Fee", m, 15, 180000, "BKASH", null);
    if (m % 4 === 2) await addVoucher("Donation & Gift", m, 9, 200000, "BANK_TRANSFER", "Well-wishers");
  }

  /* ================================================================
   *  Exams & exam schedule demo data (class + shift wise)
   * ================================================================ */
  const examRoomByName = new Map(allItems.filter((i) => i.category === "ROOM").map((i) => [i.name, i.id]));
  const examToday = new Date(new Date().toISOString().slice(0, 10));
  const dayOffset = (n: number) => new Date(Date.UTC(examToday.getUTCFullYear(), examToday.getUTCMonth(), examToday.getUTCDate() + n));
  const examSeed: {
    name: string; nameBn: string; cls: string; shift: string; start: number; end: number;
    status: "UPCOMING" | "RUNNING" | "FINISHED";
    papers: { subject: string; day: number; start: string; end: string; room: string; marks: number }[];
  }[] = [
    {
      name: "First Terminal Examination", nameBn: "প্রথম সাময়িক পরীক্ষা", cls: "Class 9", shift: "Morning",
      start: 0, end: 6, status: "RUNNING",
      papers: [
        { subject: "Mathematics", day: 0, start: "10:00", end: "13:00", room: "Room 101", marks: 100 },
        { subject: "English", day: 2, start: "10:00", end: "13:00", room: "Room 101", marks: 100 },
        { subject: "Science", day: 4, start: "14:00", end: "16:30", room: "Room 102", marks: 100 },
        { subject: "ICT", day: 6, start: "10:00", end: "12:00", room: "Room 103", marks: 50 },
      ],
    },
    {
      name: "Final Examination", nameBn: "বার্ষিক পরীক্ষা", cls: "Class 8", shift: "Day",
      start: 7, end: 13, status: "UPCOMING",
      papers: [
        { subject: "Bangla", day: 7, start: "09:00", end: "12:00", room: "Room 201", marks: 100 },
        { subject: "Mathematics", day: 9, start: "09:00", end: "12:00", room: "Room 201", marks: 100 },
        { subject: "Religion & Moral Education", day: 12, start: "14:00", end: "16:00", room: "Room 202", marks: 100 },
      ],
    },
    {
      name: "Annual Test", nameBn: "বার্ষিক পরীক্ষা", cls: "Class 7", shift: "Evening",
      start: 14, end: 18, status: "UPCOMING",
      papers: [
        { subject: "English", day: 14, start: "16:00", end: "18:00", room: "Room 103", marks: 100 },
        { subject: "Science", day: 16, start: "16:00", end: "18:30", room: "Room 103", marks: 100 },
        { subject: "Social Science", day: 18, start: "16:00", end: "18:00", room: "Room 102", marks: 100 },
      ],
    },
  ];

  for (const ex of examSeed) {
    const createdExam = await prisma.exam.create({
      data: {
        institutionId: school.id,
        name: ex.name,
        nameBn: ex.nameBn,
        classItemId: classByName.get(ex.cls) ?? null,
        shiftItemId: shiftByName.get(ex.shift) ?? null,
        startDate: dayOffset(ex.start),
        endDate: dayOffset(ex.end),
        status: ex.status,
      },
    });
    for (const p of ex.papers) {
      await prisma.examSchedule.create({
        data: {
          institutionId: school.id,
          examId: createdExam.id,
          subjectItemId: attSubjectByName.get(p.subject) ?? null,
          date: dayOffset(p.day),
          startTime: p.start,
          endTime: p.end,
          roomItemId: examRoomByName.get(p.room) ?? null,
          fullMarks: p.marks,
        },
      });
    }
  }

  /* ================================================================
   *  Communication panel demo data (simulated sends)
   * ================================================================ */
  const class9 = classByName.get("Class 9")!;

  const feeBroadcast = await prisma.broadcast.create({
    data: {
      institutionId: school.id,
      channels: ["SMS", "WHATSAPP"],
      audience: "BY_CLASS",
      classItemId: class9,
      body: "Dear Guardian, September tuition fee is due on the 10th. Please pay via bKash 01711-000111 or at the office.",
      recipientCount: 2,
      status: "SENT",
      sentById: schoolAdminUser?.id ?? central.id,
      createdAt: new Date(Date.now() - 3 * 86400000),
    },
  });
  await prisma.broadcastRecipient.createMany({
    data: students
      .filter((_, idx) => idx < 2)
      .map((s) => ({
        institutionId: school.id,
        broadcastId: feeBroadcast.id,
        name: studentSeed.find((x) => x.roll === s.roll)!.guardian,
        phone: studentSeed.find((x) => x.roll === s.roll)!.phone,
        channels: ["SMS", "WHATSAPP"],
      })),
  });

  const holidayBroadcast = await prisma.broadcast.create({
    data: {
      institutionId: school.id,
      channels: ["EMAIL"],
      audience: "ALL_STUDENTS",
      subject: "School closed on 15 September",
      body: "Dear Guardian, the institution will remain closed on 15 September due to a government holiday. Classes resume the following day.",
      recipientCount: students.length,
      status: "SENT",
      sentById: schoolAdminUser?.id ?? central.id,
      createdAt: new Date(Date.now() - 6 * 86400000),
    },
  });
  await prisma.broadcastRecipient.createMany({
    data: students.map((s) => ({
      institutionId: school.id,
      broadcastId: holidayBroadcast.id,
      name: studentSeed.find((x) => x.roll === s.roll)!.guardian,
      phone: studentSeed.find((x) => x.roll === s.roll)!.phone,
      channels: ["EMAIL"],
    })),
  });

  const staffBroadcast = await prisma.broadcast.create({
    data: {
      institutionId: school.id,
      channels: ["SMS"],
      audience: "ALL_STAFF",
      body: "Monthly staff meeting on Sunday at 11 AM in the conference room. Attendance is mandatory.",
      recipientCount: staff.length,
      status: "SENT",
      sentById: schoolAdminUser?.id ?? central.id,
      createdAt: new Date(Date.now() - 1 * 86400000),
    },
  });
  await prisma.broadcastRecipient.createMany({
    data: staff.map((s) => ({
      institutionId: school.id,
      broadcastId: staffBroadcast.id,
      name: s.name,
      phone: staffSeed.find((x) => x.code === s.code)!.phone,
      email: `${s.code.toLowerCase()}@demohigh.edu`,
      channels: ["SMS"],
    })),
  });

  /* ================================================================
   *  Library demo data
   * ================================================================ */
  const bookSeed = [
    { title: "NCTB Bangla — Class 9", titleBn: "এনসিটিবি বাংলা — নবম শ্রেণি", author: "NCTB", publisher: "National Curriculum", category: "TEXTBOOK", shelf: "A-1", copies: 10, price: 180 },
    { title: "English Grammar & Composition", titleBn: "ইংরেজি ব্যাকরণ ও রচনা", author: "P. K. Dey", publisher: "Dey's Publishing", category: "TEXTBOOK", shelf: "A-2", copies: 5, price: 320 },
    { title: "Physics for Classes 9-10", titleBn: "পদার্থবিজ্ঞান — নবম-দশম", author: "Ishak Nirob", publisher: "Panjeree", category: "SCIENCE", shelf: "B-1", copies: 8, price: 380 },
    { title: "Padma Nadir Majhi", titleBn: "পদ্মা নদীর মাঝি", author: "Manik Bandopadhyay", publisher: "Bangla Academy", category: "LITERATURE", shelf: "C-3", copies: 3, price: 250 },
    { title: "World History Atlas", titleBn: "বিশ্ব ইতিহাস অ্যাটলাস", author: "Oxford", publisher: "OUP", category: "HISTORY", shelf: "D-1", copies: 2, price: 1200 },
    { title: "Children's Rhymes & Poems", titleBn: "শিশুদের ছড়া ও কবিতা", author: "Sukanta Chatterjee", publisher: "Shishu Prokash", category: "CHILDREN", shelf: "E-2", copies: 4, price: 150 },
  ];

  const books: { id: number; title: string }[] = [];
  for (const b of bookSeed) {
    const created = await prisma.book.create({
      data: {
        institutionId: school.id,
        title: b.title,
        titleBn: b.titleBn,
        author: b.author,
        publisher: b.publisher,
        category: b.category,
        shelf: b.shelf,
        totalCopies: b.copies,
        availableCopies: b.copies,
        price: b.price,
      },
    });
    books.push({ id: created.id, title: created.title });
  }

  // Issues: 1 overdue (student), 1 active (student), 1 returned with fine (staff)
  const overdueDue = new Date(today);
  overdueDue.setDate(overdueDue.getDate() - 5); // 5 days overdue
  const overdueIssued = new Date(overdueDue);
  overdueIssued.setDate(overdueIssued.getDate() - 14);
  await prisma.bookIssue.create({
    data: {
      institutionId: school.id,
      bookId: books[2].id,
      memberType: "STUDENT",
      studentId: students[0].id,
      issueDate: overdueIssued,
      dueDate: overdueDue,
    },
  });
  await prisma.book.update({ where: { id: books[2].id }, data: { availableCopies: { decrement: 1 } } });

  const activeDue = new Date(today);
  activeDue.setDate(activeDue.getDate() + 9);
  const activeIssued = new Date(today);
  activeIssued.setDate(activeIssued.getDate() - 5);
  await prisma.bookIssue.create({
    data: {
      institutionId: school.id,
      bookId: books[3].id,
      memberType: "STUDENT",
      studentId: students[2].id,
      issueDate: activeIssued,
      dueDate: activeDue,
    },
  });
  await prisma.book.update({ where: { id: books[3].id }, data: { availableCopies: { decrement: 1 } } });

  const retIssued = new Date(today);
  retIssued.setDate(retIssued.getDate() - 20);
  const retDue = new Date(retIssued);
  retDue.setDate(retDue.getDate() + 14);
  const retReturn = new Date(retDue);
  retReturn.setDate(retReturn.getDate() + 2); // 2 days late → fine 20
  await prisma.bookIssue.create({
    data: {
      institutionId: school.id,
      bookId: books[4].id,
      memberType: "STAFF",
      staffId: staff[3].id,
      issueDate: retIssued,
      dueDate: retDue,
      returnDate: retReturn,
      fine: 20,
      status: "RETURNED",
    },
  });

  /* ================================================================
   *  Inventory demo data
   * ================================================================ */
  const inventorySeed = [
    { name: "Student Chair", nameBn: "শিক্ষার্থী চেয়ার", category: "FURNITURE", unit: "PCS", quantity: 120, minQuantity: 20, unitPrice: 1200, location: "Store Room" },
    { name: "Teacher Desk", nameBn: "শিক্ষক ডেস্ক", category: "FURNITURE", unit: "PCS", quantity: 15, minQuantity: 2, unitPrice: 4500, location: "Store Room" },
    { name: "Whiteboard Marker", nameBn: "হোয়াইটবোর্ড মার্কার", category: "STATIONERY", unit: "BOX", quantity: 8, minQuantity: 10, unitPrice: 350, location: "Office" },
    { name: "A4 Paper", nameBn: "এ৪ কাগজ", category: "STATIONERY", unit: "REAM", quantity: 25, minQuantity: 10, unitPrice: 480, location: "Office" },
    { name: "Lab Microscope", nameBn: "ল্যাব মাইক্রোস্কোপ", category: "LAB", unit: "PCS", quantity: 6, minQuantity: 2, unitPrice: 25000, location: "Science Lab" },
    { name: "Desktop Computer", nameBn: "ডেস্কটপ কম্পিউটার", category: "IT", unit: "PCS", quantity: 12, minQuantity: 3, unitPrice: 45000, location: "Computer Lab" },
  ];

  for (const i of inventorySeed) {
    const created = await prisma.inventoryItem.create({
      data: {
        institutionId: school.id,
        name: i.name,
        nameBn: i.nameBn,
        category: i.category as never,
        unit: i.unit as never,
        quantity: i.quantity,
        minQuantity: i.minQuantity,
        unitPrice: i.unitPrice,
        location: i.location,
      },
    });
    await prisma.stockMovement.create({
      data: {
        institutionId: school.id,
        itemId: created.id,
        type: "IN",
        quantity: i.quantity,
        note: "Initial stock",
        createdById: schoolAdminUser?.id ?? central.id,
        createdAt: new Date(Date.now() - 30 * 86400000),
      },
    });
  }

  // A few movements
  const chairItem = await prisma.inventoryItem.findFirst({ where: { institutionId: school.id, name: "Student Chair" } });
  const markerItem = await prisma.inventoryItem.findFirst({ where: { institutionId: school.id, name: "Whiteboard Marker" } });
  if (chairItem && markerItem) {
    await prisma.stockMovement.create({
      data: {
        institutionId: school.id, itemId: chairItem.id, type: "OUT", quantity: 20,
        party: "Room 101 — Class 7", note: "New classroom setup",
        createdById: schoolAdminUser?.id ?? central.id,
        createdAt: new Date(Date.now() - 10 * 86400000),
      },
    });
    await prisma.stockMovement.create({
      data: {
        institutionId: school.id, itemId: markerItem.id, type: "OUT", quantity: 3,
        party: "Teachers' Room", note: "Monthly supply",
        createdById: schoolAdminUser?.id ?? central.id,
        createdAt: new Date(Date.now() - 4 * 86400000),
      },
    });
  }

  console.log("  ✔ Institution ops: 6 students, 3 fee heads, schedules + collections, 2 admissions, messages");
  console.log("  ✔ HR: 5 staff, attendance, leaves, salaries");
  console.log("  ✔ Communication: 3 broadcasts (SMS/Email/WhatsApp)");
  console.log("  ✔ Library: 6 books, 3 issues (1 overdue, 1 returned w/ fine)");
  console.log("  ✔ Inventory: 6 items with stock movements");

  /* ================================================================
   *  Communication integration settings + SMS purchase
   * ================================================================ */
  await prisma.commSetting.create({
    data: {
      institutionId: school.id,
      smsApiUrl: "https://api.smsprovider.com.bd/v1/send",
      smsApiKey: "sk_live_demo_9f3k2x",
      smsSenderId: "DEMO HIGH",
      smsType: "NON_MASKING",
      smsBalance: 120,
      smtpHost: "smtp.mailprovider.com",
      smtpPort: 587,
      smtpUser: "notifications@demohigh.edu",
      smtpFromName: "Demo High School",
      smtpFromEmail: "notifications@demohigh.edu",
      smtpSecure: true,
      waApiUrl: "https://graph.facebook.com/v20.0",
      waPhoneId: "103948572",
    },
  });
  await prisma.smsPurchase.create({
    data: {
      institutionId: school.id,
      quantity: 500,
      price: 600,
      method: "BKASH",
      note: "Top-up for admission season",
      createdAt: new Date(Date.now() - 45 * 86400000),
    },
  });

  /* ================================================================
   *  Transport demo data
   * ================================================================ */
  const bus1 = await prisma.transportVehicle.create({
    data: {
      institutionId: school.id,
      name: "Bus-1",
      registrationNo: "DHA-11-2345",
      type: "BUS",
      capacity: 40,
      driverName: "Habib Mia",
      driverPhone: "+880 1711-400001",
    },
  });
  const micro1 = await prisma.transportVehicle.create({
    data: {
      institutionId: school.id,
      name: "Micro-1",
      registrationNo: "DHA-14-8899",
      type: "MICROBUS",
      capacity: 14,
      driverName: "Selim Khan",
      driverPhone: "+880 1711-400002",
    },
  });

  const route1 = await prisma.transportRoute.create({
    data: {
      institutionId: school.id,
      name: "Dhanmondi Route",
      nameBn: "ধানমন্ডি রুট",
      vehicleId: bus1.id,
      baseFare: 1500,
      stops: {
        create: [
          { institutionId: school.id, name: "Jigatola", nameBn: "জিগাতলা", extraFare: 0, sortOrder: 0 },
          { institutionId: school.id, name: "Kalabagan", nameBn: "কালাবাগান", extraFare: 100, sortOrder: 1 },
          { institutionId: school.id, name: "Green Road", nameBn: "গ্রিন রোড", extraFare: 150, sortOrder: 2 },
        ],
      },
    },
    include: { stops: true },
  });
  const route2 = await prisma.transportRoute.create({
    data: {
      institutionId: school.id,
      name: "Uttara Route",
      nameBn: "উত্তরা রুট",
      vehicleId: micro1.id,
      baseFare: 2000,
      stops: {
        create: [
          { institutionId: school.id, name: "Azampur", nameBn: "আজমপুর", extraFare: 0, sortOrder: 0 },
          { institutionId: school.id, name: "Sector 4", nameBn: "সেক্টর ৪", extraFare: 100, sortOrder: 1 },
          { institutionId: school.id, name: "Sector 7", nameBn: "সেক্টর ৭", extraFare: 200, sortOrder: 2 },
        ],
      },
    },
    include: { stops: true },
  });

  const stopByName = (route: { stops: { id: number; name: string }[] }, name: string) =>
    route.stops.find((s) => s.name === name)!.id;

  const member1 = await prisma.transportMember.create({
    data: {
      institutionId: school.id,
      studentId: students[0].id,
      routeId: route1.id,
      stopId: stopByName(route1, "Kalabagan"),
      monthlyFare: 1600,
    },
  });
  const member2 = await prisma.transportMember.create({
    data: {
      institutionId: school.id,
      studentId: students[2].id,
      routeId: route1.id,
      monthlyFare: 1500,
    },
  });
  const member3 = await prisma.transportMember.create({
    data: {
      institutionId: school.id,
      studentId: students[4].id,
      routeId: route2.id,
      stopId: stopByName(route2, "Sector 7"),
      monthlyFare: 2200,
    },
  });

  // Fares — last month all paid, this month partially
  for (const m of [member1, member2, member3]) {
    await prisma.transportPayment.create({
      data: {
        institutionId: school.id,
        memberId: m.id,
        month: monthStr(prevMonth),
        amount: m.monthlyFare,
        method: "BKASH",
        paidById: schoolAdminUser?.id ?? central.id,
        paidAt: new Date(prevMonth.getFullYear(), prevMonth.getMonth(), 7),
      },
    });
  }
  await prisma.transportPayment.create({
    data: {
      institutionId: school.id,
      memberId: member1.id,
      month: monthStr(today),
      amount: 1600,
      method: "BKASH",
      paidById: schoolAdminUser?.id ?? central.id,
      paidAt: new Date(today.getFullYear(), today.getMonth(), 7),
    },
  });

  console.log("  ✔ Communication: gateway/SMTP settings + SMS purchase (balance 120)");
  console.log("  ✔ Transport: 2 vehicles, 2 routes with stops, 3 members, fares");

  /* ================================================================
   *  Hostel demo data
   * ================================================================ */
  const boysHostel = await prisma.hostel.create({
    data: {
      institutionId: school.id,
      name: "Sher-e-Bangla Boys Hostel",
      nameBn: "শেরেবাংলা ছেলেদের হোস্টেল",
      type: "BOYS",
      wardenName: "Abdul Karim",
      wardenPhone: "+880 1711-500001",
      monthlyFee: 2500,
    },
  });
  const girlsHostel = await prisma.hostel.create({
    data: {
      institutionId: school.id,
      name: "Begum Rokeya Girls Hostel",
      nameBn: "বেগম রোকেয়া মেয়েদের হোস্টেল",
      type: "GIRLS",
      wardenName: "Rahima Begum",
      wardenPhone: "+880 1711-500002",
      monthlyFee: 2800,
    },
  });

  const boys101 = await prisma.hostelRoom.create({
    data: { institutionId: school.id, hostelId: boysHostel.id, roomNo: "101", floor: 1, capacity: 2, roomType: "DOUBLE", monthlyFee: 2800 },
  });
  await prisma.hostelRoom.create({
    data: { institutionId: school.id, hostelId: boysHostel.id, roomNo: "102", floor: 1, capacity: 4, roomType: "DORMITORY", monthlyFee: 2200 },
  });
  const girls201 = await prisma.hostelRoom.create({
    data: { institutionId: school.id, hostelId: girlsHostel.id, roomNo: "201", floor: 2, capacity: 2, roomType: "DOUBLE", monthlyFee: 3000 },
  });

  const hostellers = [
    { studentIdx: 0, hostelId: boysHostel.id, roomId: boys101.id, bedNo: "A-1", fee: 2800 },
    { studentIdx: 2, hostelId: boysHostel.id, roomId: boys101.id, bedNo: "A-2", fee: 2800 },
    { studentIdx: 1, hostelId: girlsHostel.id, roomId: girls201.id, bedNo: "B-1", fee: 3000 },
  ];
  const hostellerIds: number[] = [];
  for (const h of hostellers) {
    const created = await prisma.hostelMember.create({
      data: {
        institutionId: school.id,
        studentId: students[h.studentIdx].id,
        hostelId: h.hostelId,
        roomId: h.roomId,
        bedNo: h.bedNo,
        monthlyFee: h.fee,
        joinDate: new Date(Date.now() - 30 * 86400000),
      },
    });
    hostellerIds.push(created.id);
  }

  // Attendance — yesterday all present, today one on leave
  for (const d of [1, 0]) {
    for (const [i, memberId] of hostellerIds.entries()) {
      await prisma.hostelAttendance.create({
        data: {
          institutionId: school.id,
          memberId,
          date: new Date(Date.now() - d * 86400000),
          status: d === 0 && i === 2 ? "LEAVE" : "PRESENT",
        },
      });
    }
  }

  console.log("  ✔ Hostel: 2 hostels, 3 rooms, 3 residents, attendance");

  /* ================================================================
   *  Notice / Complaint / Event / Committee demo data
   * ================================================================ */
  const d = (offsetDays: number) => new Date(Date.now() + offsetDays * 86400000);

  await prisma.notice.createMany({
    data: [
      {
        institutionId: school.id,
        title: "Annual Sports Day registration open",
        titleBn: "বার্ষিক ক্রীড়া দিবসের নিবন্ধন চালু",
        body: "Students willing to participate in the Annual Sports Day (December) must register with their class teacher by the end of this month. Events: 100m sprint, relay, high jump, chess.",
        audience: "STUDENTS",
        publishDate: d(-2),
        expiryDate: d(20),
        isPinned: true,
      },
      {
        institutionId: school.id,
        title: "Parent-teacher meeting — Class 9",
        body: "A parent-teacher meeting for Class 9 will be held on Friday at 10:00 AM in the school auditorium. Guardian attendance is requested.",
        audience: "ALL",
        publishDate: d(-6),
        isPinned: false,
      },
      {
        institutionId: school.id,
        title: "Library book return reminder",
        body: "All books issued before this month must be returned before the term final examination. A fine of Tk 10/day applies after the due date.",
        audience: "STUDENTS",
        publishDate: d(-25),
        expiryDate: d(-3),
        isPinned: false,
      },
    ],
  });

  await prisma.complaint.createMany({
    data: [
      {
        institutionId: school.id,
        complainantType: "PARENT",
        complainantName: "Rafiq Islam",
        studentId: students[1].id,
        category: "FACILITY",
        subject: "Drinking water cooler on 2nd floor",
        description: "The water cooler on the 2nd floor has been out of order for two weeks. Students have to go downstairs between classes.",
        status: "IN_REVIEW",
      },
      {
        institutionId: school.id,
        complainantType: "STUDENT",
        complainantName: "Tanvir Ahmed",
        studentId: students[2].id,
        category: "ACADEMIC",
        subject: "Extra mathematics practice classes",
        description: "Requesting additional math practice sessions before the term final for Class 8 Section B.",
        status: "RESOLVED",
        responseNote: "Arranged weekly extra classes every Thursday from next week.",
        resolvedAt: d(-1),
      },
      {
        institutionId: school.id,
        complainantType: "STAFF",
        complainantName: "Mahmudul Hasan",
        category: "FACILITY",
        subject: "Staff room fan replacement",
        description: "Two ceiling fans in the staff room are not working properly.",
        status: "PENDING",
      },
    ],
  });

  await prisma.eventItem.createMany({
    data: [
      {
        institutionId: school.id,
        title: "Science Fair 2026",
        titleBn: "বিজ্ঞান মেলা ২০২৬",
        description: "Inter-school science fair with project displays, robotics demos and quiz bowls.",
        venue: "Main Auditorium",
        category: "ACADEMIC",
        startDate: d(9),
        endDate: d(10),
      },
      {
        institutionId: school.id,
        title: "Cultural Evening",
        description: "Music, drama and recitation performances by students.",
        venue: "School Ground",
        category: "CULTURAL",
        startDate: d(24),
      },
      {
        institutionId: school.id,
        title: "Mid-term Examination",
        description: "Mid-term exams for all classes. Routine published on the notice board.",
        category: "EXAM",
        startDate: d(35),
        endDate: d(40),
      },
      {
        institutionId: school.id,
        title: "Independence Day celebration",
        venue: "School Ground",
        category: "HOLIDAY",
        startDate: d(-160),
      },
    ],
  });

  const academicCouncil = await prisma.committee.create({
    data: {
      institutionId: school.id,
      name: "Academic Council",
      nameBn: "একাডেমিক কাউন্সিল",
      description: "Reviews curriculum, exam results and academic standards.",
      formedDate: d(-300),
    },
  });
  const discipline = await prisma.committee.create({
    data: {
      institutionId: school.id,
      name: "Discipline Committee",
      description: "Maintains student discipline and reviews incident reports.",
      formedDate: d(-200),
    },
  });

  // staff[0] Principal, staff[1] Farhana, staff[3] Librarian
  await prisma.committeeMember.createMany({
    data: [
      { institutionId: school.id, committeeId: academicCouncil.id, staffId: staff[0].id, role: "PRESIDENT", joinedDate: d(-300) },
      { institutionId: school.id, committeeId: academicCouncil.id, staffId: staff[1].id, role: "SECRETARY", joinedDate: d(-300) },
      { institutionId: school.id, committeeId: academicCouncil.id, memberName: "Dr. Salma Khatun", memberDesignation: "Education Specialist", role: "MEMBER", joinedDate: d(-280) },
      { institutionId: school.id, committeeId: discipline.id, staffId: staff[2].id, role: "PRESIDENT", joinedDate: d(-200) },
      { institutionId: school.id, committeeId: discipline.id, staffId: staff[3].id, role: "MEMBER", joinedDate: d(-200) },
    ],
  });

  console.log("  ✔ Notice/Complaint/Event/Committee demo data");

  /* ================================================================
   *  Class routine demo data
   * ================================================================ */
  const subjectByName = new Map(allItems.filter((i) => i.category === "SUBJECT").map((i) => [i.name, i.id]));
  const roomByName = new Map(allItems.filter((i) => i.category === "ROOM").map((i) => [i.name, i.id]));
  const groupByName = new Map(allItems.filter((i) => i.category === "GROUP").map((i) => [i.name, i.id]));
  const sessionByName = new Map(allItems.filter((i) => i.category === "SESSION").map((i) => [i.name, i.id]));

  // staff[1] = Farhana (Science), staff[2] = Mahmudul (Arts)
  const week = ["SAT", "SUN", "MON", "TUE", "WED"];

  const scheduleSeed = [
    // Class 9, Section A — Science subjects with Farhana
    { cls: "Class 9", sec: "Section A", subject: "Physics", teacher: staff[1].id, room: "Science Lab", start: "09:00", end: "10:00", days: ["SAT", "MON", "WED"], active: true },
    { cls: "Class 9", sec: "Section A", subject: "Chemistry", teacher: staff[1].id, room: "Science Lab", start: "10:00", end: "11:00", days: ["SAT", "MON", "WED"], active: true },
    { cls: "Class 9", sec: "Section A", subject: "Mathematics", teacher: staff[2].id, room: "Room 101", start: "09:00", end: "10:00", days: ["SUN", "TUE"], active: true },
    { cls: "Class 9", sec: "Section A", subject: "Bangla", teacher: staff[2].id, room: "Room 101", start: "11:00", end: "12:00", days: week, active: true },
    { cls: "Class 9", sec: "Section A", subject: "English", teacher: staff[2].id, room: "Room 102", start: "12:00", end: "13:00", days: ["SUN", "TUE", "THU"], active: true },
    // Class 8, Section B — with Mahmudul
    { cls: "Class 8", sec: "Section B", subject: "Mathematics", teacher: staff[2].id, room: "Room 201", start: "10:00", end: "11:00", days: ["SAT", "MON", "WED"], active: true },
    { cls: "Class 8", sec: "Section B", subject: "Science", teacher: staff[1].id, room: "Room 201", start: "11:00", end: "12:00", days: ["SUN", "TUE"], active: true },
    { cls: "Class 8", sec: "Section B", subject: "ICT", teacher: staff[1].id, room: "Room 201", start: "09:00", end: "10:00", days: ["THU"], active: false },
  ];

  for (const s of scheduleSeed) {
    await prisma.classSchedule.create({
      data: {
        institutionId: school.id,
        staffId: s.teacher,
        sessionItemId: sessionByName.get("2026-27") ?? null,
        classItemId: classByName.get(s.cls) ?? null,
        sectionItemId: sectionByName.get(s.sec) ?? null,
        subjectItemId: subjectByName.get(s.subject) ?? null,
        roomItemId: roomByName.get(s.room) ?? null,
        groupItemId: groupByName.get("Science") ?? null,
        days: s.days,
        startTime: s.start,
        endTime: s.end,
        isActive: s.active,
      },
    });
  }

  console.log("  ✔ Class routine: 8 schedules across Class 8 & 9 (1 inactive)");

  /* ================================================================
   *  Member credentials (Demo High School, code HS-1001)
   *  Members log in with Institution Code + Username + Password
   * ================================================================ */
  const memberPassword = await bcrypt.hash("Member@123", 10);
  const arif = students.find((s) => s.roll === "1001")!;
  const arifFull = await prisma.student.findUnique({ where: { id: arif.id } });
  await prisma.user.create({
    data: {
      name: arif.name,
      username: arif.roll,
      passwordHash: memberPassword,
      role: "STUDENT",
      institutionId: school.id,
      studentProfileId: arif.id,
    },
  });
  await prisma.user.create({
    data: {
      name: arifFull?.guardianName ?? "Kamal Hasan",
      username: `${arif.roll}-P`,
      passwordHash: memberPassword,
      role: "PARENT",
      institutionId: school.id,
      parentOfStudentId: arif.id,
    },
  });
  const farhana = staff.find((s) => s.code === "EMP-002")!;
  await prisma.user.create({
    data: {
      name: farhana.name,
      username: farhana.code,
      passwordHash: memberPassword,
      role: "TEACHER",
      institutionId: school.id,
      staffId: farhana.id,
    },
  });
  // Farhana is the demo Student Identity maintainer for Class 9 — log in as
  // HS-1001 / EMP-002 to see the maintainer view of /portal/identity
  await prisma.identityManager.create({
    data: {
      institutionId: school.id,
      staffId: farhana.id,
      scopeClassItemIds: [classByName.get("Class 9")!],
      grantedById: schoolAdminUser!.id,
    },
  });
  const rashed = staff.find((s) => s.code === "EMP-004")!;
  await prisma.user.create({
    data: {
      name: rashed.name,
      username: rashed.code,
      passwordHash: memberPassword,
      role: "STAFF",
      institutionId: school.id,
      staffId: rashed.id,
    },
  });
  console.log("  ✔ Member credentials (HS-1001 · Member@123):");
  console.log("      Student 1001 · Parent 1001-P · Teacher EMP-002 · Staff EMP-004");

  /* ================================================================
   *  Demo Primary School — operational Exam Result module (PRIMARY type)
   *  ================================================================ */
  const primaryPassword = await bcrypt.hash("Primary@123", 10);
  const primarySchool = await prisma.institution.create({
    data: {
      name: "Demo Primary School",
      code: "PS-1004",
      type: "PRIMARY_AND_HIGH_SCHOOL",
      email: "primary@demo.com",
      phone: "+880 1711-888999",
      address: "15, Road 7, Mirpur, Dhaka",
      district: "Dhaka",
      subDistrict: "Dhaka Metropolitan",
      status: "ACTIVE",
      createdAt: new Date("2026-01-10"),
      users: {
        create: {
          name: "Primary Admin",
          email: "primary@demo.com",
          passwordHash: primaryPassword,
          role: "INSTITUTION_ADMIN",
        },
      },
    },
  });

  const primaryClass = classByName.get("Class 3") ?? null;
  const primarySection = sectionByName.get("Section A") ?? null;
  const primarySubjectByName = new Map(allItems.filter((i) => i.category === "SUBJECT").map((i) => [i.name, i.id]));

  const primarySeed = [
    { roll: "2001", name: "Abdullah Al Noman", bn: "আব্দুল্লাহ আল নোমান", father: "মোঃ শাহ আলম", mother: "রোকসানা বেগম", scores: [88, 82, 95, 85] },
    { roll: "2002", name: "Fatima Begum", bn: "ফাতিমা বেগম", father: "মোঃ ইদ্রিস আলী", mother: "সেলিনা আক্তার", scores: [74, 79, 68, 81] },
    { roll: "2003", name: "Sabbir Rahman", bn: "সাব্বির রহমান", father: "মোঃ আনোয়ার হোসেন", mother: "নাসরিন সুলতানা", scores: [58, 62, 55, 66] },
    { roll: "2004", name: "Tasnim Akter", bn: "তাসনিম আক্তার", father: "মোঃ কামরুল ইসলাম", mother: "শাহনাজ পারভীন", scores: [45, 52, 38, 49] },
    { roll: "2005", name: "Jubayer Hossain", bn: "জুবায়ের হোসেন", father: "মোঃ দেলোয়ার হোসেন", mother: "আয়েশা সিদ্দিকা", scores: [28, 35, 30, 41] },
  ];
  const primaryStudents: { id: number; scores: number[] }[] = [];
  for (const p of primarySeed) {
    const st = await prisma.student.create({
      data: {
        institutionId: primarySchool.id,
        roll: p.roll,
        name: p.name,
        nameBn: p.bn,
        gender: p.roll === "2002" || p.roll === "2004" ? "FEMALE" : "MALE",
        dob: new Date("2017-06-01"),
        guardianName: p.father,
        guardianPhone: "+880 18" + p.roll,
        motherName: p.mother,
        address: "Mirpur, Dhaka",
        classItemId: primaryClass,
        sectionItemId: primarySection,
        createdAt: new Date("2026-01-25"),
      },
    });
    primaryStudents.push({ id: st.id, scores: p.scores });
  }

  const primaryExam = await prisma.exam.create({
    data: {
      institutionId: primarySchool.id,
      name: "Annual Examination 2026",
      nameBn: "বার্ষিক পরীক্ষা ২০২৬",
      classItemId: primaryClass,
      sectionItemId: primarySection,
      startDate: new Date("2026-08-05"),
      endDate: new Date("2026-08-12"),
      status: "FINISHED",
      format: "FINAL",
    },
  });

  const papers = [
    { subject: "Bangla", date: new Date("2026-08-05"), scores: 0 },
    { subject: "English", date: new Date("2026-08-06"), scores: 1 },
    { subject: "Mathematics", date: new Date("2026-08-07"), scores: 2 },
    { subject: "Science", date: new Date("2026-08-09"), scores: 3 },
  ];
  for (const [pi, paper] of papers.entries()) {
    const schedule = await prisma.examSchedule.create({
      data: {
        institutionId: primarySchool.id,
        examId: primaryExam.id,
        subjectItemId: primarySubjectByName.get(paper.subject) ?? null,
        date: paper.date,
        startTime: "10:00",
        endTime: "12:00",
        fullMarks: 100,
        totalPassMarks: 33,
        cqMarks: 70,
        cqPassMarks: 23,
        mcqMarks: 30,
        mcqPassMarks: 10,
      },
    });
    for (const st of primaryStudents) {
      const total = st.scores[pi];
      const mcq = Math.min(30, Math.round(total * 0.3));
      await prisma.examMark.create({
        data: {
          institutionId: primarySchool.id,
          examScheduleId: schedule.id,
          studentId: st.id,
          cq: total - mcq,
          mcq,
          total,
        },
      });
    }
  }

  /* Two periodical assessments so the Periodical/Final formats have data */
  const periodicalExams = [
    { name: "First Periodical Test 2026", bn: "প্রথম পিরিয়ডিক্যাল পরীক্ষা ২০২৬", start: "2026-04-06", deltas: [-6, 4, -3, 6, 5] },
    { name: "Second Periodical Test 2026", bn: "দ্বিতীয় পিরিয়ডিক্যাল পরীক্ষা ২০২৬", start: "2026-06-01", deltas: [3, -5, 7, -4, -6] },
  ];
  for (const [pi2, pe] of periodicalExams.entries()) {
    const peExam = await prisma.exam.create({
      data: {
        institutionId: primarySchool.id,
        name: pe.name,
        nameBn: pe.bn,
        classItemId: primaryClass,
        sectionItemId: primarySection,
        startDate: new Date(pe.start),
        endDate: new Date(pe.start),
        status: "FINISHED",
        format: "PERIODICAL",
      },
    });
    for (const [pi, paper] of papers.entries()) {
      const schedule = await prisma.examSchedule.create({
        data: {
          institutionId: primarySchool.id,
          examId: peExam.id,
          subjectItemId: primarySubjectByName.get(paper.subject) ?? null,
          date: new Date(pe.start),
          startTime: "10:00",
          endTime: "11:30",
          fullMarks: 100,
          totalPassMarks: 33,
          cqMarks: 70,
          cqPassMarks: 23,
          mcqMarks: 30,
          mcqPassMarks: 10,
        },
      });
      for (const [si, st] of primaryStudents.entries()) {
        const base = st.scores[pi];
        const delta = pe.deltas[si];
        const total = Math.max(0, Math.min(100, base + delta));
        const mcq = Math.min(30, Math.round(total * 0.3));
        await prisma.examMark.create({
          data: {
            institutionId: primarySchool.id,
            examScheduleId: schedule.id,
            studentId: st.id,
            cq: total - mcq,
            mcq,
            total,
          },
        });
      }
    }
    void pi2;
  }

  // attendance for the marksheet (Academic Day / Present / Absent)
  {
    const attDays = Array.from({ length: 10 }, (_, i) => new Date(2026, 7, 10 + i));
    for (const [di, d] of attDays.entries()) {
      for (const [si, st] of primaryStudents.entries()) {
        // student 5 (Jubayer) is absent 3 days; others 0-1 days
        const absences = si === 4 ? [1, 4, 7] : si === 3 ? [6] : si === 1 ? [2] : [];
        const status = absences.includes(di) ? "ABSENT" : "PRESENT";
        await prisma.studentAttendance.create({
          data: {
            institutionId: primarySchool.id,
            studentId: st.id,
            date: d,
            status: status as never,
          },
        });
      }
    }
  }

  console.log("  ✔ Demo Primary School: primary@demo.com / Primary@123 — 5 students, exam + marks (Results module)");

  /* Satellite demo institutions + district data for central monitoring */
  await seedMonitoring(prisma);
  /* Six Tutorial/Semester exams for the Final Result (3 Sets) module */
  await seedFinalExams(prisma);
  await seedPatternPlans(prisma);
  await seedCompetitions(prisma);
  await seedHighSchool(prisma);
  await seedCampus(prisma);
  await seedCampusExtra(prisma);
  await resetBoardSubjects(prisma);
  console.log("  ✔ Satellite institutions across Gazipur, Rajshahi, Sylhet, Khulna, Cumilla, Barishal (monitoring demo)");

  console.log("  ✔ Demo institutions: school@demo.com / School@123 (ACTIVE)");
  console.log("  ✔ kindergarten@demo.com & college@demo.com / Demo@123");
  console.log("🌱 Seeding complete.");
}

main()
  .catch((e) => {
    console.error(e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });
