/**
 * ZeptoMail webhook payload → delivery events (Pilot Invitation Manager,
 * 2026-09-15). ZeptoMail posts JSON with `event_name` (e.g. "hardbounce",
 * "softbounce") and `event_message[]` entries carrying the recipient in
 * `event_data[].details[].bounced_recipient` and/or
 * `email_info.to[].email_address.address`. The walk below is tolerant of
 * shape differences: it collects every event name and every recipient
 * address it can find, so a payload variant never drops a bounce silently.
 * Pure — tested without I/O.
 */

export type DeliveryEventKind = 'hardbounce' | 'softbounce' | 'complaint' | 'other'

export interface DeliveryEvent {
  kind: DeliveryEventKind
  raw_event: string
  emails: string[]
  reason: string | null
}

export function classifyEventName(name: string): DeliveryEventKind {
  const n = name.toLowerCase().replace(/[^a-z]/g, '')
  if (n.includes('hard')) return 'hardbounce'
  if (n.includes('soft')) return 'softbounce'
  if (n.includes('complaint') || n.includes('spam') || n.includes('abuse')) return 'complaint'
  if (n.includes('bounce')) return 'hardbounce'
  return 'other'
}

export function parseZeptoMailWebhook(payload: unknown): DeliveryEvent[] {
  if (!payload || typeof payload !== 'object') return []
  const root = payload as Record<string, unknown>
  const topNames = asStringArray(root.event_name)
  const messages = Array.isArray(root.event_message) ? (root.event_message as unknown[]) : [root]
  const out: DeliveryEvent[] = []
  for (const m of messages) {
    if (!m || typeof m !== 'object') continue
    const msg = m as Record<string, unknown>
    const eventData = Array.isArray(msg.event_data) ? (msg.event_data as Record<string, unknown>[]) : []
    const names = [...topNames, ...eventData.flatMap((d) => asStringArray(d.event_name))]
    const name = names[0] ?? 'unknown'
    const emails = new Set<string>()
    let reason: string | null = null
    for (const d of eventData) {
      const details = Array.isArray(d.details) ? (d.details as Record<string, unknown>[]) : []
      for (const det of details) {
        for (const key of ['bounced_recipient', 'recipient', 'email_address', 'address']) {
          const v = det[key]
          if (typeof v === 'string' && v.includes('@')) emails.add(v.trim().toLowerCase())
        }
        const r = det.reason ?? det.diagnostic_message ?? det.bounce_reason
        if (typeof r === 'string' && !reason) reason = r
      }
    }
    const info = (msg.email_info ?? {}) as Record<string, unknown>
    for (const t of Array.isArray(info.to) ? (info.to as Record<string, unknown>[]) : []) {
      const ea = (t.email_address ?? t) as Record<string, unknown>
      if (typeof ea.address === 'string' && ea.address.includes('@')) emails.add(ea.address.trim().toLowerCase())
    }
    if (emails.size === 0) continue
    out.push({ kind: classifyEventName(name), raw_event: name, emails: [...emails], reason })
  }
  return out
}

function asStringArray(v: unknown): string[] {
  if (typeof v === 'string') return [v]
  if (Array.isArray(v)) return v.filter((x): x is string => typeof x === 'string')
  return []
}
