import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import TimeSelector from '../components/shared/TimeSelector.vue'

function mk(hour: number, minute: number) {
  return mount(TimeSelector, { props: { modelValue: { hour, minute } } })
}

// ---------------------------------------------------------------------------
// Display
// ---------------------------------------------------------------------------
describe('TimeSelector display', () => {
  it('shows 12 for midnight (hour=0)', () => {
    const w = mk(0, 0)
    expect(w.findAll('.time-value')[0].text()).toBe('12')
    expect(w.find('.ampm-btn').text()).toBe('AM')
  })

  it('shows 12 for noon (hour=12)', () => {
    const w = mk(12, 0)
    expect(w.findAll('.time-value')[0].text()).toBe('12')
    expect(w.find('.ampm-btn').text()).toBe('PM')
  })

  it('shows 3:30 PM for hour=15 minute=30', () => {
    const w = mk(15, 30)
    const cols = w.findAll('.time-value')
    expect(cols[0].text()).toBe('3')
    expect(cols[1].text()).toBe('30')
    expect(w.find('.ampm-btn').text()).toBe('PM')
  })

  it('pads single-digit minutes', () => {
    const w = mk(8, 0)
    expect(w.findAll('.time-value')[1].text()).toBe('00')
  })
})

// ---------------------------------------------------------------------------
// Increment / Decrement hour
// ---------------------------------------------------------------------------
describe('TimeSelector hour increment/decrement', () => {
  it('emits hour+1 when increment hour clicked', async () => {
    const w = mk(8, 15)
    await w.findAll('.arrow-btn')[0].trigger('click')
    const emitted = w.emitted('update:modelValue') as any[]
    expect(emitted[0][0]).toEqual({ hour: 9, minute: 15 })
  })

  it('emits hour-1 when decrement hour clicked', async () => {
    const w = mk(8, 15)
    await w.findAll('.arrow-btn')[1].trigger('click')
    const emitted = w.emitted('update:modelValue') as any[]
    expect(emitted[0][0]).toEqual({ hour: 7, minute: 15 })
  })

  it('wraps hour 23 → 0 on increment', async () => {
    const w = mk(23, 0)
    await w.findAll('.arrow-btn')[0].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 0, minute: 0 })
  })

  it('wraps hour 0 → 23 on decrement', async () => {
    const w = mk(0, 0)
    await w.findAll('.arrow-btn')[1].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 23, minute: 0 })
  })
})

// ---------------------------------------------------------------------------
// Increment / Decrement minute (15-min steps)
// ---------------------------------------------------------------------------
describe('TimeSelector minute increment/decrement', () => {
  it('emits minute+15 on increment', async () => {
    const w = mk(8, 0)
    await w.findAll('.arrow-btn')[2].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 8, minute: 15 })
  })

  it('emits minute-15 on decrement', async () => {
    const w = mk(8, 30)
    await w.findAll('.arrow-btn')[3].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 8, minute: 15 })
  })

  it('minute 45 → 0 and carry hour on increment', async () => {
    const w = mk(8, 45)
    await w.findAll('.arrow-btn')[2].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 9, minute: 0 })
  })

  it('minute 0 → 45 and borrow hour on decrement', async () => {
    const w = mk(8, 0)
    await w.findAll('.arrow-btn')[3].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 7, minute: 45 })
  })

  // The key boundary case from the spec: 11:45 AM → 12:00 PM
  it('11:45 AM (hour=11, minute=45) → increment minute → 12:00 PM (hour=12)', async () => {
    const w = mk(11, 45)
    await w.findAll('.arrow-btn')[2].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 12, minute: 0 })
  })

  // Inverse: 12:00 PM (hour=12) → decrement minute → 11:45 AM (hour=11, minute=45)
  it('12:00 PM (hour=12, minute=0) → decrement minute → 11:45 (hour=11)', async () => {
    const w = mk(12, 0)
    await w.findAll('.arrow-btn')[3].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 11, minute: 45 })
  })

  // Midnight boundary: 0:00 → decrement → 23:45
  it('0:00 AM (hour=0, minute=0) → decrement minute → 23:45', async () => {
    const w = mk(0, 0)
    await w.findAll('.arrow-btn')[3].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 23, minute: 45 })
  })

  // 23:45 → increment → 0:00
  it('23:45 → increment minute → 0:00', async () => {
    const w = mk(23, 45)
    await w.findAll('.arrow-btn')[2].trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 0, minute: 0 })
  })
})

// ---------------------------------------------------------------------------
// AM/PM toggle
// ---------------------------------------------------------------------------
describe('TimeSelector AM/PM toggle', () => {
  it('toggles AM → PM (hour < 12 adds 12)', async () => {
    const w = mk(8, 0)
    await w.find('.ampm-btn').trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 20, minute: 0 })
  })

  it('toggles PM → AM (hour >= 12 subtracts 12)', async () => {
    const w = mk(14, 30)
    await w.find('.ampm-btn').trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 2, minute: 30 })
  })

  it('toggles midnight (0) → 12 (noon)', async () => {
    const w = mk(0, 0)
    await w.find('.ampm-btn').trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 12, minute: 0 })
  })

  it('toggles noon (12) → 0 (midnight)', async () => {
    const w = mk(12, 0)
    await w.find('.ampm-btn').trigger('click')
    expect(w.emitted('update:modelValue')![0][0]).toEqual({ hour: 0, minute: 0 })
  })
})
