import "dotenv/config"
import pg from "pg"
import { PrismaPg } from "@prisma/adapter-pg"
import { PrismaClient } from "../src/generated/prisma/client.ts"

const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL })
const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })

function daysFromNow(days: number): Date {
  return new Date(Date.now() + days * 86400000)
}

function daysAgo(days: number): Date {
  return new Date(Date.now() - days * 86400000)
}

async function main() {
  // ── Organisation ──
  const org = await prisma.organization.upsert({
    where: { slug: "demo-charity" },
    update: {
      bankName: "Barclays",
      bankSortCode: "20-00-00",
      bankAccountNo: "12345678",
      bankAccountName: "Charity Right",
    },
    create: {
      name: "Charity Right",
      slug: "demo-charity",
      country: "UK",
      timezone: "Europe/London",
      bankName: "Barclays",
      bankSortCode: "20-00-00",
      bankAccountNo: "12345678",
      bankAccountName: "Charity Right",
      refPrefix: "DEMO",
      primaryColor: "#1e40af",
    },
  })

  // ── Admin user ──
  await prisma.user.upsert({
    where: { email: "admin@charityright.org" },
    update: {},
    create: {
      email: "admin@charityright.org",
      name: "Azreen Jamal",
      role: "org_admin",
      organizationId: org.id,
    },
  })

  // ── Events ──
  const galaEvent = await prisma.event.upsert({
    where: { organizationId_slug: { organizationId: org.id, slug: "ramadan-gala-2026" } },
    update: { name: "Ramadan Gala 2026", eventDate: daysFromNow(14), goalAmount: 5000000 },
    create: {
      name: "Ramadan Gala 2026",
      slug: "ramadan-gala-2026",
      description: "Annual fundraising gala dinner — all proceeds support orphan education in Bangladesh, Pakistan, and Syria.",
      eventDate: daysFromNow(14),
      location: "Bradford Hilton, Hall Lane, BD1 4QR",
      goalAmount: 5000000, // £50,000
      currency: "GBP",
      status: "active",
      organizationId: org.id,
    },
  })

  const eidEvent = await prisma.event.upsert({
    where: { organizationId_slug: { organizationId: org.id, slug: "eid-community-lunch-2026" } },
    update: {},
    create: {
      name: "Eid Community Lunch 2026",
      slug: "eid-community-lunch-2026",
      description: "Community lunch and fundraiser for local food bank programme.",
      eventDate: daysFromNow(45),
      location: "East London Mosque, Whitechapel Road, E1 1JX",
      goalAmount: 1500000, // £15,000
      currency: "GBP",
      status: "active",
      organizationId: org.id,
    },
  })

  // ── QR Sources for Gala ──
  const qrCodes = [
    { label: "Table 1 - Ahmed", volunteerName: "Ahmed Khan", tableName: "Table 1", code: "gala-tbl1" },
    { label: "Table 2 - Fatima", volunteerName: "Fatima Patel", tableName: "Table 2", code: "gala-tbl2" },
    { label: "Table 3 - Yusuf", volunteerName: "Yusuf Ali", tableName: "Table 3", code: "gala-tbl3" },
    { label: "Table 4 - Khadijah", volunteerName: "Khadijah Begum", tableName: "Table 4", code: "gala-tbl4" },
    { label: "Table 5 - Omar", volunteerName: "Omar Malik", tableName: "Table 5", code: "gala-tbl5" },
    { label: "Main Entrance", volunteerName: null, tableName: null, code: "gala-entrance" },
    { label: "Stage Banner", volunteerName: null, tableName: null, code: "gala-stage" },
    { label: "Online Link", volunteerName: null, tableName: null, code: "gala-online" },
  ]

  const qrSourceIds: Record<string, string> = {}
  for (const qr of qrCodes) {
    const source = await prisma.qrSource.upsert({
      where: { code: qr.code },
      update: { label: qr.label, volunteerName: qr.volunteerName, scanCount: Math.floor(Math.random() * 40) + 5 },
      create: {
        label: qr.label,
        code: qr.code,
        volunteerName: qr.volunteerName,
        tableName: qr.tableName,
        eventId: galaEvent.id,
        scanCount: Math.floor(Math.random() * 40) + 5,
      },
    })
    qrSourceIds[qr.code] = source.id
  }

  // ── QR Sources for Eid ──
  const eidQrs = [
    { label: "Registration Desk", volunteerName: "Ibrahim Hassan", tableName: null, code: "eid-reg" },
    { label: "Online Link", volunteerName: null, tableName: null, code: "eid-online" },
  ]
  for (const qr of eidQrs) {
    await prisma.qrSource.upsert({
      where: { code: qr.code },
      update: {},
      create: {
        label: qr.label,
        code: qr.code,
        volunteerName: qr.volunteerName,
        tableName: qr.tableName,
        eventId: eidEvent.id,
        scanCount: Math.floor(Math.random() * 10) + 2,
      },
    })
  }

  // ── Sample Pledges ──
  const samplePledges = [
    // Paid pledges
    { name: "Sarah Khan", email: "sarah@example.com", phone: "07700900001", amount: 10000, rail: "bank", status: "paid", giftAid: true, qr: "gala-tbl1", daysAgo: 5 },
    { name: "Ali Hassan", email: "ali.hassan@gmail.com", phone: "07700900002", amount: 25000, rail: "bank", status: "paid", giftAid: false, qr: "gala-tbl1", daysAgo: 4 },
    { name: "Amina Begum", email: "amina.b@hotmail.com", phone: "", amount: 5000, rail: "card", status: "paid", giftAid: true, qr: "gala-tbl2", daysAgo: 3 },
    { name: "Mohammed Raza", email: "m.raza@outlook.com", phone: "07700900004", amount: 50000, rail: "gocardless", status: "paid", giftAid: true, qr: "gala-stage", daysAgo: 6 },
    { name: "Zainab Ahmed", email: "zainab@example.com", phone: "", amount: 10000, rail: "bank", status: "paid", giftAid: false, qr: "gala-tbl3", daysAgo: 7 },
    { name: "Hassan Malik", email: "hassan.malik@gmail.com", phone: "07700900006", amount: 20000, rail: "card", status: "paid", giftAid: true, qr: "gala-entrance", daysAgo: 2 },

    // Initiated (payment in progress)
    { name: "Ruqayyah Patel", email: "ruqayyah@example.com", phone: "07700900007", amount: 15000, rail: "bank", status: "initiated", giftAid: true, qr: "gala-tbl4", daysAgo: 1 },
    { name: "Ibrahim Shah", email: "ibrahim.shah@gmail.com", phone: "", amount: 10000, rail: "gocardless", status: "initiated", giftAid: false, qr: "gala-tbl5", daysAgo: 1 },

    // New pledges (just created)
    { name: "Maryam Siddiqui", email: "maryam.s@yahoo.com", phone: "07700900009", amount: 5000, rail: "bank", status: "new", giftAid: false, qr: "gala-tbl2", daysAgo: 0 },
    { name: "Usman Chaudhry", email: "usman.c@gmail.com", phone: "", amount: 100000, rail: "bank", status: "new", giftAid: true, qr: "gala-entrance", daysAgo: 0 },
    { name: "Aisha Rahman", email: "aisha.r@hotmail.com", phone: "07700900011", amount: 7500, rail: "card", status: "new", giftAid: true, qr: "gala-online", daysAgo: 0 },
    { name: null, email: "anon.donor@gmail.com", phone: "", amount: 20000, rail: "bank", status: "new", giftAid: false, qr: "gala-tbl3", daysAgo: 0 },

    // Overdue
    { name: "Tariq Hussain", email: "tariq.h@example.com", phone: "07700900013", amount: 25000, rail: "bank", status: "overdue", giftAid: true, qr: "gala-tbl1", daysAgo: 12 },
    { name: "Nadia Akhtar", email: "nadia.a@outlook.com", phone: "", amount: 10000, rail: "bank", status: "overdue", giftAid: false, qr: "gala-tbl5", daysAgo: 10 },

    // Cancelled
    { name: "Omar Farooq", email: "omar.f@gmail.com", phone: "07700900015", amount: 5000, rail: "card", status: "cancelled", giftAid: false, qr: "gala-tbl4", daysAgo: 8 },

    // FPX pledge (Malaysian donor)
    { name: "Ahmad bin Abdullah", email: "ahmad@example.my", phone: "+60123456789", amount: 50000, rail: "fpx", status: "paid", giftAid: false, qr: "gala-online", daysAgo: 3 },

    // Eid event pledges
    { name: "Hafsa Nawaz", email: "hafsa@example.com", phone: "07700900017", amount: 5000, rail: "bank", status: "new", giftAid: true, qr: null, daysAgo: 1 },
    { name: "Bilal Iqbal", email: "bilal.i@gmail.com", phone: "", amount: 10000, rail: "gocardless", status: "paid", giftAid: false, qr: null, daysAgo: 5 },
  ]

  let pledgeIndex = 0
  for (const p of samplePledges) {
    pledgeIndex++
    const ref = `DEMO-SEED${String(pledgeIndex).padStart(2, "0")}-${Math.floor(p.amount / 100)}`
    const isEid = p.qr === null
    const eventId = isEid ? eidEvent.id : galaEvent.id
    const createdAt = daysAgo(p.daysAgo)
    const paidAt = p.status === "paid" ? daysAgo(Math.max(p.daysAgo - 1, 0)) : null

    // Skip if reference already exists
    const existing = await prisma.pledge.findUnique({ where: { reference: ref } })
    if (existing) continue

    const pledge = await prisma.pledge.create({
      data: {
        reference: ref,
        amountPence: p.amount,
        currency: "GBP",
        rail: p.rail,
        status: p.status,
        donorName: p.name,
        donorEmail: p.email || null,
        donorPhone: p.phone || null,
        giftAid: p.giftAid,
        eventId,
        qrSourceId: p.qr ? qrSourceIds[p.qr] || null : null,
        organizationId: org.id,
        createdAt,
        paidAt,
        cancelledAt: p.status === "cancelled" ? daysAgo(p.daysAgo - 1) : null,
      },
    })

    // Payment instruction for bank transfers
    if (p.rail === "bank") {
      await prisma.paymentInstruction.create({
        data: {
          pledgeId: pledge.id,
          bankReference: ref,
          bankDetails: {
            bankName: "Barclays",
            sortCode: "20-00-00",
            accountNo: "12345678",
            accountName: "Charity Right",
          },
        },
      })
    }

    // Payment record for paid pledges
    if (p.status === "paid") {
      await prisma.payment.create({
        data: {
          pledgeId: pledge.id,
          provider: p.rail === "gocardless" ? "gocardless" : p.rail === "card" || p.rail === "fpx" ? "stripe" : "bank",
          providerRef: p.rail === "bank" ? null : `sim_${pledge.id.slice(0, 8)}`,
          amountPence: p.amount,
          status: "confirmed",
          matchedBy: p.rail === "bank" ? "auto" : "webhook",
          receivedAt: paidAt,
        },
      })
    }

    // Reminders for non-paid pledges
    if (["new", "initiated", "overdue"].includes(p.status)) {
      const steps = [
        { step: 0, delayDays: 0, key: "instructions" },
        { step: 1, delayDays: 2, key: "gentle_nudge" },
        { step: 2, delayDays: 7, key: "urgency_impact" },
        { step: 3, delayDays: 14, key: "final_reminder" },
      ]
      for (const s of steps) {
        const scheduledAt = new Date(createdAt.getTime() + s.delayDays * 86400000)
        const isSent = scheduledAt < new Date() && p.status !== "new"
        await prisma.reminder.create({
          data: {
            pledgeId: pledge.id,
            step: s.step,
            channel: "email",
            scheduledAt,
            status: p.status === "overdue" && s.step <= 2 ? "sent" : isSent ? "sent" : "pending",
            sentAt: isSent ? scheduledAt : null,
            payload: { templateKey: s.key },
          },
        })
      }
    }

    // Analytics events
    await prisma.analyticsEvent.create({
      data: {
        eventType: "pledge_completed",
        pledgeId: pledge.id,
        eventId,
        qrSourceId: p.qr ? qrSourceIds[p.qr] || null : null,
        metadata: { amountPence: p.amount, rail: p.rail },
        createdAt,
      },
    })
  }

  // ── Funnel analytics (scans → starts → completions) ──
  const funnelEvents = [
    ...Array.from({ length: 45 }, () => ({ eventType: "pledge_start", eventId: galaEvent.id })),
    ...Array.from({ length: 8 }, () => ({ eventType: "pledge_start", eventId: eidEvent.id })),
    ...Array.from({ length: 12 }, () => ({ eventType: "instruction_copy_clicked", eventId: galaEvent.id })),
    ...Array.from({ length: 6 }, () => ({ eventType: "i_paid_clicked", eventId: galaEvent.id })),
  ]
  for (const fe of funnelEvents) {
    await prisma.analyticsEvent.create({
      data: {
        eventType: fe.eventType,
        eventId: fe.eventId,
        createdAt: daysAgo(Math.floor(Math.random() * 7)),
      },
    })
  }

  // Count totals
  const pledgeCount = await prisma.pledge.count({ where: { organizationId: org.id } })
  const totalAmount = await prisma.pledge.aggregate({ where: { organizationId: org.id }, _sum: { amountPence: true } })

  console.log("✅ Seed data created")
  console.log(`   Org:      ${org.name} (${org.slug})`)
  console.log(`   Events:   ${galaEvent.name}, ${eidEvent.name}`)
  console.log(`   QR Codes: ${qrCodes.length + eidQrs.length}`)
  console.log(`   Pledges:  ${pledgeCount} (£${((totalAmount._sum.amountPence || 0) / 100).toLocaleString()})`)
}

main()
  .catch(console.error)
  .finally(async () => {
    await prisma.$disconnect()
    await pool.end()
  })
