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

describe('logistics.listConfirmations', () => {
  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 cleanupTestData(programId, [])
    }
    if (userIds.length > 0) {
      await prisma.user.deleteMany({ where: { id: { in: userIds } } })
    }
  })

  it('returns every confirmation in a program with project + attendee count', async () => {
    const admin = await createTestUser('SUPER_ADMIN')
    userIds.push(admin.id)
    const program = await createTestProgram({ name: `confs-list-${uid()}` })
    programIds.push(program.id)

    // Two confirmations: one CONFIRMED with 2 attendees, one PENDING
    const lead1 = await prisma.user.create({
      data: {
        id: uid('user'),
        email: `l1_${uid()}@test.local`,
        name: 'L1',
        role: 'APPLICANT',
        roles: ['APPLICANT'],
        status: 'ACTIVE',
      },
    })
    const teammate = await prisma.user.create({
      data: {
        id: uid('user'),
        email: `tm_${uid()}@test.local`,
        name: 'TM',
        role: 'APPLICANT',
        roles: ['APPLICANT'],
        status: 'ACTIVE',
      },
    })
    userIds.push(lead1.id, teammate.id)

    const projectA = await createTestProject(program.id, {
      title: 'A',
      competitionCategory: 'STARTUP',
    })
    const projectB = await createTestProject(program.id, {
      title: 'B',
      competitionCategory: 'STARTUP',
    })

    const confirmedRow = await prisma.finalistConfirmation.create({
      data: {
        projectId: projectA.id,
        category: 'STARTUP',
        status: 'CONFIRMED',
        deadline: new Date(Date.now() + 86400000),
        token: `tok_${uid()}`,
        confirmedAt: new Date(),
      },
    })
    await prisma.attendingMember.createMany({
      data: [
        { confirmationId: confirmedRow.id, userId: lead1.id, needsVisa: false },
        { confirmationId: confirmedRow.id, userId: teammate.id, needsVisa: true },
      ],
    })

    await prisma.finalistConfirmation.create({
      data: {
        projectId: projectB.id,
        category: 'STARTUP',
        status: 'PENDING',
        deadline: new Date(Date.now() + 86400000),
        token: `tok_${uid()}`,
      },
    })

    const caller = createCaller(logisticsRouter, {
      id: admin.id,
      email: admin.email,
      role: 'SUPER_ADMIN',
    })
    const rows = await caller.listConfirmations({ programId: program.id })
    expect(rows).toHaveLength(2)

    const byTitle = Object.fromEntries(
      rows.map((r: (typeof rows)[number]) => [r.project.title, r]),
    )
    expect(byTitle['A'].status).toBe('CONFIRMED')
    expect(byTitle['A'].attendeeCount).toBe(2)
    expect(byTitle['B'].status).toBe('PENDING')
    expect(byTitle['B'].attendeeCount).toBe(0)
  })

  it('sorts PENDING first then by deadline ascending', async () => {
    const admin = await createTestUser('SUPER_ADMIN')
    userIds.push(admin.id)
    const program = await createTestProgram({ name: `confs-sort-${uid()}` })
    programIds.push(program.id)

    const projects = await Promise.all([
      createTestProject(program.id, { title: 'Old confirmed', competitionCategory: 'STARTUP' }),
      createTestProject(program.id, { title: 'New pending', competitionCategory: 'STARTUP' }),
      createTestProject(program.id, { title: 'Old pending', competitionCategory: 'STARTUP' }),
    ])
    await prisma.finalistConfirmation.create({
      data: {
        projectId: projects[0].id,
        category: 'STARTUP',
        status: 'CONFIRMED',
        deadline: new Date(Date.now() + 1000),
        token: `tok_${uid()}`,
        confirmedAt: new Date(),
      },
    })
    await prisma.finalistConfirmation.create({
      data: {
        projectId: projects[1].id,
        category: 'STARTUP',
        status: 'PENDING',
        deadline: new Date(Date.now() + 200_000),
        token: `tok_${uid()}`,
      },
    })
    await prisma.finalistConfirmation.create({
      data: {
        projectId: projects[2].id,
        category: 'STARTUP',
        status: 'PENDING',
        deadline: new Date(Date.now() + 100_000),
        token: `tok_${uid()}`,
      },
    })

    const caller = createCaller(logisticsRouter, {
      id: admin.id,
      email: admin.email,
      role: 'SUPER_ADMIN',
    })
    const rows = await caller.listConfirmations({ programId: program.id })
    // PENDING ones first (sorted by deadline asc), then CONFIRMED
    expect(rows.map((r: (typeof rows)[number]) => r.project.title)).toEqual([
      'Old pending',
      'New pending',
      'Old confirmed',
    ])
  })
})
