import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { useEventGrouping } from '../../composables/useEventGrouping'
import type { StoredEvent } from '../../composables/useEventStorage'

function makeEvent(overrides: Partial<StoredEvent> & { dateTime: string }): StoredEvent {
  return {
    eventToken: `evt-${Math.random().toString(36).slice(2, 8)}`,
    title: 'Test Event',
    ...overrides,
  }
}

describe('useEventGrouping', () => {
  // Fixed "now": Wednesday, 2026-03-11 12:00 local
  const NOW = new Date(2026, 2, 11, 12, 0, 0)

  beforeEach(() => {
    vi.useFakeTimers()
    vi.setSystemTime(NOW)
  })

  afterEach(() => {
    vi.useRealTimers()
  })

  it('returns empty array when no events', () => {
    const sections = useEventGrouping([], NOW)
    expect(sections).toEqual([])
  })

  it('classifies a today event into "today" section', () => {
    const event = makeEvent({ dateTime: '2026-03-11T18:30:00' })
    const sections = useEventGrouping([event], NOW)
    expect(sections).toHaveLength(1)
    expect(sections[0]!.key).toBe('today')
    expect(sections[0]!.label).toBe('Today')
    expect(sections[0]!.dateGroups[0]!.events).toHaveLength(1)
  })

  it('classifies events into all five sections', () => {
    const events = [
      makeEvent({ title: 'Today', dateTime: '2026-03-11T10:00:00' }),
      makeEvent({ title: 'This Week', dateTime: '2026-03-13T10:00:00' }), // Friday (same week)
      makeEvent({ title: 'Next Week', dateTime: '2026-03-16T10:00:00' }), // Monday next week
      makeEvent({ title: 'Later', dateTime: '2026-03-30T10:00:00' }), // far future
      makeEvent({ title: 'Past', dateTime: '2026-03-09T10:00:00' }), // Monday (past)
    ]
    const sections = useEventGrouping(events, NOW)
    expect(sections).toHaveLength(5)
    expect(sections[0]!.key).toBe('today')
    expect(sections[1]!.key).toBe('thisWeek')
    expect(sections[2]!.key).toBe('nextWeek')
    expect(sections[3]!.key).toBe('later')
    expect(sections[4]!.key).toBe('past')
  })

  it('omits empty sections', () => {
    const events = [
      makeEvent({ title: 'Today', dateTime: '2026-03-11T10:00:00' }),
      makeEvent({ title: 'Past', dateTime: '2026-03-01T10:00:00' }),
    ]
    const sections = useEventGrouping(events, NOW)
    expect(sections).toHaveLength(2)
    expect(sections[0]!.key).toBe('today')
    expect(sections[1]!.key).toBe('past')
  })

  it('sorts upcoming events ascending by time', () => {
    const events = [
      makeEvent({ title: 'Later', dateTime: '2026-03-11T20:00:00' }),
      makeEvent({ title: 'Earlier', dateTime: '2026-03-11T08:00:00' }),
    ]
    const sections = useEventGrouping(events, NOW)
    const todayEvents = sections[0]!.dateGroups[0]!.events
    expect(todayEvents[0]!.title).toBe('Earlier')
    expect(todayEvents[1]!.title).toBe('Later')
  })

  it('sorts past events descending by time (most recent first)', () => {
    const events = [
      makeEvent({ title: 'Older', dateTime: '2026-03-01T10:00:00' }),
      makeEvent({ title: 'Newer', dateTime: '2026-03-09T10:00:00' }),
    ]
    const sections = useEventGrouping(events, NOW)
    const pastEvents = sections[0]!.dateGroups
    expect(pastEvents[0]!.events[0]!.title).toBe('Newer')
    expect(pastEvents[1]!.events[0]!.title).toBe('Older')
  })

  it('groups events by date within a section', () => {
    const events = [
      makeEvent({ title: 'Fri AM', dateTime: '2026-03-13T09:00:00' }),
      makeEvent({ title: 'Fri PM', dateTime: '2026-03-13T18:00:00' }),
      makeEvent({ title: 'Sat', dateTime: '2026-03-14T12:00:00' }),
    ]
    const sections = useEventGrouping(events, NOW)
    expect(sections[0]!.key).toBe('thisWeek')
    const dateGroups = sections[0]!.dateGroups
    expect(dateGroups).toHaveLength(2) // Friday and Saturday
    expect(dateGroups[0]!.events).toHaveLength(2) // Two Friday events
    expect(dateGroups[1]!.events).toHaveLength(1) // One Saturday event
  })

  it('sets showSubheader=false for "today" section', () => {
    const event = makeEvent({ dateTime: '2026-03-11T18:00:00' })
    const sections = useEventGrouping([event], NOW)
    expect(sections[0]!.dateGroups[0]!.showSubheader).toBe(false)
  })

  it('sets showSubheader=true for non-today sections', () => {
    const events = [
      makeEvent({ dateTime: '2026-03-13T10:00:00' }), // thisWeek
      makeEvent({ dateTime: '2026-03-30T10:00:00' }), // later (beyond next week)
      makeEvent({ dateTime: '2026-03-01T10:00:00' }), // past
    ]
    const sections = useEventGrouping(events, NOW)
    for (const section of sections) {
      for (const group of section.dateGroups) {
        expect(group.showSubheader).toBe(true)
      }
    }
  })

  it('sets emphasized=true only for "today" section', () => {
    const events = [
      makeEvent({ dateTime: '2026-03-11T18:00:00' }),
      makeEvent({ dateTime: '2026-03-30T10:00:00' }),
    ]
    const sections = useEventGrouping(events, NOW)
    expect(sections[0]!.emphasized).toBe(true) // today
    expect(sections[1]!.emphasized).toBe(false) // later
  })

  it('on Sunday, tomorrow (Monday) goes to "nextWeek" not "thisWeek"', () => {
    // Sunday 2026-03-15
    const sunday = new Date(2026, 2, 15, 12, 0, 0)
    const mondayEvent = makeEvent({ title: 'Monday', dateTime: '2026-03-16T10:00:00' })
    const sections = useEventGrouping([mondayEvent], sunday)
    expect(sections).toHaveLength(1)
    expect(sections[0]!.key).toBe('nextWeek')
  })

  it('on Sunday, today events still appear under "today"', () => {
    const sunday = new Date(2026, 2, 15, 12, 0, 0)
    const todayEvent = makeEvent({ dateTime: '2026-03-15T18:00:00' })
    const sections = useEventGrouping([todayEvent], sunday)
    expect(sections[0]!.key).toBe('today')
  })

  it('dateGroup labels are formatted via Intl', () => {
    const event = makeEvent({ dateTime: '2026-03-13T10:00:00' }) // Friday
    const sections = useEventGrouping([event], NOW)
    const label = sections[0]!.dateGroups[0]!.label
    // The exact format depends on locale, but should contain the day number
    expect(label).toContain('13')
  })
})
