// Seed bron: docs/scrum4me-backlog.md → prisma/seed-data/parse-backlog.ts.
// Pas alléén de backlog-markdown aan als je seed-data wilt wijzigen, niet deze file.
import { PrismaClient } from '@prisma/client'
import * as dotenv from 'dotenv'
import * as path from 'path'
import * as bcrypt from 'bcryptjs'
import { loadBacklog } from './seed-data/parse-backlog'

// Load env from project root
const root = path.resolve(__dirname, '..')
dotenv.config({ path: path.join(root, '.env.local'), override: true })
dotenv.config({ path: path.join(root, '.env') })

let prisma: PrismaClient

async function main() {
  const url = process.env.DATABASE_URL
  if (!url) throw new Error('DATABASE_URL is not set. Check .env.local')

  const { Pool } = await import('pg')
  const { PrismaPg } = await import('@prisma/adapter-pg')
  const pool = new Pool({ connectionString: url })
  const adapter = new PrismaPg(pool)
  prisma = new PrismaClient({ adapter })

  console.log('Seeding database...')

  // Create main demo user
  const demoHash = await bcrypt.hash('demo1234', 12)
  const demo = await prisma.user.upsert({
    where: { username: 'demo' },
    update: {},
    create: {
      username: 'demo',
      password_hash: demoHash,
      is_demo: true,
      roles: {
        create: [
          { role: 'PRODUCT_OWNER' },
          { role: 'DEVELOPER' },
        ],
      },
    },
  })

  console.log(`Demo user: ${demo.username} (id: ${demo.id})`)

  // Create seed user for the product
  const userHash = await bcrypt.hash('scrum4me123', 12)
  const user = await prisma.user.upsert({
    where: { username: 'lars' },
    update: {},
    create: {
      username: 'lars',
      password_hash: userHash,
      is_demo: false,
      roles: {
        create: [
          { role: 'PRODUCT_OWNER' },
          { role: 'SCRUM_MASTER' },
          { role: 'DEVELOPER' },
        ],
      },
    },
  })

  console.log(`Main user: ${user.username} (id: ${user.id})`)

  // Create tester user for cross-user isolation tests (no products)
  const testerHash = await bcrypt.hash('tester123', 12)
  const tester = await prisma.user.upsert({
    where: { username: 'tester' },
    update: {},
    create: {
      username: 'tester',
      password_hash: testerHash,
      is_demo: false,
      roles: {
        create: [
          { role: 'PRODUCT_OWNER' },
          { role: 'DEVELOPER' },
        ],
      },
    },
  })

  console.log(`Tester user: ${tester.username} (id: ${tester.id})`)

  // Reset demo product data — delete in dependency order to avoid FK violations
  const existingProducts = await prisma.product.findMany({ where: { user_id: demo.id }, select: { id: true } })
  for (const p of existingProducts) {
    // Stories reference product_id directly (no cascade), so delete PBIs first (cascades to stories via pbi_id)
    const existingPbis = await prisma.pbi.findMany({ where: { product_id: p.id }, select: { id: true } })
    for (const pbi of existingPbis) {
      await prisma.story.deleteMany({ where: { pbi_id: pbi.id } })
    }
    await prisma.pbi.deleteMany({ where: { product_id: p.id } })
    await prisma.sprint.deleteMany({ where: { product_id: p.id } })
  }
  await prisma.product.deleteMany({ where: { user_id: demo.id } })

  const product = await prisma.product.create({
    data: {
      user_id: demo.id,
      name: 'Scrum4Me',
      code: 'SCRUM4ME',
      description:
        'Een desktop-first fullstack webapplicatie voor solo developers en kleine Scrum Teams die meerdere softwareprojecten parallel beheren.',
      repo_url: 'https://github.com/madhura68/Scrum4Me',
      definition_of_done:
        'Code is geïmplementeerd, type-checked, getest, gedocumenteerd in code en docs, en gedeployed naar Vercel zonder regressies.',
      archived: false,
    },
  })

  console.log(`Product created: ${product.name} (id: ${product.id}, owner: demo)`)

  await prisma.productMember.create({
    data: { product_id: product.id, user_id: user.id },
  })
  console.log(`  Added ${user.username} as member of ${product.name}`)

  const milestones = await loadBacklog(root)
  console.log(`Loaded backlog: ${milestones.length} milestones, ${milestones.reduce((acc, m) => acc + m.stories.length, 0)} stories`)

  let productTaskCounter = 0
  let sprintCounter = 0
  for (const ms of milestones) {
    const pbi = await prisma.pbi.create({
      data: {
        product_id: product.id,
        code: ms.key,
        title: ms.title,
        description: ms.goal,
        priority: ms.priority,
        sort_order: ms.sort_order,
      },
    })

    const sprint = await prisma.sprint.create({
      data: {
        product_id: product.id,
        code: `SP-${++sprintCounter}`,
        sprint_goal: `${ms.key} — ${ms.goal}`,
        status: ms.sprint_status,
      },
    })

    console.log(
      `  PBI ${pbi.title} (priority ${pbi.priority}) + sprint ${ms.sprint_status}`,
    )

    // M3.5 = de huidige sprint die nog moet beginnen — alle stories en taken
    // worden geforceerd op niet-uitgevoerd, ongeacht de checkbox in de backlog.
    const forceOpen = ms.key === 'M3.5'

    for (const s of ms.stories) {
      const isActive = ms.sprint_status === 'OPEN'
      const effectivelyDone = !forceOpen && s.status === 'DONE'
      const inSprint = isActive || effectivelyDone
      const storyStatus = effectivelyDone ? 'DONE' : isActive ? 'IN_SPRINT' : 'OPEN'
      const storySummary = s.tasks.map((t) => t.title).join('; ')

      const story = await prisma.story.create({
        data: {
          pbi_id: pbi.id,
          product_id: product.id,
          sprint_id: inSprint ? sprint.id : null,
          code: s.ref,
          title: s.title,
          description: storySummary,
          acceptance_criteria: s.acceptance_criteria,
          priority: ms.priority,
          sort_order: s.sort_order,
          status: storyStatus,
        },
      })

      for (const t of s.tasks) {
        productTaskCounter += 1
        await prisma.task.create({
          data: {
            story_id: story.id,
            product_id: product.id,
            sprint_id: inSprint ? sprint.id : null,
            code: `T-${productTaskCounter}`,
            title: t.title,
            description: t.description,
            priority: ms.priority,
            sort_order: t.sort_order,
            status: effectivelyDone ? 'DONE' : 'TO_DO',
          },
        })
      }
    }
  }

  const modelPrices = [
    {
      model_id: 'claude-opus-4-7',
      input_price_per_1m: 15.0,
      output_price_per_1m: 75.0,
      cache_read_price_per_1m: 1.5,
      cache_write_price_per_1m: 18.75,
    },
    {
      model_id: 'claude-sonnet-4-6',
      input_price_per_1m: 3.0,
      output_price_per_1m: 15.0,
      cache_read_price_per_1m: 0.3,
      cache_write_price_per_1m: 3.75,
    },
    {
      model_id: 'claude-haiku-4-5-20251001',
      input_price_per_1m: 0.8,
      output_price_per_1m: 4.0,
      cache_read_price_per_1m: 0.08,
      cache_write_price_per_1m: 1.0,
    },
  ]

  for (const mp of modelPrices) {
    await prisma.modelPrice.upsert({
      where: { model_id: mp.model_id },
      update: mp,
      create: mp,
    })
    console.log(`  ModelPrice upserted: ${mp.model_id}`)
  }

  console.log('\nSeeding complete!')
  console.log('Demo user:  username=demo     password=demo1234')
  console.log('Main user:  username=lars     password=scrum4me123')
}

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