import type { StoredEvent } from './useEventStorage'

export type SectionKey = 'today' | 'thisWeek' | 'nextWeek' | 'later' | 'past'

export interface DateGroup {
  dateKey: string
  label: string
  events: StoredEvent[]
  showSubheader: boolean
}

export interface EventSection {
  key: SectionKey
  label: string
  dateGroups: DateGroup[]
  emphasized: boolean
}

const SECTION_ORDER: SectionKey[] = ['today', 'thisWeek', 'nextWeek', 'later', 'past']

const SECTION_LABELS: Record<SectionKey, string> = {
  today: 'Today',
  thisWeek: 'This Week',
  nextWeek: 'Next Week',
  later: 'Later',
  past: 'Past',
}

function startOfDay(date: Date): Date {
  const d = new Date(date)
  d.setHours(0, 0, 0, 0)
  return d
}

function endOfDay(date: Date): Date {
  const d = new Date(date)
  d.setHours(23, 59, 59, 999)
  return d
}

function endOfWeek(date: Date): Date {
  const d = new Date(date)
  const dayOfWeek = d.getDay() // 0=Sun, 1=Mon, ..., 6=Sat
  // ISO week: Monday is first day. End of week = Sunday.
  // If today is Sunday (0), end of week is today.
  // Otherwise, days until Sunday = 7 - dayOfWeek
  const daysUntilSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek
  d.setDate(d.getDate() + daysUntilSunday)
  return endOfDay(d)
}

function endOfNextWeek(date: Date): Date {
  const thisWeekEnd = endOfWeek(date)
  const d = new Date(thisWeekEnd)
  d.setDate(d.getDate() + 7)
  return endOfDay(d)
}

function toDateKey(date: Date): string {
  const y = date.getFullYear()
  const m = String(date.getMonth() + 1).padStart(2, '0')
  const d = String(date.getDate()).padStart(2, '0')
  return `${y}-${m}-${d}`
}

function formatDateLabel(date: Date): string {
  return new Intl.DateTimeFormat(undefined, {
    weekday: 'short',
    day: 'numeric',
    month: 'short',
  }).format(date)
}

function classifyEvent(eventDate: Date, todayStart: Date, todayEnd: Date, weekEnd: Date, nextWeekEnd: Date): SectionKey {
  if (eventDate < todayStart) return 'past'
  if (eventDate <= todayEnd) return 'today'
  if (eventDate <= weekEnd) return 'thisWeek'
  if (eventDate <= nextWeekEnd) return 'nextWeek'
  return 'later'
}

export function useEventGrouping(events: StoredEvent[], now: Date = new Date()): EventSection[] {
  const todayStart = startOfDay(now)
  const todayEnd = endOfDay(now)
  const weekEnd = endOfWeek(now)
  const nextWeekEnd = endOfNextWeek(now)

  // Classify events into sections
  const buckets: Record<SectionKey, StoredEvent[]> = {
    today: [],
    thisWeek: [],
    nextWeek: [],
    later: [],
    past: [],
  }

  for (const event of events) {
    const eventDate = new Date(event.dateTime)
    const section = classifyEvent(eventDate, todayStart, todayEnd, weekEnd, nextWeekEnd)
    buckets[section].push(event)
  }

  // Build sections
  const sections: EventSection[] = []

  for (const key of SECTION_ORDER) {
    const sectionEvents = buckets[key]
    if (sectionEvents.length === 0) continue

    // Sort events
    const ascending = key !== 'past'
    sectionEvents.sort((a, b) => {
      const diff = new Date(a.dateTime).getTime() - new Date(b.dateTime).getTime()
      return ascending ? diff : -diff
    })

    // Group by date
    const dateGroupMap = new Map<string, StoredEvent[]>()
    for (const event of sectionEvents) {
      const dateKey = toDateKey(new Date(event.dateTime))
      const group = dateGroupMap.get(dateKey)
      if (group) {
        group.push(event)
      } else {
        dateGroupMap.set(dateKey, [event])
      }
    }

    // Convert to DateGroup array (order preserved from sorted events)
    const dateGroups: DateGroup[] = []
    for (const [dateKey, groupEvents] of dateGroupMap) {
      dateGroups.push({
        dateKey,
        label: formatDateLabel(new Date(groupEvents[0]!.dateTime)),
        events: groupEvents,
        showSubheader: key !== 'today',
      })
    }

    sections.push({
      key,
      label: SECTION_LABELS[key],
      dateGroups,
      emphasized: key === 'today',
    })
  }

  return sections
}
