import type { Event } from '@/payload-types'

const WEEKDAYS_DE = [
  'Sonntag',
  'Montag',
  'Dienstag',
  'Mittwoch',
  'Donnerstag',
  'Freitag',
  'Samstag',
]

const WEEKDAY_LABEL: Record<string, string> = {
  monday: 'Montag',
  tuesday: 'Dienstag',
  wednesday: 'Mittwoch',
  thursday: 'Donnerstag',
  friday: 'Freitag',
  saturday: 'Samstag',
  sunday: 'Sonntag',
}

const WEEK_OF_MONTH_LABEL: Record<string, string> = {
  first: '1.',
  second: '2.',
  third: '3.',
  fourth: '4.',
  fifth: '5.',
  last: 'letzten',
}

const BERLIN_TZ = 'Europe/Berlin'

const WEEKDAY_EN_TO_INDEX: Record<string, number> = {
  Sunday: 0,
  Monday: 1,
  Tuesday: 2,
  Wednesday: 3,
  Thursday: 4,
  Friday: 5,
  Saturday: 6,
}

const berlinFormatter = new Intl.DateTimeFormat('en-GB', {
  timeZone: BERLIN_TZ,
  hour: '2-digit',
  minute: '2-digit',
  day: 'numeric',
  weekday: 'long',
  hourCycle: 'h23',
})

type BerlinParts = {
  hour: string
  minute: string
  day: number
  weekdayIndex: number
}

const getBerlinParts = (d: Date): BerlinParts => {
  const parts = berlinFormatter.formatToParts(d)
  const get = (type: string) =>
    parts.find((p) => p.type === type)?.value ?? ''
  return {
    hour: get('hour'),
    minute: get('minute'),
    day: Number(get('day')),
    weekdayIndex: WEEKDAY_EN_TO_INDEX[get('weekday')] ?? 0,
  }
}

// Match the clamp in eventRecurrence.ts so the label on the Event page
// agrees with the rule the generator actually produces.
const weekOfMonthN = (dayOfMonth: number): number =>
  Math.min(Math.ceil(dayOfMonth / 7), 4)

const formatTime = (p: BerlinParts): string => `${p.hour}:${p.minute}`

const withTime = (description: string, p: BerlinParts | null): string =>
  p ? `${description} um ${formatTime(p)} Uhr` : description

type RecurrenceRule = NonNullable<Event['recurrenceRules']>[number]

const describeCustomRule = (rule: RecurrenceRule): string | null => {
  switch (rule.frequency) {
    case 'daily':
      return 'Täglich'
    case 'weekly': {
      const weekday = rule.weekday ? WEEKDAY_LABEL[rule.weekday] : null
      return weekday ? `Jeden ${weekday}` : null
    }
    case 'monthlyByDate':
      return typeof rule.dayOfMonth === 'number'
        ? `Am ${rule.dayOfMonth}. jedes Monats`
        : null
    case 'monthlyByWeekday': {
      const weekday = rule.weekday ? WEEKDAY_LABEL[rule.weekday] : null
      const week = rule.weekOfMonth ? WEEK_OF_MONTH_LABEL[rule.weekOfMonth] : null
      return weekday && week ? `Am ${week} ${weekday} jedes Monats` : null
    }
    default:
      return null
  }
}

/**
 * Human-readable German description of an event's recurrence. Returns
 * `undefined` for one-shot events (recurrenceType = 'none' / missing) so
 * callers can fall back to a regular date.
 */
export const describeRecurrence = (
  event: Pick<Event, 'recurrenceType' | 'recurrenceRules' | 'date'>,
): string | undefined => {
  const type = event.recurrenceType
  if (!type || type === 'none') return undefined

  const parsed = event.date ? new Date(event.date) : null
  const d = parsed && !Number.isNaN(parsed.getTime()) ? parsed : null
  const p = d ? getBerlinParts(d) : null

  switch (type) {
    case 'daily':
      return withTime('Täglich', p)
    case 'weekly':
      return withTime(p ? `Jeden ${WEEKDAYS_DE[p.weekdayIndex]}` : 'Wöchentlich', p)
    case 'biweekly':
      return withTime(
        p ? `Alle 2 Wochen, ${WEEKDAYS_DE[p.weekdayIndex]}` : 'Alle 2 Wochen',
        p,
      )
    case 'monthlyByDate':
      return withTime(p ? `Monatlich am ${p.day}.` : 'Monatlich', p)
    case 'monthlyByWeekday':
      return withTime(
        p
          ? `Monatlich am ${weekOfMonthN(p.day)}. ${WEEKDAYS_DE[p.weekdayIndex]}`
          : 'Monatlich',
        p,
      )
    case 'custom': {
      const rules = event.recurrenceRules ?? []
      const parts = rules
        .map(describeCustomRule)
        .filter((part): part is string => Boolean(part))
      if (parts.length === 0) return withTime('Benutzerdefiniert', p)
      return withTime(parts.join(' · '), p)
    }
    default:
      return undefined
  }
}
