import { describe, it, expect } from 'vitest'
import { generateIcs } from '../useIcalDownload'

describe('generateIcs', () => {
  const baseEvent = {
    eventToken: '550e8400-e29b-41d4-a716-446655440000',
    title: 'Sommerfest am See',
    dateTime: '2026-07-15T18:00:00+02:00',
    location: 'Stadtpark Berlin',
    description: 'Bring your own drinks',
  }

  it('generates valid VCALENDAR wrapper', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toMatch(/^BEGIN:VCALENDAR\r\n/)
    expect(ics).toMatch(/\r\nEND:VCALENDAR\r\n$/)
  })

  it('includes VERSION and PRODID', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('VERSION:2.0\r\n')
    expect(ics).toContain('PRODID:-//fete//EN\r\n')
  })

  it('generates valid VEVENT block', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('BEGIN:VEVENT\r\n')
    expect(ics).toContain('END:VEVENT\r\n')
  })

  it('sets UID from eventToken', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('UID:550e8400-e29b-41d4-a716-446655440000@fete\r\n')
  })

  it('sets DTSTART in UTC format', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('DTSTART:20260715T160000Z\r\n')
  })

  it('does NOT include DTEND or DURATION', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).not.toContain('DTEND')
    expect(ics).not.toContain('DURATION')
  })

  it('sets SUMMARY from title', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('SUMMARY:Sommerfest am See\r\n')
  })

  it('sets LOCATION when present', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('LOCATION:Stadtpark Berlin\r\n')
  })

  it('sets DESCRIPTION when present', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('DESCRIPTION:Bring your own drinks\r\n')
  })

  it('omits LOCATION when not provided', () => {
    const { location: _location, ...noLocation } = baseEvent
    const ics = generateIcs(noLocation)
    expect(ics).not.toContain('LOCATION')
  })

  it('omits DESCRIPTION when not provided', () => {
    const { description: _description, ...noDesc } = baseEvent
    const ics = generateIcs(noDesc)
    expect(ics).not.toContain('DESCRIPTION')
  })

  it('includes SEQUENCE:0', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toContain('SEQUENCE:0\r\n')
  })

  it('includes DTSTAMP in UTC format', () => {
    const ics = generateIcs(baseEvent)
    expect(ics).toMatch(/DTSTAMP:\d{8}T\d{6}Z\r\n/)
  })

  it('escapes commas in text fields', () => {
    const ics = generateIcs({ ...baseEvent, title: 'Hello, World' })
    expect(ics).toContain('SUMMARY:Hello\\, World\r\n')
  })

  it('escapes semicolons in text fields', () => {
    const ics = generateIcs({ ...baseEvent, description: 'foo; bar' })
    expect(ics).toContain('DESCRIPTION:foo\\; bar\r\n')
  })

  it('escapes backslashes in text fields', () => {
    const ics = generateIcs({ ...baseEvent, title: 'path\\to' })
    expect(ics).toContain('SUMMARY:path\\\\to\r\n')
  })

  it('escapes newlines in text fields', () => {
    const ics = generateIcs({ ...baseEvent, description: 'line1\nline2' })
    expect(ics).toContain('DESCRIPTION:line1\\nline2\r\n')
  })

  it('produces deterministic output for the same input', () => {
    const ics1 = generateIcs(baseEvent)
    const ics2 = generateIcs(baseEvent)
    // DTSTAMP changes with time, so strip it for comparison
    const strip = (s: string) => s.replace(/DTSTAMP:\d{8}T\d{6}Z\r\n/, '')
    expect(strip(ics1)).toBe(strip(ics2))
  })

  it('uses CRLF line endings throughout', () => {
    const ics = generateIcs(baseEvent)
    const lines = ics.split('\r\n')
    // Every "line" split by CRLF should not contain a bare LF
    for (const line of lines) {
      expect(line).not.toContain('\n')
    }
  })
})
