import { afterAll, describe, expect, it } from 'vitest'
import { prisma, createCaller } from '../setup'
import {
  createTestUser,
  createTestProgram,
  createTestProject,
  cleanupTestData,
  uid,
} from '../helpers'
import { finalistRouter } from '../../src/server/routers/finalist'

describe('finalist.setQuota', () => {
  const programIds: string[] = []
  const userIds: string[] = []

  afterAll(async () => {
    for (const programId of programIds) {
      await prisma.attendingMember.deleteMany({
        where: { confirmation: { project: { programId } } },
      })
      await prisma.finalistConfirmation.deleteMany({ where: { project: { programId } } })
      await prisma.waitlistEntry.deleteMany({ where: { programId } })
      await prisma.finalistSlotQuota.deleteMany({ where: { programId } })
      await cleanupTestData(programId, [])
    }
    if (userIds.length > 0) {
      await prisma.user.deleteMany({ where: { id: { in: userIds } } })
    }
  })

  it('creates a new quota row', async () => {
    const admin = await createTestUser('SUPER_ADMIN')
    userIds.push(admin.id)
    const program = await createTestProgram({ name: `quota-${uid()}` })
    programIds.push(program.id)
    const caller = createCaller(finalistRouter, {
      id: admin.id,
      email: admin.email,
      role: 'SUPER_ADMIN',
    })
    const q = await caller.setQuota({
      programId: program.id,
      category: 'STARTUP',
      quota: 3,
    })
    expect(q.quota).toBe(3)
    expect(q.category).toBe('STARTUP')
  })

  it('updates an existing quota row', async () => {
    const admin = await createTestUser('SUPER_ADMIN')
    userIds.push(admin.id)
    const program = await createTestProgram({ name: `quota-update-${uid()}` })
    programIds.push(program.id)
    await prisma.finalistSlotQuota.create({
      data: { programId: program.id, category: 'STARTUP', quota: 3 },
    })
    const caller = createCaller(finalistRouter, {
      id: admin.id,
      email: admin.email,
      role: 'SUPER_ADMIN',
    })
    const q = await caller.setQuota({ programId: program.id, category: 'STARTUP', quota: 5 })
    expect(q.quota).toBe(5)
  })

  it('blocks decreasing quota below confirmed count', async () => {
    const admin = await createTestUser('SUPER_ADMIN')
    userIds.push(admin.id)
    const program = await createTestProgram({ name: `quota-block-${uid()}` })
    programIds.push(program.id)
    // 3 confirmed Startup finalists
    for (let i = 0; i < 3; i++) {
      const project = await createTestProject(program.id, {
        title: `Confirmed ${i}`,
        competitionCategory: 'STARTUP',
      })
      await prisma.finalistConfirmation.create({
        data: {
          projectId: project.id,
          category: 'STARTUP',
          status: 'CONFIRMED',
          deadline: new Date(Date.now() + 86400000),
          token: `tok_block_${uid()}_${i}`,
          confirmedAt: new Date(),
        },
      })
    }
    await prisma.finalistSlotQuota.create({
      data: { programId: program.id, category: 'STARTUP', quota: 3 },
    })
    const caller = createCaller(finalistRouter, {
      id: admin.id,
      email: admin.email,
      role: 'SUPER_ADMIN',
    })
    await expect(
      caller.setQuota({ programId: program.id, category: 'STARTUP', quota: 2 }),
    ).rejects.toThrow(/3 teams have already confirmed/i)
  })

  it('allows decreasing if confirmed count already fits', async () => {
    const admin = await createTestUser('SUPER_ADMIN')
    userIds.push(admin.id)
    const program = await createTestProgram({ name: `quota-decrease-${uid()}` })
    programIds.push(program.id)
    const project = await createTestProject(program.id, {
      title: 'One',
      competitionCategory: 'STARTUP',
    })
    await prisma.finalistConfirmation.create({
      data: {
        projectId: project.id,
        category: 'STARTUP',
        status: 'CONFIRMED',
        deadline: new Date(Date.now() + 86400000),
        token: `tok_dec_${uid()}`,
        confirmedAt: new Date(),
      },
    })
    await prisma.finalistSlotQuota.create({
      data: { programId: program.id, category: 'STARTUP', quota: 3 },
    })
    const caller = createCaller(finalistRouter, {
      id: admin.id,
      email: admin.email,
      role: 'SUPER_ADMIN',
    })
    const q = await caller.setQuota({ programId: program.id, category: 'STARTUP', quota: 1 })
    expect(q.quota).toBe(1)
  })

  it('only counts CONFIRMED status, not PENDING/DECLINED/EXPIRED', async () => {
    const admin = await createTestUser('SUPER_ADMIN')
    userIds.push(admin.id)
    const program = await createTestProgram({ name: `quota-status-${uid()}` })
    programIds.push(program.id)
    const statuses = ['PENDING', 'DECLINED', 'EXPIRED'] as const
    for (let i = 0; i < statuses.length; i++) {
      const project = await createTestProject(program.id, {
        title: `Status ${statuses[i]}`,
        competitionCategory: 'STARTUP',
      })
      await prisma.finalistConfirmation.create({
        data: {
          projectId: project.id,
          category: 'STARTUP',
          status: statuses[i],
          deadline: new Date(Date.now() + 86400000),
          token: `tok_status_${uid()}_${i}`,
        },
      })
    }
    const caller = createCaller(finalistRouter, {
      id: admin.id,
      email: admin.email,
      role: 'SUPER_ADMIN',
    })
    // 0 confirmed → quota of 0 should succeed
    const q = await caller.setQuota({ programId: program.id, category: 'STARTUP', quota: 0 })
    expect(q.quota).toBe(0)
  })
})
