/**
 * Comprehensive seed for end-to-end manual testing.
 * Run with: npm run seed
 *
 * Covers every user role, permission variant, visitor status, and product
 * feature so all flows can be exercised with a single command. Wipes
 * existing rows first — reruns produce a clean, reproducible state.
 */

import bcrypt from 'bcryptjs';
import { nanoid } from 'nanoid';
import { prisma } from '../config/database';
import { generateQRCodeBuffer } from '../utils/qrcode';
import { saveUpload } from '../config/storage';

const log = (msg: string) => console.log(`[seed] ${msg}`);

async function wipe(): Promise<void> {
  log('Wiping existing data…');
  // Delete children first, then parents. Any row with an FK to Owner
  // must be cleared before Owner itself, otherwise Prisma throws P2003.
  // VisitorEditLog cascades off Visitor at the DB level, but delete it
  // explicitly up front too — past omissions here made the seed
  // non-idempotent on some Postgres versions.
  await prisma.visitorEditLog.deleteMany();
  await prisma.notification.deleteMany();
  await prisma.otpToken.deleteMany();
  await prisma.pushSubscription.deleteMany();
  await prisma.deviceToken.deleteMany();
  await prisma.platformAdmin.deleteMany();
  await prisma.visitorScanLog.deleteMany();
  await prisma.visitorRequest.deleteMany();
  await prisma.visitor.deleteMany();
  await prisma.walkInQR.deleteMany();
  await prisma.visitorCheckpoint.deleteMany();
  await prisma.emailTemplate.deleteMany();
  await prisma.emailAutomation.deleteMany();
  await prisma.visitorReason.deleteMany();
  await prisma.department.deleteMany();
  await prisma.approver.deleteMany();
  // Null the self-referential FK before bulk-deleting admins
  await prisma.admin.updateMany({ data: { createdByAdminId: null } });
  await prisma.admin.deleteMany();
  await prisma.owner.deleteMany();
  await prisma.allowedEmail.deleteMany();
}

async function mkVisitorQR(name: string): Promise<{ shortId: string; qrCodeUrl: string }> {
  const shortId = nanoid(10).toUpperCase();
  const buf = await generateQRCodeBuffer(shortId);
  const url = await saveUpload(buf, `visitors/qr/${shortId}.png`, 'image/png');
  return { shortId, qrCodeUrl: url };
}

async function mkWalkInQRCode(code: string): Promise<string> {
  const buf = await generateQRCodeBuffer(code);
  return saveUpload(buf, `walk-in-qrs/${code}.png`, 'image/png');
}

async function main(): Promise<void> {
  await wipe();

  // ── Platform Admin (vendor console /platform/login) ──────────────────────
  log('Creating platform admin…');
  await prisma.platformAdmin.create({
    data: { email: 'platform@example.com', name: 'Platform Admin', isActive: true },
  });

  // ── Allowed Emails (gates OTP login for owner + all admins/approvers) ────
  log('Creating allowed emails…');
  for (const email of [
    'owner@example.com',
    'admin.full@example.com',
    'admin.approver@example.com',
    'admin.scanner@example.com',
    'admin.readonly@example.com',
    'dan.admin@example.com',
    'alice@example.com',
    'bob@example.com',
    'carol@example.com',
  ]) {
    await prisma.allowedEmail.create({ data: { email, isActive: true } });
  }

  // ── Owner (workspace super-admin) ────────────────────────────────────────
  log('Creating owner…');
  const owner = await prisma.owner.create({
    data: { email: 'owner@example.com', name: 'Workspace Owner' },
  });

  // ── Departments ──────────────────────────────────────────────────────────
  log('Creating departments…');
  for (const name of ['HR', 'Engineering', 'Sales', 'Operations', 'Finance']) {
    await prisma.department.create({ data: { ownerId: owner.id, name } });
  }

  // ── Visitor reason presets ───────────────────────────────────────────────
  log('Creating visitor reasons…');
  for (const name of [
    'Job interview',
    'Vendor meeting',
    'Sales pitch',
    'Partnership discussion',
    'Delivery / Courier',
    'Document handover',
    'Site tour',
    'Investor briefing',
    'HR consultation',
    'Compliance audit',
  ]) {
    await prisma.visitorReason.create({ data: { ownerId: owner.id, name } });
  }

  // ── Legacy Approvers ─────────────────────────────────────────────────────
  log('Creating legacy approvers…');
  const alice = await prisma.approver.create({
    data: {
      ownerId: owner.id,
      name: 'Alice Approver',
      email: 'alice@example.com',
      phone: '+91 90000 00011',
      designation: 'Manager',
      department: 'HR',
      isActive: true,
      canAddVisitors: true,
    },
  });
  const bob = await prisma.approver.create({
    data: {
      ownerId: owner.id,
      name: 'Bob Approver',
      email: 'bob@example.com',
      phone: '+91 90000 00012',
      designation: 'Director',
      department: 'Sales',
      isActive: true,
      canAddVisitors: false,
    },
  });
  await prisma.approver.create({
    data: {
      ownerId: owner.id,
      name: 'Carol (inactive)',
      email: 'carol@example.com',
      phone: '+91 90000 00013',
      designation: 'Lead',
      department: 'Engineering',
      isActive: false,    // should be blocked at login
      canAddVisitors: true,
    },
  });

  // ── Admins (5 permission profiles) ───────────────────────────────────────
  log('Creating admins…');

  // 1. Full admin — every flag on; tests the "super sub-admin" path
  const adminFull = await prisma.admin.create({
    data: {
      ownerId: owner.id,
      name: 'Fatima Full Admin',
      email: 'admin.full@example.com',
      phone: '+91 90000 10001',
      designation: 'Operations Head',
      department: 'Operations',
      isActive: true,
      isApprover: true,
      canManageVisitors: true,
      canManageApprovers: true,
      canManageSettings: true,
      canApproveRequests: true,
      canAddVisitors: true,
      canViewWalkInQr: true,
      canAddWalkInQr: true,
      canDeleteWalkInQr: true,
      canBackdateVisitor: true,
      canScanCheckpoint: true,
      canManageSubAdmins: true,
      canSeeAllVisitors: true,
      canPolicyAuto: true,
      canPolicyLive: true,
      canPolicyPre: true,
      canPolicyWalkIn: true,
    },
  });

  // 2. Approver-type admin — isApprover=true; models the new merged role
  const adminApprover = await prisma.admin.create({
    data: {
      ownerId: owner.id,
      name: 'Raj Approver-Admin',
      email: 'admin.approver@example.com',
      phone: '+91 90000 10002',
      designation: 'Engineering Manager',
      department: 'Engineering',
      isActive: true,
      isApprover: true,
      canManageVisitors: true,
      canApproveRequests: true,
      canAddVisitors: true,
      canViewWalkInQr: true,
      canAddWalkInQr: true,
      canSeeAllVisitors: false,   // only sees assigned visitors
      canPolicyLive: true,
      canPolicyPre: true,
      canPolicyAuto: false,
      canPolicyWalkIn: false,
    },
  });

  // 3. Scanner / front-desk — scan QRs + see all visitors; no edit access
  await prisma.admin.create({
    data: {
      ownerId: owner.id,
      name: 'Sam Scanner',
      email: 'admin.scanner@example.com',
      phone: '+91 90000 10003',
      designation: 'Front Desk Executive',
      department: 'Operations',
      isActive: true,
      canManageVisitors: false,
      canScanCheckpoint: true,
      canSeeAllVisitors: true,
    },
  });

  // 4. Read-only — sees everything, changes nothing; compliance / audit persona
  await prisma.admin.create({
    data: {
      ownerId: owner.id,
      name: 'Rita Readonly',
      email: 'admin.readonly@example.com',
      phone: '+91 90000 10004',
      designation: 'Compliance Officer',
      department: 'Finance',
      isActive: true,
      canManageVisitors: false,
      canSeeAllVisitors: true,
    },
  });

  // 5. Manage + approve — original "Dan" persona kept for regression coverage
  await prisma.admin.create({
    data: {
      ownerId: owner.id,
      name: 'Dan Admin',
      email: 'dan.admin@example.com',
      phone: '+91 90000 10005',
      isActive: true,
      canManageVisitors: true,
      canApproveRequests: true,
    },
  });

  // ── Checkpoints (scanner login: username + password, no OTP) ─────────────
  log('Creating checkpoints…');
  const cpPass = 'scan123';
  const cpHash = bcrypt.hashSync(cpPass, 10);
  const reception = await prisma.visitorCheckpoint.create({
    data: {
      ownerId: owner.id,
      name: 'Main Reception',
      personName: 'Reena Desk',
      mobile: '9000000001',
      passwordHash: cpHash,
      plainPassword: cpPass,
      isActive: true,
    },
  });
  await prisma.visitorCheckpoint.create({
    data: {
      ownerId: owner.id,
      name: 'South Gate',
      personName: 'Rohit Guard',
      mobile: '9000000002',
      passwordHash: cpHash,
      plainPassword: cpPass,
      isActive: true,
    },
  });

  // ── Email template + automation ──────────────────────────────────────────
  log('Creating email template + automation…');
  await prisma.emailTemplate.create({
    data: {
      ownerId: owner.id,
      type: 'VISITOR_INVITE',
      subject: 'You have a visit scheduled with {{host_name}}',
      body:
        `Hi {{visitor_name}},\n\n` +
        `You're expected at our office {{visit_date}}{{visit_time}}.\n` +
        `Your visitor ID: {{visitor_id}}\n\nNotes: {{visit_notes}}\n\n— {{host_name}}`,
    },
  });
  await prisma.emailAutomation.create({
    data: {
      ownerId: owner.id,
      inviteEnabled: false,
      checkInEnabled: false,
      reminderEnabled: false,
    },
  });

  // ── Walk-in QR posters ───────────────────────────────────────────────────
  log('Creating walk-in QR posters…');
  const qrCode1 = nanoid(12).toUpperCase();
  const qrCode2 = nanoid(12).toUpperCase();
  const qrUrl1 = await mkWalkInQRCode(qrCode1);
  const qrUrl2 = await mkWalkInQRCode(qrCode2);
  await prisma.walkInQR.create({
    data: {
      ownerId: owner.id,
      assignedAdminId: adminApprover.id,
      createdByAdminId: adminFull.id,
      label: 'Main Lobby',
      code: qrCode1,
      qrCodeUrl: qrUrl1,
      isActive: true,
      requiresApproval: true,
    },
  });
  await prisma.walkInQR.create({
    data: {
      ownerId: owner.id,
      label: 'Delivery Entrance',
      code: qrCode2,
      qrCodeUrl: qrUrl2,
      isActive: true,
      requiresApproval: false,    // straight to ARRIVED on scan
    },
  });

  // ── Visitors ─────────────────────────────────────────────────────────────
  log('Creating visitors…');
  const now = new Date();
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const tomorrow = new Date(today.getTime() + 1 * 24 * 60 * 60 * 1000);
  const dayAfterTomorrow = new Date(today.getTime() + 2 * 24 * 60 * 60 * 1000);
  const inThreeDays = new Date(today.getTime() + 3 * 24 * 60 * 60 * 1000);
  const inSixMonths = new Date(today.getTime() + 180 * 24 * 60 * 60 * 1000);
  const yesterday = new Date(today.getTime() - 1 * 24 * 60 * 60 * 1000);
  const twoDaysAgo = new Date(today.getTime() - 2 * 24 * 60 * 60 * 1000);
  const in2h = new Date(now.getTime() + 2 * 60 * 60 * 1000);

  type Spec = {
    name: string;
    mobile?: string;
    email?: string;
    reasonForVisit: string;
    notes?: string;
    visitDate?: Date;
    visitTime?: string;
    status: 'EXPECTED' | 'AWAITING_APPROVAL' | 'ARRIVED' | 'CHECKED_OUT' | 'REJECTED' | 'CANCELLED' | 'EXPIRED';
    arrivedAt?: Date;
    checkedOutAt?: Date;
    requiresApproval?: boolean;
    isPreApproval?: boolean;
    approvalRequestedAt?: Date;
    approvalNote?: string;
    assignedApproverId?: string;
    assignedAdminId?: string;
    createdByApproverId?: string;
    createdByAdminId?: string;
    expiresAt?: Date;
    isFrequent?: boolean;
    frequencyType?: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'CUSTOM';
    frequencyValidFrom?: Date;
    frequencyValidUntil?: Date;
    frequencyWeekdays?: number[];
    addScanLog?: boolean;
  };

  const specs: Spec[] = [
    // ── EXPECTED ────────────────────────────────────────────────────────────
    {
      name: 'Priya Shah', mobile: '+91 98765 11111', email: 'priya@acme.com',
      reasonForVisit: 'Interview with HR team',
      visitDate: today, visitTime: '10:00', status: 'EXPECTED',
    },
    {
      name: 'Karan Mehta', mobile: '+91 98765 11112', email: 'karan@acme.com',
      reasonForVisit: 'Vendor demo for procurement',
      visitDate: tomorrow, visitTime: '14:30', status: 'EXPECTED',
    },
    {
      name: 'Sneha Kapoor', mobile: '+91 98765 11113', email: 'sneha@acme.com',
      reasonForVisit: 'Partnership discussion with founders',
      notes: 'Please escort to floor 4',
      visitDate: today, visitTime: '11:30', status: 'EXPECTED',
      requiresApproval: true,
    },
    {
      name: 'Rohan Patel', mobile: '+91 98765 11114', email: 'rohan@acme.com',
      reasonForVisit: 'HR onboarding interview',
      visitDate: today, visitTime: '12:00', status: 'EXPECTED',
      requiresApproval: true, assignedApproverId: alice.id,
    },
    {
      name: 'Aisha Khan', mobile: '+91 98765 11115',
      reasonForVisit: 'Document handover — time-sensitive',
      visitDate: today, visitTime: '13:00', status: 'EXPECTED',
      requiresApproval: true, assignedApproverId: alice.id, expiresAt: in2h,
    },
    // Pre-approval: host decided YES before arrival → status=EXPECTED, scan straight to ARRIVED
    {
      name: 'Nilufar Rashidova', mobile: '+91 98765 11130', email: 'nilufar@partner.io',
      reasonForVisit: 'Board member — pre-approved entry',
      notes: 'Gold tier access — escort not required',
      visitDate: today, visitTime: '09:00', status: 'EXPECTED',
      requiresApproval: true, isPreApproval: true,
      approvalNote: 'Pre-approved by Fatima',
      assignedAdminId: adminFull.id,
    },
    // Created and assigned to the new approver-admin
    {
      name: 'Neha Verma', mobile: '+91 98765 11122', email: 'neha@acme.com',
      reasonForVisit: 'Engineering code review session',
      visitDate: tomorrow, visitTime: '15:00', status: 'EXPECTED',
      createdByAdminId: adminApprover.id, assignedAdminId: adminApprover.id,
    },
    // Created by Bob (legacy approver)
    {
      name: 'Manish Rao', mobile: '+91 98765 11123',
      reasonForVisit: 'Sales lead introduction',
      visitDate: tomorrow, visitTime: '11:00', status: 'EXPECTED',
      createdByApproverId: bob.id,
    },

    // ── AWAITING_APPROVAL ────────────────────────────────────────────────────
    {
      name: 'Meera Iyer', mobile: '+91 98765 11117', email: 'meera@acme.com',
      reasonForVisit: 'Legal contract signing', notes: 'Bring NDA copies',
      visitDate: today, visitTime: '10:30', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now, addScanLog: true,
    },
    {
      name: 'Dev Sharma', mobile: '+91 98765 11118',
      reasonForVisit: 'Sales pitch from new partner',
      visitDate: today, visitTime: '11:00', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id, addScanLog: true,
    },
    // Pre-approval pending: host needs to decide BEFORE visitor arrives
    {
      name: 'Kabir Singh', mobile: '+91 98765 11131', email: 'kabir@auditor.in',
      reasonForVisit: 'Compliance pre-approval — scheduled for next week',
      visitDate: inThreeDays, visitTime: '10:00', status: 'AWAITING_APPROVAL',
      requiresApproval: true, isPreApproval: true,
      approvalRequestedAt: now, assignedAdminId: adminApprover.id,
    },
    // Alice's workload queue
    {
      name: 'Anika Verma', mobile: '+91 98765 30001', email: 'anika.verma@acme.com',
      reasonForVisit: 'Job interview — Senior React Developer role',
      visitDate: today, visitTime: '10:00', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id,
    },
    {
      name: 'Karthik Reddy', mobile: '+91 98765 30002', email: 'karthik@cloudvendor.io',
      reasonForVisit: 'Vendor pitch — cloud infrastructure migration',
      notes: 'Has signed NDA',
      visitDate: today, visitTime: '11:30', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id,
    },
    {
      name: 'Pooja Iyer', mobile: '+91 98765 30003',
      reasonForVisit: 'Compensation benchmarking consultation',
      visitDate: today, visitTime: '14:00', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id,
    },
    {
      name: 'Sneha Mathur', mobile: '+91 98765 30004', email: 'sneha.m@boardadvisory.com',
      reasonForVisit: 'Q3 board meeting prep — agenda walkthrough',
      visitDate: tomorrow, visitTime: '09:00', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id,
    },
    {
      name: 'Vivek Joshi', mobile: '+91 98765 30005',
      reasonForVisit: 'Compliance audit — annual ISO walkthrough',
      visitDate: tomorrow, visitTime: '13:00', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id,
    },
    {
      name: 'Anita Desai', mobile: '+91 98765 30006', email: 'anita@strategiccoo.com',
      reasonForVisit: 'Strategic review session with COO',
      visitDate: dayAfterTomorrow, visitTime: '11:00', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id,
    },
    {
      name: 'Mohan Patel', mobile: '+91 98765 30007', email: 'mohan@vc-partners.in',
      reasonForVisit: 'Investor introduction — early Series B exploration',
      visitDate: inThreeDays, visitTime: '15:30', status: 'AWAITING_APPROVAL',
      requiresApproval: true, approvalRequestedAt: now,
      assignedApproverId: alice.id,
    },

    // ── ARRIVED ──────────────────────────────────────────────────────────────
    {
      name: 'Tina Roy', mobile: '+91 98765 11119', email: 'tina@acme.com',
      reasonForVisit: 'Office maintenance follow-up',
      visitDate: today, visitTime: '09:30', status: 'ARRIVED',
      arrivedAt: now, addScanLog: true,
    },
    {
      name: 'Arjun Nair', mobile: '+91 98765 11120',
      reasonForVisit: 'Investor briefing',
      visitDate: today, visitTime: '08:00', status: 'ARRIVED',
      arrivedAt: now,
      requiresApproval: true, approvalNote: 'Approved by owner — escort to boardroom',
      addScanLog: true,
    },
    {
      name: 'Walk-in Direct', mobile: '+91 98765 11124',
      reasonForVisit: 'Courier delivery — small parcel',
      status: 'ARRIVED', arrivedAt: now, addScanLog: true,
    },

    // ── CHECKED_OUT ──────────────────────────────────────────────────────────
    {
      name: 'Sumit Bansal', mobile: '+91 98765 40001', email: 'sumit@contractor.com',
      reasonForVisit: 'Office IT equipment setup',
      visitDate: today, visitTime: '08:00', status: 'CHECKED_OUT',
      arrivedAt: new Date(today.getTime() + 8 * 60 * 60 * 1000),
      checkedOutAt: new Date(today.getTime() + 11 * 60 * 60 * 1000),
      addScanLog: true,
    },
    {
      name: 'Divya Nambiar', mobile: '+91 98765 40002',
      reasonForVisit: 'Annual facility inspection',
      visitDate: yesterday, visitTime: '10:00', status: 'CHECKED_OUT',
      arrivedAt: new Date(yesterday.getTime() + 10 * 60 * 60 * 1000),
      checkedOutAt: new Date(yesterday.getTime() + 14 * 60 * 60 * 1000),
      addScanLog: true,
    },

    // ── REJECTED ─────────────────────────────────────────────────────────────
    {
      name: 'Ravi Kulkarni',
      reasonForVisit: 'Walk-in — sales meeting (rejected)',
      status: 'REJECTED',
      requiresApproval: true, approvalNote: 'Wrong appointment — please reschedule',
    },

    // ── CANCELLED ────────────────────────────────────────────────────────────
    {
      name: 'Sunita Joshi', mobile: '+91 98765 11121',
      reasonForVisit: 'Routine vendor visit (cancelled)',
      visitDate: tomorrow, visitTime: '16:00', status: 'CANCELLED',
    },

    // ── EXPIRED ──────────────────────────────────────────────────────────────
    {
      name: 'Vikram Singh', mobile: '+91 98765 11116',
      reasonForVisit: 'Quarterly audit review',
      visitDate: yesterday, visitTime: '09:00', status: 'EXPIRED',
      expiresAt: yesterday,
    },

    // ── FREQUENT — DAILY pass (no expiry window, rescans re-arrive them) ─────
    {
      name: 'Manish Gupta', mobile: '+91 98765 50001', email: 'manish@cleaners.in',
      reasonForVisit: 'Daily housekeeping rounds',
      status: 'EXPECTED', isFrequent: true, frequencyType: 'DAILY',
    },
    // ── FREQUENT — CUSTOM Mon–Fri window, 6-month contract ───────────────────
    {
      name: 'Preethi Nair', mobile: '+91 98765 50002', email: 'preethi@contractor.io',
      reasonForVisit: 'On-site consulting engagement',
      notes: 'Valid Mon–Fri, 6-month contract',
      status: 'EXPECTED', isFrequent: true, frequencyType: 'CUSTOM',
      frequencyValidFrom: today, frequencyValidUntil: inSixMonths,
      frequencyWeekdays: [1, 2, 3, 4, 5],    // 0=Sun … 6=Sat
    },
  ];

  let scanCount = 0;
  for (const s of specs) {
    const { shortId, qrCodeUrl } = await mkVisitorQR(s.name);
    const visitor = await prisma.visitor.create({
      data: {
        ownerId: owner.id,
        shortId,
        name: s.name,
        email: s.email ?? null,
        mobile: s.mobile ?? null,
        reasonForVisit: s.reasonForVisit,
        notes: s.notes ?? null,
        visitDate: s.visitDate ?? null,
        visitTime: s.visitTime ?? null,
        qrCodeUrl,
        status: s.status,
        arrivedAt: s.arrivedAt ?? null,
        checkedOutAt: s.checkedOutAt ?? null,
        requiresApproval: !!s.requiresApproval,
        isPreApproval: !!s.isPreApproval,
        approvalRequestedAt: s.approvalRequestedAt ?? null,
        approvalNote: s.approvalNote ?? null,
        assignedApproverId: s.assignedApproverId ?? null,
        assignedAdminId: s.assignedAdminId ?? null,
        createdByApproverId: s.createdByApproverId ?? null,
        createdByAdminId: s.createdByAdminId ?? null,
        expiresAt: s.expiresAt ?? null,
        isFrequent: !!s.isFrequent,
        frequencyType: s.frequencyType ?? null,
        frequencyValidFrom: s.frequencyValidFrom ?? null,
        frequencyValidUntil: s.frequencyValidUntil ?? null,
        frequencyWeekdays: s.frequencyWeekdays ?? [],
      },
    });
    if (s.addScanLog) {
      await prisma.visitorScanLog.create({
        data: { visitorId: visitor.id, checkpointId: reception.id },
      });
      scanCount++;
    }
  }

  // ── Walk-in requests (4 states) ──────────────────────────────────────────
  log('Creating walk-in requests + linked visitors…');

  type WalkInSpec = {
    name: string;
    phone?: string;
    email?: string;
    company?: string;
    reason: string;
    status: 'PENDING' | 'APPROVED' | 'REJECTED';
    ownerNote?: string;
    assignedApproverId?: string;
  };

  const walkIns: WalkInSpec[] = [
    {
      name: 'Drop-in: Lara Stevens',
      phone: '+91 98765 22001', email: 'lara@partner.io', company: 'Partner Co.',
      reason: 'Unannounced visit — wants to meet finance lead', status: 'PENDING',
    },
    {
      name: 'Drop-in: Sanjay Rao',
      phone: '+91 98765 22002', company: 'Vendor Ltd.',
      reason: 'Follow-up on procurement quote', status: 'PENDING',
      assignedApproverId: alice.id,
    },
    {
      name: 'Drop-in: Maya Patel',
      reason: 'Resume drop-off', status: 'APPROVED',
      ownerNote: 'Send to HR floor',
    },
    {
      name: 'Drop-in: Spam Caller',
      reason: 'Unsolicited cold pitch', status: 'REJECTED',
      ownerNote: 'Not a fit',
    },
  ];

  const visitorStatusByRequest: Record<WalkInSpec['status'], Spec['status']> = {
    PENDING: 'AWAITING_APPROVAL',
    APPROVED: 'ARRIVED',
    REJECTED: 'REJECTED',
  };

  for (const w of walkIns) {
    const { shortId, qrCodeUrl } = await mkVisitorQR(w.name);
    const visitorStatus = visitorStatusByRequest[w.status];
    const v = await prisma.visitor.create({
      data: {
        ownerId: owner.id,
        shortId,
        name: w.name,
        email: w.email ?? null,
        mobile: w.phone ?? null,
        reasonForVisit: w.reason,
        notes: w.company ? `Walk-in from ${w.company}` : null,
        visitDate: now,
        qrCodeUrl,
        status: visitorStatus,
        arrivedAt: visitorStatus === 'ARRIVED' ? now : null,
        requiresApproval: true,
        approvalRequestedAt: now,
        approvalNote: w.ownerNote ?? null,
        assignedApproverId: w.assignedApproverId ?? null,
      },
    });
    await prisma.visitorRequest.create({
      data: {
        ownerId: owner.id,
        checkpointId: reception.id,
        name: w.name,
        phone: w.phone ?? null,
        email: w.email ?? null,
        company: w.company ?? null,
        reason: w.reason,
        status: w.status,
        ownerNote: w.ownerNote ?? null,
        assignedApproverId: w.assignedApproverId ?? null,
        visitorId: v.id,
      },
    });
    await prisma.visitorScanLog.create({
      data: { visitorId: v.id, checkpointId: reception.id },
    });
    scanCount++;
  }

  // ── Sample notifications ─────────────────────────────────────────────────
  log('Creating sample notifications…');

  const notifs = [
    // Owner — 2 unread, 2 read
    { recipientType: 'OWNER' as const, recipientId: owner.id, type: 'visitor:arrived',        title: 'Tina Roy has arrived',           body: 'Office maintenance — checked in at Main Reception',      link: '/visitors', readAt: null },
    { recipientType: 'OWNER' as const, recipientId: owner.id, type: 'request:created',         title: 'New walk-in request',            body: 'Lara Stevens — Unannounced visit, wants to meet finance', link: '/visitors', readAt: null },
    { recipientType: 'OWNER' as const, recipientId: owner.id, type: 'visitor:checked_out',     title: 'Sumit Bansal checked out',       body: 'IT equipment setup — departed at 11:00',                 link: '/visitors', readAt: twoDaysAgo },
    { recipientType: 'OWNER' as const, recipientId: owner.id, type: 'visitor:rejected',        title: 'Visitor rejected',               body: 'Ravi Kulkarni — Wrong appointment, please reschedule',   link: '/visitors', readAt: twoDaysAgo },
    // Alice (legacy approver) — 2 unread, 1 read
    { recipientType: 'APPROVER' as const, recipientId: alice.id, type: 'visitor:approval_requested', title: 'Approval needed: Dev Sharma',  body: 'Sales pitch from new partner — awaiting your decision',  link: '/approvals', readAt: null },
    { recipientType: 'APPROVER' as const, recipientId: alice.id, type: 'visitor:approval_requested', title: 'Approval needed: Anika Verma', body: 'Job interview — Senior React Developer role',            link: '/approvals', readAt: null },
    { recipientType: 'APPROVER' as const, recipientId: alice.id, type: 'visitor:arrived',      title: 'Arjun Nair has arrived',         body: 'Investor briefing — approved and checked in',            link: '/approvals', readAt: yesterday },
    // Checkpoint — 1 unread
    { recipientType: 'CHECKPOINT' as const, recipientId: reception.id, type: 'request:created', title: 'Walk-in: Sanjay Rao',           body: 'Follow-up on procurement quote — Vendor Ltd.',           link: '/visitor-scanner', readAt: null },
  ];

  for (const n of notifs) {
    await prisma.notification.create({ data: n });
  }

  // ── Summary ──────────────────────────────────────────────────────────────
  const totalVisitors = specs.length + walkIns.length;
  log('Done.');
  console.log(`
─────────────────────────────────────────────────────────────────────────
 SEED COMPLETE — Login Credentials
─────────────────────────────────────────────────────────────────────────

 PLATFORM ADMIN  →  /platform/login
   Email:    platform@example.com
   Note:     OTP returned in API response + printed to server console

 WORKSPACE OWNER  →  /login
   Email:    owner@example.com

 ADMINS  →  /login  (5 permission profiles)
   admin.full@example.com       All permissions ON             (Fatima)
   admin.approver@example.com   isApprover + manage + approve  (Raj)
   admin.scanner@example.com    Scan QR + see all visitors     (Sam)
   admin.readonly@example.com   Read-only, no edit access      (Rita)
   dan.admin@example.com        Manage visitors + approve      (Dan)

 LEGACY APPROVERS  →  mobile /login
   alice@example.com            Active — canAddVisitors=true
   bob@example.com              Active — canAddVisitors=false
   carol@example.com            INACTIVE — login should be blocked

 RECEPTION CHECKPOINTS  →  /visitor-scanner/login
   Mobile: 9000000001  Password: ${cpPass}  (Main Reception)
   Mobile: 9000000002  Password: ${cpPass}  (South Gate)

─────────────────────────────────────────────────────────────────────────
 DATA COUNTS
─────────────────────────────────────────────────────────────────────────
 Visitors ……………………… ${totalVisitors}
   EXPECTED            ${specs.filter(s => s.status === 'EXPECTED').length + walkIns.filter(w => w.status === 'PENDING').length}  (incl. walk-in PENDING)
   AWAITING_APPROVAL   ${specs.filter(s => s.status === 'AWAITING_APPROVAL').length}  (incl. pre-approval pending)
   ARRIVED             ${specs.filter(s => s.status === 'ARRIVED').length + walkIns.filter(w => w.status === 'APPROVED').length}  (incl. walk-in approved)
   CHECKED_OUT         ${specs.filter(s => s.status === 'CHECKED_OUT').length}
   REJECTED            ${specs.filter(s => s.status === 'REJECTED').length + walkIns.filter(w => w.status === 'REJECTED').length}
   CANCELLED           ${specs.filter(s => s.status === 'CANCELLED').length}
   EXPIRED             ${specs.filter(s => s.status === 'EXPIRED').length}
   Frequent visitors:  2 (DAILY + CUSTOM Mon–Fri)
   Pre-approval:       2 (1 decided → EXPECTED, 1 pending → AWAITING)

 Scan logs ……………………… ${scanCount}
 Walk-in requests …… 4  (2 PENDING, 1 APPROVED, 1 REJECTED)
 Walk-in QR posters … 2
   Main Lobby URL:          /walk-in/${qrCode1}
   Delivery Entrance URL:   /walk-in/${qrCode2}

 Notifications …………… 8  (4 owner · 3 Alice · 1 checkpoint)
 Departments …………… 5   Visitor reasons: 10

─────────────────────────────────────────────────────────────────────────
 Note: EXPOSE_OTP_IN_RESPONSE=true — OTP is in the auth response body
       and printed to the API server console. No email needed.
─────────────────────────────────────────────────────────────────────────
`);
}

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