import { expect, fixture, html } from '@open-wc/testing'
import { elementUpdated } from '@open-wc/testing-helpers'
import { oneEvent } from '@open-wc/testing-helpers'
import './date-picker.js'
import type TerraDatePicker from './date-picker.js'

// Helper to get a date string in YYYY-MM-DD format
function formatDate(date: Date): string {
    return date.toISOString().split('T')[0]
}

// Helper to get month/year from a Date
function getMonthYear(date: Date): string {
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`
}

function getCalendar(
    el: TerraDatePicker,
    isLeft: boolean = true
): HTMLElement | undefined {
    const calendars = el.shadowRoot?.querySelectorAll<HTMLElement>('.calendar')
    return isLeft ? calendars?.[0] : calendars?.[1]
}

// Helper to find calendar day buttons in shadow root
function getCalendarDays(el: any, isLeft: boolean = true): NodeListOf<HTMLElement> {
    const calendars = el.shadowRoot?.querySelectorAll('.calendar')
    const calendar = isLeft ? calendars?.[0] : calendars?.[1]
    return calendar?.querySelectorAll('.calendar__day') || ([] as any)
}

// Helper to find a specific date button
function findDateButton(
    el: any,
    targetDate: Date,
    isLeft: boolean = true
): HTMLElement | null {
    const days = getCalendarDays(el, isLeft)
    for (const day of Array.from(days)) {
        const dateStr = day.textContent?.trim()
        if (dateStr && parseInt(dateStr, 10) === targetDate.getDate()) {
            // Check if it's in the current month (not grayed out)
            if (!day.classList.contains('calendar__day--outside')) {
                return day
            }
        }
    }
    return null
}

// Helper function to make selecting a specific date on the calendar easier
async function selectDate(el: TerraDatePicker, date: Date, isLeft: boolean = true) {
    const calendar = getCalendar(el, isLeft)

    if (!calendar) {
        throw new Error('Calendar not found')
    }

    const monthDropdown = calendar.querySelector<HTMLButtonElement>(
        '.calendar__month-button'
    )

    if (!monthDropdown) {
        throw new Error('Month dropdown not found')
    }

    monthDropdown.click()
    await elementUpdated(el)

    // find the month option that contains the text of the month of the date
    const monthOption = [
        ...(calendar.querySelectorAll<HTMLButtonElement>('.calendar__month-option') ||
            []),
    ].filter((option: HTMLElement) =>
        option.textContent?.includes(
            date.toLocaleString('default', { month: 'long' })
        )
    )

    if (!monthOption) {
        throw new Error('Month option not found')
    }

    monthOption[0]?.click()

    // select the year
    const yearInput = calendar.querySelector<HTMLInputElement>(
        '.calendar__year-input'
    )

    if (!yearInput) {
        throw new Error('Year input not found')
    }

    yearInput.value = date.getFullYear().toString()
    yearInput.dispatchEvent(new Event('input'))
    await elementUpdated(el)

    // select the day
    const dayButton = findDateButton(el, date, isLeft)
    if (!dayButton) {
        throw new Error('Day button not found')
    }
    dayButton.click()
    await elementUpdated(el)
}

/**
 * Mock Date methods to simulate a specific timezone for deterministic testing.
 * This mocks getHours(), getMinutes(), and getTimezoneOffset() to return values
 * as if the system is in Pacific Daylight Time (PDT, UTC-7).
 *
 * Note: getTimezoneOffset() returns the offset in minutes from UTC.
 * For timezones behind UTC (like PDT), it returns a POSITIVE number.
 * PDT (UTC-7) = 420 minutes = 7 hours behind UTC.
 *
 * @param offsetMinutes - Timezone offset in minutes (e.g., 420 for PDT = UTC-7)
 * @returns A function to restore the original Date methods
 */
function mockTimezoneOffset(offsetMinutes: number): () => void {
    const originalGetHours = Date.prototype.getHours
    const originalGetMinutes = Date.prototype.getMinutes
    const originalGetTimezoneOffset = Date.prototype.getTimezoneOffset

    // Mock getTimezoneOffset to return the desired offset
    // Note: getTimezoneOffset() returns positive for timezones behind UTC
    Date.prototype.getTimezoneOffset = function () {
        return offsetMinutes
    }

    // Mock getHours and getMinutes to account for the timezone offset
    // getTimezoneOffset() returns the offset from local to UTC, so:
    // local time = UTC time - offset
    // For PDT (UTC-7): offset = 420 minutes, so subtract 7 hours
    Date.prototype.getHours = function () {
        const utcHours = this.getUTCHours()
        const offsetHours = Math.floor(offsetMinutes / 60)
        // Subtract offset to convert UTC to local time
        let localHours = utcHours - offsetHours
        if (localHours < 0) localHours += 24
        if (localHours >= 24) localHours -= 24
        return localHours
    }

    Date.prototype.getMinutes = function () {
        const utcMinutes = this.getUTCMinutes()
        const offsetMinutesRemainder = offsetMinutes % 60
        // Subtract offset to convert UTC to local time
        let localMinutes = utcMinutes - offsetMinutesRemainder
        if (localMinutes < 0) {
            localMinutes += 60
            // Note: This doesn't adjust hours, but for our test case (30 minutes),
            // the offset remainder is 0, so this won't be an issue
        }
        if (localMinutes >= 60) {
            localMinutes -= 60
        }
        return localMinutes
    }

    return () => {
        Date.prototype.getHours = originalGetHours
        Date.prototype.getMinutes = originalGetMinutes
        Date.prototype.getTimezoneOffset = originalGetTimezoneOffset
    }
}

describe('<terra-date-picker>', () => {
    describe('Basic Rendering', () => {
        it('should render a component', async () => {
            const el = await fixture(html` <terra-date-picker></terra-date-picker> `)
            expect(el).to.exist
        })

        it('should render with default label', async () => {
            const el: any = await fixture(html`
                <terra-date-picker></terra-date-picker>
            `)
            const input = el.shadowRoot?.querySelector('terra-input')
            expect(input?.label).to.equal('Select Date')
        })

        it('should render with custom label', async () => {
            const el: any = await fixture(html`
                <terra-date-picker label="Event Date"></terra-date-picker>
            `)
            const input = el.shadowRoot?.querySelector('terra-input')
            expect(input?.label).to.equal('Event Date')
        })

        it('should render with help text', async () => {
            const el: any = await fixture(html`
                <terra-date-picker help-text="Format: YYYY-MM-DD"></terra-date-picker>
            `)
            const input = el.shadowRoot?.querySelector('terra-input')
            expect(input?.helpText).to.equal('Format: YYYY-MM-DD')
        })
    })

    describe('Properties', () => {
        it('should accept id property', async () => {
            const el: any = await fixture(html`
                <terra-date-picker id="test-picker"></terra-date-picker>
            `)
            expect(el.id).to.equal('test-picker')
        })

        it('should accept range property', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range></terra-date-picker>
            `)
            expect(el.range).to.be.true
        })

        it('should accept min-date and max-date', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    min-date="2024-01-01"
                    max-date="2024-12-31"
                ></terra-date-picker>
            `)
            expect(el.minDate).to.equal('2024-01-01')
            expect(el.maxDate).to.equal('2024-12-31')
        })

        it('should accept start-date and end-date', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    start-date="2024-03-20"
                    end-date="2024-03-25"
                ></terra-date-picker>
            `)
            expect(el.startDate).to.equal('2024-03-20')
            expect(el.endDate).to.equal('2024-03-25')
        })

        it('should accept inline property', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            expect(el.inline).to.be.true
            expect(el.isOpen).to.be.true
        })

        it('should accept split-inputs property', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range split-inputs></terra-date-picker>
            `)
            expect(el.splitInputs).to.be.true
        })

        it('should accept enable-time property', async () => {
            const el: any = await fixture(html`
                <terra-date-picker enable-time></terra-date-picker>
            `)
            expect(el.enableTime).to.be.true
        })

        it('should accept show-presets property', async () => {
            const el: any = await fixture(html`
                <terra-date-picker show-presets></terra-date-picker>
            `)
            expect(el.showPresets).to.be.true
        })
    })

    describe('Single Date Selection', () => {
        it('should initialize with start-date', async () => {
            const el: any = await fixture(html`
                <terra-date-picker start-date="2024-03-20"></terra-date-picker>
            `)
            await elementUpdated(el)
            expect(el.selectedStart).to.not.be.null
            expect(formatDate(el.selectedStart)).to.equal('2024-03-20')
        })

        it('should emit terra-date-range-change when date is selected', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const eventPromise = oneEvent(el, 'terra-date-range-change')

            await selectDate(el, new Date(2024, 2, 16)) // March 16, 2024

            const event = await eventPromise

            expect(event.detail.startDate).to.equal('2024-03-16')
            expect(event.detail.endDate).to.equal('')
        })

        it('should update display value when date is selected', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            await elementUpdated(el)

            await selectDate(el, new Date(2023, 1, 5)) // February 5, 2023

            const input = el.shadowRoot?.querySelector('terra-input')
            expect(input?.value).to.include('2023-02-05')
        })
    })

    describe('Range Selection', () => {
        it('should initialize with start-date and end-date in range mode', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    range
                    start-date="2024-03-20"
                    end-date="2024-03-25"
                ></terra-date-picker>
            `)
            await elementUpdated(el)
            expect(el.selectedStart).to.not.be.null
            expect(el.selectedEnd).to.not.be.null
            expect(formatDate(el.selectedStart)).to.equal('2024-03-20')
            expect(formatDate(el.selectedEnd)).to.equal('2024-03-25')
        })

        it('should emit terra-date-range-change when range is selected', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const eventPromise = oneEvent(el, 'terra-date-range-change')

            // Select start date
            const startDate = new Date(2024, 2, 15) // March 15
            await selectDate(el, startDate, true)

            // Select end date
            const endDate = new Date(2024, 2, 20) // March 20
            await selectDate(el, endDate, true)

            const event = await eventPromise

            expect(event.detail.startDate).to.equal('2024-03-15')
            expect(event.detail.endDate).to.equal('2024-03-20')
        })

        it('should swap dates if end date is before start date', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const eventPromise = oneEvent(el, 'terra-date-range-change')

            // Select later date first
            const laterDate = new Date(2024, 2, 20) // March 20
            await selectDate(el, laterDate, true)

            // Select earlier date
            const earlierDate = new Date(2024, 2, 15) // March 15
            await selectDate(el, earlierDate, true)

            const event = await eventPromise

            expect(event.detail.startDate).to.equal('2024-03-15')
            expect(event.detail.endDate).to.equal('2024-03-20')
        })

        it('should display range in input value', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    range
                    start-date="2024-03-20"
                    end-date="2024-03-25"
                ></terra-date-picker>
            `)
            await elementUpdated(el)

            const input = el.shadowRoot?.querySelector('terra-input')
            expect(input?.value).to.include('2024-03-20')
            expect(input?.value).to.include('2024-03-25')
        })
    })

    describe('Month Synchronization (Current Behavior)', () => {
        it('should set leftMonth to start date month when start-date changes', async () => {
            const el: any = await fixture(html`
                <terra-date-picker start-date="2024-03-20"></terra-date-picker>
            `)
            await elementUpdated(el)

            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')
        })

        it('should set rightMonth to end date month when end-date changes in range mode', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    range
                    start-date="2024-03-20"
                    end-date="2024-12-15"
                ></terra-date-picker>
            `)
            await elementUpdated(el)

            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-12')
        })

        it('should set rightMonth to leftMonth + 1 when no end-date in range mode', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range start-date="2024-03-20"></terra-date-picker>
            `)
            await elementUpdated(el)

            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-04')
        })

        it('should preserve right calendar when single-month range is selected on left calendar', async () => {
            // Case 1: Left calendar shows September, right shows December
            // User selects September 2-4 on the left calendar
            // Right calendar should stay at December
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            // Manually set calendars to different months (simulating user navigation)
            el.leftMonth = new Date(2024, 8, 1) // September
            el.rightMonth = new Date(2024, 11, 1) // December
            await elementUpdated(el)

            // Now set a range that's entirely in September
            el.startDate = '2024-09-02'
            el.endDate = '2024-09-04'
            await elementUpdated(el)

            // Left calendar should show September, right should stay at December
            expect(getMonthYear(el.leftMonth)).to.equal('2024-09')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-12')
        })

        it('should preserve left calendar when single-month range is selected on right calendar', async () => {
            // Case 2: Left calendar shows September, right shows December
            // User selects December 1-2 on the right calendar
            // Left calendar should stay at September
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            // Manually set calendars to different months
            el.leftMonth = new Date(2024, 8, 1) // September
            el.rightMonth = new Date(2024, 11, 1) // December
            await elementUpdated(el)

            // Now set a range that's entirely in December
            el.startDate = '2024-12-01'
            el.endDate = '2024-12-02'
            await elementUpdated(el)

            // Left calendar should stay at September, right should show December
            expect(getMonthYear(el.leftMonth)).to.equal('2024-09')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-12')
        })

        it('should update only left calendar when single-month range is in neither visible month', async () => {
            // Case 3: Left calendar shows September, right shows December
            // User selects a range in a different month (e.g., March)
            // Only the left calendar should change to show March
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            // Manually set calendars to different months
            el.leftMonth = new Date(2024, 8, 1) // September
            el.rightMonth = new Date(2024, 11, 1) // December
            await elementUpdated(el)

            // Now set a range that's entirely in March (neither visible month)
            el.startDate = '2024-03-10'
            el.endDate = '2024-03-15'
            await elementUpdated(el)

            // Left calendar should show March, right should stay at December
            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-12')
        })

        it('should set right calendar to next month on initial load with single-month range', async () => {
            // When a single-month range is provided on initial load,
            // left should show the selection month, right should show next month
            const el: any = await fixture(html`
                <terra-date-picker
                    range
                    start-date="2024-03-20"
                    end-date="2024-03-25"
                ></terra-date-picker>
            `)
            await elementUpdated(el)

            // Left should show March, right should show April (next month)
            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-04')
        })

        it('should update both calendars when range spans different months', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    range
                    start-date="2024-03-20"
                    end-date="2024-06-15"
                ></terra-date-picker>
            `)
            await elementUpdated(el)

            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-06')
        })

        it('should update months when start-date changes externally', async () => {
            const el: any = await fixture(html`
                <terra-date-picker start-date="2024-03-20"></terra-date-picker>
            `)
            await elementUpdated(el)

            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')

            // Change start-date externally
            el.startDate = '2024-07-15'
            await elementUpdated(el)

            expect(getMonthYear(el.leftMonth)).to.equal('2024-07')
        })

        it('should update months when end-date changes externally in range mode', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    range
                    start-date="2024-03-20"
                    end-date="2024-03-25"
                ></terra-date-picker>
            `)
            await elementUpdated(el)

            // Change end-date externally
            el.endDate = '2024-08-10'
            await elementUpdated(el)

            expect(getMonthYear(el.leftMonth)).to.equal('2024-03')
            expect(getMonthYear(el.rightMonth)).to.equal('2024-08')
        })
    })

    describe('Calendar Navigation', () => {
        it('should navigate to previous month on left calendar', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const initialMonth = el.leftMonth.getMonth()
            const prevButton = el.shadowRoot?.querySelectorAll(
                '.calendar__nav'
            )?.[0] as HTMLElement
            prevButton?.click()
            await elementUpdated(el)

            expect(el.leftMonth.getMonth()).to.equal(
                initialMonth === 0 ? 11 : initialMonth - 1
            )
        })

        it('should navigate to next month on left calendar', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const initialMonth = el.leftMonth.getMonth()
            const nextButton = el.shadowRoot?.querySelectorAll(
                '.calendar__nav'
            )?.[1] as HTMLElement
            nextButton?.click()
            await elementUpdated(el)

            expect(el.leftMonth.getMonth()).to.equal(
                initialMonth === 11 ? 0 : initialMonth + 1
            )
        })

        it('should navigate to previous month on right calendar in range mode', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const initialMonth = el.rightMonth.getMonth()
            const calendars = el.shadowRoot?.querySelectorAll('.calendar')
            const rightCalendar = calendars?.[1]
            const prevButton = rightCalendar?.querySelectorAll(
                '.calendar__nav'
            )?.[0] as HTMLElement
            prevButton?.click()
            await elementUpdated(el)

            expect(el.rightMonth.getMonth()).to.equal(
                initialMonth === 0 ? 11 : initialMonth - 1
            )
        })

        it('should change year when year input changes', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const yearInput = el.shadowRoot?.querySelector(
                '.calendar__year-input'
            ) as HTMLInputElement
            yearInput.value = '2025'
            yearInput.dispatchEvent(new Event('input'))
            await elementUpdated(el)

            expect(el.leftMonth.getFullYear()).to.equal(2025)
        })
    })

    describe('Min/Max Date Constraints', () => {
        it('should disable dates before min-date', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    inline
                    min-date="2024-03-15"
                    start-date="2024-04-05"
                ></terra-date-picker>
            `)
            await elementUpdated(el)

            await selectDate(el, new Date(2024, 2, 10)) // try to select a date before min-date

            expect(el.startDate).to.equal('2024-04-05') // should not change
        })

        it('should disable dates before min-date when start date is not set', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline min-date="2024-03-15"></terra-date-picker>
            `)
            await elementUpdated(el)

            await selectDate(el, new Date(2024, 2, 10)) // try to select a date before min-date

            expect(el.startDate).to.equal(undefined) // should not change
        })

        it('should disable dates after max-date', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline max-date="2024-03-20"></terra-date-picker>
            `)
            await elementUpdated(el)

            // Navigate to a month with dates after max-date
            el.leftMonth = new Date(2024, 2, 1) // March
            await elementUpdated(el)

            // Find a date after max-date
            const afterMax = new Date(2024, 2, 25) // March 25
            const dateButton = findDateButton(el, afterMax, true)
            if (dateButton) {
                expect(dateButton.classList.contains('calendar__day--disabled')).to.be
                    .true
            }
        })

        it('should not allow selection of disabled dates', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline min-date="2024-03-15"></terra-date-picker>
            `)
            await elementUpdated(el)

            const beforeMinDate = new Date(2024, 2, 10)

            await selectDate(el, beforeMinDate)

            const dateButton = findDateButton(el, beforeMinDate, true)
            if (dateButton) {
                const button = dateButton as HTMLButtonElement
                if (!button.disabled) {
                    const initialSelected = el.selectedStart
                    dateButton.click()
                    await elementUpdated(el)

                    // Selection should not change
                    expect(el.selectedStart).to.deep.equal(initialSelected)
                }
            }
        })
    })

    describe('Presets', () => {
        it('should show presets sidebar when show-presets is true', async () => {
            const el: any = await fixture(html`
                <terra-date-picker show-presets inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const sidebar = el.shadowRoot?.querySelector('.date-picker__sidebar')
            expect(sidebar).to.exist
        })

        it('should have default presets', async () => {
            const el: any = await fixture(html`
                <terra-date-picker show-presets inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const presetButtons = el.shadowRoot?.querySelectorAll(
                '.date-picker__preset'
            )
            expect(presetButtons?.length).to.be.greaterThan(0)
        })

        it('should select dates when preset is clicked', async () => {
            const el: any = await fixture(html`
                <terra-date-picker show-presets inline range></terra-date-picker>
            `)
            await elementUpdated(el)

            const presetButtons = el.shadowRoot?.querySelectorAll(
                '.date-picker__preset'
            )
            const todayPreset = Array.from(presetButtons || []).find(
                (btn: any) => btn.textContent?.trim() === 'Today'
            ) as HTMLElement

            if (todayPreset) {
                const eventPromise = oneEvent(el, 'terra-date-range-change')
                todayPreset.click()
                const event = await eventPromise

                expect(event.detail.startDate).to.not.be.empty
                expect(event.detail.endDate).to.not.be.empty
            }
        })
    })

    describe('Time Selection', () => {
        it('should show time picker when enable-time is true', async () => {
            const el: any = await fixture(html`
                <terra-date-picker enable-time inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const timePicker = el.shadowRoot?.querySelector('.date-picker__time')
            expect(timePicker).to.exist
        })

        it('should initialize time from start-date when enable-time is true', async () => {
            // Mock timezone to Pacific Daylight Time (PDT, UTC-7)
            // For March 20, 2024, DST applies, so PDT offset is 420 minutes (7 hours behind UTC)
            const restoreTimezone = mockTimezoneOffset(7 * 60)

            try {
                const el: any = await fixture(html`
                    <terra-date-picker
                        enable-time
                        inline
                        start-date="2024-03-20T14:30:00Z"
                    ></terra-date-picker>
                `)
                await elementUpdated(el)

                // With PDT (UTC-7), 14:30 UTC = 7:30 AM PDT
                // In 12-hour format: hour 7, minute 30, AM
                expect(el.startHour).to.equal(7)
                expect(el.startMinute).to.equal(30)
                expect(el.timePeriod).to.equal('AM')
            } finally {
                restoreTimezone()
            }
        })

        it('should emit time in ISO format when enable-time is true', async () => {
            const el: any = await fixture(html`
                <terra-date-picker enable-time inline></terra-date-picker>
            `)
            await elementUpdated(el)

            // Select a date
            const date = new Date(2024, 2, 15)
            const dateButton = findDateButton(el, date, true)
            const eventPromise = oneEvent(el, 'terra-date-range-change')
            dateButton!.click()
            const event = await eventPromise

            // Should be ISO format with time
            expect(event.detail.startDate).to.include('T')
            expect(event.detail.startDate).to.include('Z')
        })
    })

    describe('Split Inputs', () => {
        it('should show two inputs when split-inputs and range are true', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range split-inputs inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const inputs = el.shadowRoot?.querySelectorAll('terra-input')
            expect(inputs?.length).to.equal(2)
        })

        it('should use custom start-label and end-label', async () => {
            const el: any = await fixture(html`
                <terra-date-picker
                    range
                    split-inputs
                    start-label="From"
                    end-label="To"
                ></terra-date-picker>
            `)
            await elementUpdated(el)

            const inputs = el.shadowRoot?.querySelectorAll('terra-input')
            expect(inputs?.[0]?.label).to.equal('From')
            expect(inputs?.[1]?.label).to.equal('To')
        })
    })

    describe('Inline Mode', () => {
        it('should show calendar when inline is true', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            await elementUpdated(el)

            expect(el.isOpen).to.be.true
            const calendar = el.shadowRoot?.querySelector('.calendar')
            expect(calendar).to.exist
        })

        it('should not close calendar after selection when inline is true', async () => {
            const el: any = await fixture(html`
                <terra-date-picker inline></terra-date-picker>
            `)
            await elementUpdated(el)

            const date = new Date(2024, 2, 15)
            const dateButton = findDateButton(el, date, true)
            dateButton!.click()
            await elementUpdated(el)

            expect(el.isOpen).to.be.true
        })
    })

    describe('State Management', () => {
        it('should track isSelectingRange during range selection', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            // Select start date
            const startDate = new Date(2024, 2, 15)
            const startButton = findDateButton(el, startDate, true)
            startButton!.click()
            await elementUpdated(el)

            expect(el.isSelectingRange).to.be.true

            // Select end date
            const endDate = new Date(2024, 2, 20)
            const endButton = findDateButton(el, endDate, true)
            endButton!.click()
            await elementUpdated(el)

            expect(el.isSelectingRange).to.be.false
        })

        it('should track hoverDate during range selection', async () => {
            const el: any = await fixture(html`
                <terra-date-picker range inline></terra-date-picker>
            `)
            await elementUpdated(el)

            // Select start date
            const startDate = new Date(2024, 2, 15)
            const startButton = findDateButton(el, startDate, true)
            startButton!.click()
            await elementUpdated(el)

            // Hover over another date
            const hoverDate = new Date(2024, 2, 18)
            const hoverButton = findDateButton(el, hoverDate, true)
            hoverButton?.dispatchEvent(new MouseEvent('mouseenter'))
            await elementUpdated(el)

            expect(el.hoverDate).to.not.be.null
        })
    })
})
