/**
 * Dev seed script — populates the dev database with sample data for manual testing.
 * Run: bun run src/db/seeds/dev-seed.ts
 *
 * Prerequisites: backend must have been started at least once (migrations + RBAC seeds applied).
 */
import postgres from 'postgres'

const DB_URL = process.env.DATABASE_URL ?? 'postgresql://lunarfront:lunarfront@localhost:5432/lunarfront'
const COMPANY_ID = 'a0000000-0000-4000-8000-000000000001'

const sql = postgres(DB_URL)

async function seed() {
  console.log('Seeding dev database...')

  // Create company and location if they don't exist
  const [company] = await sql`SELECT id FROM company WHERE id = ${COMPANY_ID}`
  if (!company) {
    await sql`INSERT INTO company (id, name, timezone) VALUES (${COMPANY_ID}, 'Demo Store', 'America/Chicago')`
    await sql`INSERT INTO location (id, name, tax_rate, service_tax_rate) VALUES ('a0000000-0000-4000-8000-000000000002', 'Main Store', '0.0825', '0.0825')`
    console.log('  Created company and location')

    // Seed RBAC
    const { SYSTEM_PERMISSIONS, DEFAULT_ROLES } = await import('../seeds/rbac.js')
    for (const p of SYSTEM_PERMISSIONS) {
      await sql`INSERT INTO permission (slug, domain, action, description) VALUES (${p.slug}, ${p.domain}, ${p.action}, ${p.description}) ON CONFLICT (slug) DO NOTHING`
    }
    const permRows = await sql`SELECT id, slug FROM permission`
    const permMap = new Map(permRows.map((r: any) => [r.slug, r.id]))
    for (const roleDef of DEFAULT_ROLES) {
      const [role] = await sql`INSERT INTO role (name, slug, description, is_system) VALUES (${roleDef.name}, ${roleDef.slug}, ${roleDef.description}, true) RETURNING id`
      for (const permSlug of roleDef.permissions) {
        const permId = permMap.get(permSlug)
        if (permId) await sql`INSERT INTO role_permission (role_id, permission_id) VALUES (${role.id}, ${permId}) ON CONFLICT DO NOTHING`
      }
    }
    console.log('  Seeded RBAC permissions and roles')
  }

  // --- Admin user (if not exists) ---
  const adminPassword = process.env.ADMIN_PASSWORD ?? 'admin1234'
  const [adminUser] = await sql`SELECT id FROM "user" WHERE email = 'admin@lunarfront.dev'`
  if (!adminUser) {
    const bcrypt = await import('bcryptjs')
    const hashedPw = await bcrypt.hash(adminPassword, 10)
    const pinHash = await bcrypt.hash('1234', 10)
    const [user] = await sql`INSERT INTO "user" (email, password_hash, first_name, last_name, role, employee_number, pin_hash) VALUES ('admin@lunarfront.dev', ${hashedPw}, 'Admin', 'User', 'admin', '1001', ${pinHash}) RETURNING id`
    const [adminRole] = await sql`SELECT id FROM role WHERE slug = 'admin' LIMIT 1`
    if (adminRole) {
      await sql`INSERT INTO user_role_assignment (user_id, role_id) VALUES (${user.id}, ${adminRole.id}) ON CONFLICT DO NOTHING`
    }
    console.log(`  Created admin user: admin@lunarfront.dev / ${adminPassword}`)
  } else {
    const [adminRole] = await sql`SELECT id FROM role WHERE slug = 'admin' LIMIT 1`
    if (adminRole) {
      await sql`DELETE FROM user_role_assignment WHERE user_id = ${adminUser.id}`
      await sql`INSERT INTO user_role_assignment (user_id, role_id) VALUES (${adminUser.id}, ${adminRole.id}) ON CONFLICT DO NOTHING`
    }
  }

  // --- Accounts ---
  const accounts = [
    { name: 'Smith Family', email: 'smith@example.com', phone: '555-0101' },
    { name: 'Johnson Family', email: 'johnson@example.com', phone: '555-0102' },
    { name: 'Lincoln High School', email: 'office@lincoln.edu', phone: '555-0200' },
    { name: 'Garcia Workshop', email: 'garcia@studio.com', phone: '555-0103' },
    { name: 'Mike Thompson', email: 'mike.t@email.com', phone: '555-0104' },
    { name: 'Emily Chen', email: 'emily.chen@email.com', phone: '555-0105' },
    { name: 'Westside Church', email: 'admin@westsidechurch.org', phone: '555-0300' },
    { name: 'Oak Elementary', email: 'office@oakelementary.edu', phone: '555-0201' },
  ]

  const acctIds: Record<string, string> = {}
  for (const a of accounts) {
    const existing = await sql`SELECT id FROM account WHERE name = ${a.name}`
    if (existing.length > 0) {
      acctIds[a.name] = existing[0].id
      continue
    }
    const num = String(Math.floor(100000 + Math.random() * 900000))
    const [row] = await sql`INSERT INTO account (name, email, phone, account_number, billing_mode) VALUES (${a.name}, ${a.email}, ${a.phone}, ${num}, 'consolidated') RETURNING id`
    acctIds[a.name] = row.id
    console.log(`  Account: ${a.name}`)
  }

  // --- Members ---
  const members = [
    { accountName: 'Smith Family', firstName: 'David', lastName: 'Smith', email: 'david@example.com' },
    { accountName: 'Smith Family', firstName: 'Sarah', lastName: 'Smith', email: 'sarah@example.com' },
    { accountName: 'Smith Family', firstName: 'Tommy', lastName: 'Smith', isMinor: true },
    { accountName: 'Johnson Family', firstName: 'Lisa', lastName: 'Johnson', email: 'lisa.j@example.com' },
    { accountName: 'Johnson Family', firstName: 'Jake', lastName: 'Johnson', isMinor: true },
    { accountName: 'Garcia Workshop', firstName: 'Carlos', lastName: 'Garcia', email: 'carlos@studio.com' },
    { accountName: 'Mike Thompson', firstName: 'Mike', lastName: 'Thompson', email: 'mike.t@email.com' },
    { accountName: 'Emily Chen', firstName: 'Emily', lastName: 'Chen', email: 'emily.chen@email.com' },
  ]

  for (const m of members) {
    const acctId = acctIds[m.accountName]
    const existing = await sql`SELECT id FROM member WHERE first_name = ${m.firstName} AND last_name = ${m.lastName}`
    if (existing.length > 0) continue
    const num = String(Math.floor(100000 + Math.random() * 900000))
    await sql`INSERT INTO member (account_id, first_name, last_name, email, member_number, is_minor) VALUES (${acctId}, ${m.firstName}, ${m.lastName}, ${m.email ?? null}, ${num}, ${m.isMinor ?? false})`
    console.log(`  Member: ${m.firstName} ${m.lastName}`)
  }

  // --- Repair Service Templates ---
  const templates = [
    { name: 'Screen Repair', itemCategory: 'Electronics', size: 'Phone', itemType: 'flat_rate', price: '89.00', cost: '25.00' },
    { name: 'Screen Repair', itemCategory: 'Electronics', size: 'Tablet', itemType: 'flat_rate', price: '129.00', cost: '45.00' },
    { name: 'Battery Replacement', itemCategory: 'Electronics', size: 'Phone', itemType: 'flat_rate', price: '59.00', cost: '15.00' },
    { name: 'Battery Replacement', itemCategory: 'Electronics', size: 'Laptop', itemType: 'flat_rate', price: '99.00', cost: '35.00' },
    { name: 'Tune-Up', itemCategory: 'Bicycles', size: 'Standard', itemType: 'flat_rate', price: '65.00', cost: '10.00' },
    { name: 'Brake Adjustment', itemCategory: 'Bicycles', size: null, itemType: 'flat_rate', price: '35.00', cost: '5.00' },
    { name: 'Blade Sharpening', itemCategory: 'Tools', size: null, itemType: 'flat_rate', price: '15.00', cost: '3.00' },
    { name: 'Motor Repair', itemCategory: 'Appliances', size: null, itemType: 'labor', price: '85.00', cost: null },
    { name: 'Zipper Replacement', itemCategory: 'Clothing', size: null, itemType: 'flat_rate', price: '25.00', cost: '5.00' },
    { name: 'Sole Replacement', itemCategory: 'Footwear', size: null, itemType: 'flat_rate', price: '55.00', cost: '15.00' },
    { name: 'Watch Battery', itemCategory: 'Watches', size: null, itemType: 'flat_rate', price: '15.00', cost: '3.00' },
    { name: 'Furniture Refinishing', itemCategory: 'Furniture', size: null, itemType: 'labor', price: '150.00', cost: null },
    { name: 'Diagnostic Check', itemCategory: null, size: null, itemType: 'flat_rate', price: '30.00', cost: '5.00' },
    { name: 'General Cleaning', itemCategory: null, size: null, itemType: 'flat_rate', price: '30.00', cost: '5.00' },
  ]

  for (const t of templates) {
    const existing = await sql`SELECT id FROM repair_service_template WHERE name = ${t.name} AND COALESCE(item_category, '') = ${t.itemCategory ?? ''} AND COALESCE(size, '') = ${t.size ?? ''}`
    if (existing.length > 0) continue
    await sql`INSERT INTO repair_service_template (name, item_category, size, item_type, default_price, default_cost, is_active) VALUES (${t.name}, ${t.itemCategory}, ${t.size}, ${t.itemType}, ${t.price}, ${t.cost}, true)`
    console.log(`  Template: ${t.name} ${t.itemCategory ?? ''} ${t.size ?? ''}`)
  }

  // --- Repair Tickets ---
  const tickets = [
    { customer: 'Mike Thompson', item: 'Samsung Galaxy S24', serial: 'IMEI-354789102', problem: 'Cracked screen, touch not responsive in bottom half', condition: 'good', status: 'in_progress', estimate: '89.00' },
    { customer: 'Emily Chen', item: 'HP LaserJet Pro M404', serial: 'HP-CNB3K12345', problem: 'Paper jam sensor error, won\'t feed from tray 2', condition: 'fair', status: 'pending_approval', estimate: '85.00' },
    { customer: 'David Smith', item: 'Trek Marlin 7 Mountain Bike', serial: null, problem: 'Rear derailleur bent, chain skipping gears', condition: 'fair', status: 'ready', estimate: '65.00' },
    { customer: 'Carlos Garcia', item: 'KitchenAid Stand Mixer KSM150', serial: 'W10807813', problem: 'Motor making grinding noise at low speeds', condition: 'good', status: 'new', estimate: null },
    { customer: 'Lisa Johnson', item: 'Apple MacBook Pro 14"', serial: null, problem: 'Battery draining rapidly, trackpad click intermittent', condition: 'poor', status: 'diagnosing', estimate: null },
    { customer: 'Walk-In Customer', item: 'Leather Work Boots', serial: null, problem: 'Sole separating from upper on both shoes', condition: 'fair', status: 'intake', estimate: null },
  ]

  for (const t of tickets) {
    const existing = await sql`SELECT id FROM repair_ticket WHERE customer_name = ${t.customer} AND problem_description = ${t.problem}`
    if (existing.length > 0) continue
    const num = String(Math.floor(100000 + Math.random() * 900000))
    const acctId = acctIds[t.customer] ?? null
    await sql`INSERT INTO repair_ticket (ticket_number, customer_name, account_id, item_description, serial_number, problem_description, condition_in, status, estimated_cost) VALUES (${num}, ${t.customer}, ${acctId}, ${t.item}, ${t.serial}, ${t.problem}, ${t.condition}, ${t.status}, ${t.estimate})`
    console.log(`  Ticket: ${t.customer} — ${t.item} [${t.status}]`)
  }

  // --- Repair Batch ---
  const batchExists = await sql`SELECT id FROM repair_batch WHERE contact_name = 'Mr. Williams'`
  if (batchExists.length === 0) {
    const batchNum = String(Math.floor(100000 + Math.random() * 900000))
    const schoolId = acctIds['Lincoln High School']
    const [batch] = await sql`INSERT INTO repair_batch (batch_number, account_id, contact_name, contact_phone, contact_email, item_count, notes, status) VALUES (${batchNum}, ${schoolId}, 'Mr. Williams', '555-0210', 'williams@lincoln.edu', 5, 'Annual equipment checkup — 5 items', 'intake') RETURNING id`

    const batchTickets = [
      { item: 'Chromebook #101', problem: 'Screen flickering, hinge loose', condition: 'fair' },
      { item: 'Chromebook #102', problem: 'Keyboard unresponsive, several keys stuck', condition: 'fair' },
      { item: 'Projector — Epson EB-X51', problem: 'Lamp dim, color wheel noise', condition: 'poor' },
      { item: 'Label Printer — Dymo 450', problem: 'Feed mechanism jammed', condition: 'good' },
      { item: 'PA Speaker — JBL EON715', problem: 'Crackling at high volume', condition: 'fair' },
    ]

    for (const bt of batchTickets) {
      const num = String(Math.floor(100000 + Math.random() * 900000))
      await sql`INSERT INTO repair_ticket (ticket_number, customer_name, account_id, repair_batch_id, item_description, problem_description, condition_in, status) VALUES (${num}, 'Lincoln High School', ${schoolId}, ${batch.id}, ${bt.item}, ${bt.problem}, ${bt.condition}, 'new')`
      console.log(`  Batch ticket: ${bt.item}`)
    }
    console.log(`  Batch: Lincoln High School — 5 items`)
  }

  // --- Sample POS Transactions tied to accounts ---
  const [adminUsr] = await sql`SELECT id FROM "user" WHERE email = 'admin@lunarfront.dev'`
  const [mainLoc] = await sql`SELECT id FROM location WHERE name = 'Main Store'`
  if (adminUsr && mainLoc) {
    const existingTxns = await sql`SELECT id FROM transaction WHERE account_id IS NOT NULL LIMIT 1`
    if (existingTxns.length === 0) {
      const salesData = [
        { account: 'Smith Family', items: [
          { desc: 'Violin Strings — Dominant 4/4 Set', qty: 1, price: '59.99', tax: '4.95' },
          { desc: 'Rosin — Pirastro Goldflex', qty: 1, price: '12.00', tax: '0.99' },
        ]},
        { account: 'Smith Family', items: [
          { desc: 'Shoulder Rest — Kun Original 4/4', qty: 1, price: '35.00', tax: '2.89' },
        ]},
        { account: 'Johnson Family', items: [
          { desc: 'Cello Strings — Jargar Superior Set', qty: 1, price: '89.99', tax: '7.42' },
          { desc: 'Bow Grip — Leather Cello/Bass', qty: 2, price: '6.00', tax: '0.99' },
        ]},
        { account: 'Garcia Workshop', items: [
          { desc: 'Bridge — Violin 4/4 Blank', qty: 3, price: '18.00', tax: '4.46' },
          { desc: 'Bow Hair — Mongolian White (hank)', qty: 2, price: '18.00', tax: '2.97' },
          { desc: 'Bow Tip Plate — Violin Ivory-Style', qty: 5, price: '7.00', tax: '2.89' },
        ]},
        { account: 'Emily Chen', items: [
          { desc: 'Violin Strings — Dominant 4/4 Set', qty: 1, price: '59.99', tax: '4.95' },
          { desc: 'Chin Rest — Guarneri Ebony 4/4', qty: 1, price: '28.00', tax: '2.31' },
        ]},
      ]

      for (const sale of salesData) {
        const acctId = acctIds[sale.account]
        if (!acctId) continue
        const subtotal = sale.items.reduce((s, i) => s + parseFloat(i.price) * i.qty, 0)
        const taxTotal = sale.items.reduce((s, i) => s + parseFloat(i.tax), 0)
        const total = Math.round((subtotal + taxTotal) * 100) / 100
        const txnNum = `TXN-SEED-${String(Math.floor(1000 + Math.random() * 9000))}`

        const [txn] = await sql`INSERT INTO transaction (
          transaction_number, transaction_type, status, location_id, account_id, processed_by,
          subtotal, discount_total, tax_total, total, payment_method, completed_at
        ) VALUES (
          ${txnNum}, 'sale', 'completed', ${mainLoc.id}, ${acctId}, ${adminUsr.id},
          ${subtotal.toFixed(2)}, '0.00', ${taxTotal.toFixed(2)}, ${total.toFixed(2)}, 'card_present', NOW()
        ) RETURNING id`

        for (const item of sale.items) {
          const lineTotal = Math.round((parseFloat(item.price) * item.qty + parseFloat(item.tax)) * 100) / 100
          await sql`INSERT INTO transaction_line_item (
            transaction_id, description, qty, unit_price, tax_rate, tax_amount, line_total
          ) VALUES (
            ${txn.id}, ${item.desc}, ${item.qty}, ${item.price}, '0.0825', ${item.tax}, ${lineTotal.toFixed(2)}
          )`
        }
        console.log(`  Transaction: ${txnNum} — ${sale.account} — $${total.toFixed(2)}`)
      }
    }
  }

  console.log('\nDev seed complete!')
  await sql.end()
}

seed().catch((err) => {
  console.error('Seed failed:', err)
  process.exit(1)
})
