import type { PrismaClient } from '@prisma/client'

/**
 * Build the lunch manifest payload for a program. Used by both the
 * admin manifest UI and the recap aggregation.
 *
 * Filters attending members to FinalistConfirmation.status === 'CONFIRMED'.
 * Externals are unconditionally included (admin curates them directly).
 */
export async function buildManifest(prisma: PrismaClient, programId: string) {
  const event = await prisma.lunchEvent.findUnique({
    where: { programId },
    include: { dishes: { orderBy: [{ sortOrder: 'asc' }, { createdAt: 'asc' }] } },
  })
  if (!event) {
    return {
      event: null,
      members: [] as ManifestMember[],
      externals: [] as ManifestExternal[],
      dishes: [],
      summary: { total: 0, picked: 0, missing: 0 },
    }
  }
  const ams = await prisma.attendingMember.findMany({
    where: {
      confirmation: { project: { programId }, status: 'CONFIRMED' },
    },
    include: {
      user: { select: { id: true, name: true, email: true } },
      confirmation: { include: { project: { select: { id: true, title: true } } } },
      lunchPick: { include: { dish: true } },
    },
  })
  const externals = await prisma.externalAttendee.findMany({
    where: { lunchEventId: event.id },
    include: {
      project: { select: { id: true, title: true } },
      dish: true,
    },
    orderBy: { createdAt: 'asc' },
  })
  const members: ManifestMember[] = ams.map((am) => ({
    kind: 'MEMBER',
    attendingMemberId: am.id,
    userId: am.user.id,
    name: am.user.name ?? am.user.email,
    email: am.user.email,
    project: { id: am.confirmation.project.id, name: am.confirmation.project.title },
    dish: am.lunchPick?.dish ?? null,
    allergens: am.lunchPick?.allergens ?? [],
    allergenOther: am.lunchPick?.allergenOther ?? null,
    pickedAt: am.lunchPick?.pickedAt ?? null,
  }))
  const ext: ManifestExternal[] = externals.map((e) => ({
    kind: 'EXTERNAL',
    externalId: e.id,
    name: e.name,
    email: e.email,
    project: e.project ? { id: e.project.id, name: e.project.title } : null,
    roleNote: e.roleNote,
    dish: e.dish,
    allergens: e.allergens,
    allergenOther: e.allergenOther,
    pickedAt: e.dishId ? e.updatedAt : null,
  }))
  const total = members.length + ext.length
  const picked = members.filter((m) => m.dish).length + ext.filter((e) => e.dish).length
  return {
    event,
    dishes: event.dishes,
    members,
    externals: ext,
    summary: { total, picked, missing: total - picked },
  }
}

/**
 * Build the recap email payload — manifest plus aggregate counts of dishes,
 * dietary tags, and allergens.
 */
export async function buildRecapPayload(prisma: PrismaClient, programId: string) {
  const m = await buildManifest(prisma, programId)
  const dishCounts: Record<string, number> = {}
  const dietaryCounts: Record<string, number> = {}
  const allergenCounts: Record<string, number> = {}
  const allRows: Array<{
    dish: { name: string; dietaryTags: string[] } | null
    allergens: string[]
  }> = [
    ...m.members.map((r) => ({ dish: r.dish, allergens: r.allergens })),
    ...m.externals.map((r) => ({ dish: r.dish, allergens: r.allergens })),
  ]
  for (const row of allRows) {
    if (row.dish) {
      dishCounts[row.dish.name] = (dishCounts[row.dish.name] ?? 0) + 1
      for (const tag of row.dish.dietaryTags) {
        dietaryCounts[tag] = (dietaryCounts[tag] ?? 0) + 1
      }
    }
    for (const a of row.allergens) {
      allergenCounts[a] = (allergenCounts[a] ?? 0) + 1
    }
  }
  return {
    event: m.event,
    members: m.members,
    externals: m.externals,
    dishCounts,
    dietaryCounts,
    allergenCounts,
    summary: m.summary,
  }
}

// ─── Types ──────────────────────────────────────────────────────────────────

export type ManifestMember = {
  kind: 'MEMBER'
  attendingMemberId: string
  userId: string
  name: string
  email: string
  project: { id: string; name: string }
  dish: { id: string; name: string; dietaryTags: string[] } | null
  allergens: string[]
  allergenOther: string | null
  pickedAt: Date | null
}

export type ManifestExternal = {
  kind: 'EXTERNAL'
  externalId: string
  name: string
  email: string | null
  project: { id: string; name: string } | null
  roleNote: string | null
  dish: { id: string; name: string; dietaryTags: string[] } | null
  allergens: string[]
  allergenOther: string | null
  pickedAt: Date | null
}
