import { describe, expect, it } from 'vitest'
import { civilDateInZone, InvalidInstantError, InvalidTimeZoneError } from './datetime'

describe('civilDateInZone', () => {
  it('resolves the SAME instant to different civil dates across far-east / UTC / far-west zones', () => {
    // 11:30 UTC on 2026-06-15: +14h crosses into the 16th, -12h falls back to the 14th.
    const instant = new Date('2026-06-15T11:30:00Z')
    expect(civilDateInZone(instant, 'UTC')).toBe('2026-06-15')
    expect(civilDateInZone(instant, 'Pacific/Kiritimati')).toBe('2026-06-16') // UTC+14
    expect(civilDateInZone(instant, 'Etc/GMT+12')).toBe('2026-06-14') // UTC-12 (POSIX sign)
  })

  it('reads the zone DST offset — same UTC clock-time straddles a day boundary differently in EST vs EDT', () => {
    // America/New_York at 04:30 UTC: winter EST (-5) is still the prior day; summer EDT (-4) has ticked over.
    expect(civilDateInZone(new Date('2026-01-15T04:30:00Z'), 'America/New_York')).toBe('2026-01-14')
    expect(civilDateInZone(new Date('2026-07-15T04:30:00Z'), 'America/New_York')).toBe('2026-07-15')
  })

  it('crosses month and year boundaries with the zone offset', () => {
    // 2025-12-31 23:30 UTC: Jerusalem (+2 in winter) ticks into the new year; Honolulu (-10) stays in Dec.
    const nye = new Date('2025-12-31T23:30:00Z')
    expect(civilDateInZone(nye, 'Asia/Jerusalem')).toBe('2026-01-01')
    expect(civilDateInZone(nye, 'Pacific/Honolulu')).toBe('2025-12-31')
    expect(civilDateInZone(nye, 'UTC')).toBe('2025-12-31')
  })

  it('matches the production app seam (en-CA YYYY-MM-DD in Asia/Jerusalem)', () => {
    // toIsraelDateString / todayDateStr ≡ Intl.DateTimeFormat('en-CA', { timeZone }).format(instant)
    expect(civilDateInZone(new Date('2026-06-15T09:00:00Z'), 'Asia/Jerusalem')).toBe('2026-06-15')
  })

  it('throws InvalidInstantError on a non-valid Date (never returns "Invalid Date")', () => {
    expect(() => civilDateInZone(new Date('not-a-date'), 'UTC')).toThrow(InvalidInstantError)
  })

  it('throws InvalidTimeZoneError on an unknown or empty zone', () => {
    const instant = new Date('2026-06-15T00:00:00Z')
    expect(() => civilDateInZone(instant, 'Not/AZone')).toThrow(InvalidTimeZoneError)
    expect(() => civilDateInZone(instant, '')).toThrow(InvalidTimeZoneError)
  })
})
