import { afterAll, describe, expect, it } from 'vitest'
import { prisma } from '../setup'
import {
  createTestUser,
  createTestProgram,
  createTestProject,
  cleanupTestData,
  uid,
} from '../helpers'
import { ensureLunchPickForAttendingMember } from '@/server/services/lunch-pick-sync'

const programIds: string[] = []
const userIds: string[] = []

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

async function setupConfirmedAttendee(programId: string) {
  const user = await createTestUser('APPLICANT')
  userIds.push(user.id)
  const project = await createTestProject(programId, {
    title: `pick-sync-${uid()}`,
    competitionCategory: 'STARTUP',
  })
  const confirmation = await prisma.finalistConfirmation.create({
    data: {
      projectId: project.id,
      category: 'STARTUP',
      status: 'CONFIRMED',
      deadline: new Date(Date.now() + 86_400_000),
      token: `tok-${uid()}`,
    },
  })
  const member = await prisma.attendingMember.create({
    data: { confirmationId: confirmation.id, userId: user.id },
  })
  return member
}

describe('ensureLunchPickForAttendingMember', () => {
  it('creates an empty MemberLunchPick when a LunchEvent exists', async () => {
    const program = await createTestProgram({ name: `lunch-sync-${uid()}` })
    programIds.push(program.id)
    await prisma.lunchEvent.create({ data: { programId: program.id } })

    const member = await setupConfirmedAttendee(program.id)
    await ensureLunchPickForAttendingMember(prisma, member.id)

    const pick = await prisma.memberLunchPick.findUnique({
      where: { attendingMemberId: member.id },
    })
    expect(pick).not.toBeNull()
    expect(pick?.dishId).toBeNull()
    expect(pick?.pickedAt).toBeNull()
  })

  it('is idempotent — calling twice does not create a second pick', async () => {
    const program = await createTestProgram({ name: `lunch-sync-${uid()}` })
    programIds.push(program.id)
    await prisma.lunchEvent.create({ data: { programId: program.id } })

    const member = await setupConfirmedAttendee(program.id)
    await ensureLunchPickForAttendingMember(prisma, member.id)
    await ensureLunchPickForAttendingMember(prisma, member.id)

    const picks = await prisma.memberLunchPick.findMany({
      where: { attendingMemberId: member.id },
    })
    expect(picks).toHaveLength(1)
  })

  it('no-ops when no LunchEvent exists for the program', async () => {
    const program = await createTestProgram({ name: `lunch-sync-${uid()}` })
    programIds.push(program.id)
    // Note: no LunchEvent created.

    const member = await setupConfirmedAttendee(program.id)
    await ensureLunchPickForAttendingMember(prisma, member.id)

    const pick = await prisma.memberLunchPick.findUnique({
      where: { attendingMemberId: member.id },
    })
    expect(pick).toBeNull()
  })
})
