import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import ButtonGroup from '~/components/UI/ButtonGroup.vue'
import type { ButtonGroupOption } from '~/components/UI/ButtonGroup.vue'

describe('ButtonGroup', () => {
  const mockOptions: ButtonGroupOption[] = [
    { value: 'option1', label: 'Option 1' },
    { value: 'option2', label: 'Option 2' },
    { value: 'option3', label: 'Option 3' },
  ]

  describe('Rendering', () => {
    it('renders all options', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
        },
      })

      const buttons = wrapper.findAll('button')
      expect(buttons).toHaveLength(3)
      expect(buttons[0].text()).toContain('Option 1')
      expect(buttons[1].text()).toContain('Option 2')
      expect(buttons[2].text()).toContain('Option 3')
    })

    it('renders with icons when provided', () => {
      const optionsWithIcons: ButtonGroupOption[] = [
        { value: 'opt1', label: 'Option 1', icon: '🎯' },
        { value: 'opt2', label: 'Option 2', icon: '⚡' },
      ]

      const wrapper = mount(ButtonGroup, {
        props: {
          options: optionsWithIcons,
          modelValue: 'opt1',
        },
      })

      expect(wrapper.html()).toContain('🎯')
      expect(wrapper.html()).toContain('⚡')
    })

    it('renders with badges when provided', () => {
      const optionsWithBadges: ButtonGroupOption[] = [
        { value: 'opt1', label: 'Option 1', badge: '5' },
        { value: 'opt2', label: 'Option 2', badge: 10 },
      ]

      const wrapper = mount(ButtonGroup, {
        props: {
          options: optionsWithBadges,
          modelValue: 'opt1',
        },
      })

      expect(wrapper.text()).toContain('5')
      expect(wrapper.text()).toContain('10')
    })
  })

  describe('Selection', () => {
    it('applies selected styles to current value', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option2',
        },
      })

      const buttons = wrapper.findAll('button')
      expect(buttons[1].classes()).toContain('from-primary')
      expect(buttons[0].classes()).toContain('bg-white')
      expect(buttons[2].classes()).toContain('bg-white')
    })

    it('emits update:modelValue when option is clicked', async () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
        },
      })

      await wrapper.findAll('button')[2].trigger('click')
      expect(wrapper.emitted('update:modelValue')).toBeTruthy()
      expect(wrapper.emitted('update:modelValue')![0]).toEqual(['option3'])
    })

    it('does not emit when disabled', async () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          disabled: true,
        },
      })

      await wrapper.findAll('button')[1].trigger('click')
      expect(wrapper.emitted('update:modelValue')).toBeFalsy()
    })
  })

  describe('Variants', () => {
    it('uses primary variant by default', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          variant: 'primary',
        },
      })

      const selectedButton = wrapper.findAll('button')[0]
      expect(selectedButton.classes()).toContain('from-primary')
    })

    it('applies secondary variant when specified', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          variant: 'secondary',
        },
      })

      const selectedButton = wrapper.findAll('button')[0]
      expect(selectedButton.classes()).toContain('from-gray-600')
    })
  })

  describe('Sizes', () => {
    it('applies small size classes', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          size: 'sm',
        },
      })

      const button = wrapper.find('button')
      expect(button.classes()).toContain('px-3')
      expect(button.classes()).toContain('py-1.5')
    })

    it('applies medium size classes', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          size: 'md',
        },
      })

      const button = wrapper.find('button')
      expect(button.classes()).toContain('px-4')
      expect(button.classes()).toContain('py-2.5')
    })

    it('applies large size classes', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          size: 'lg',
        },
      })

      const button = wrapper.find('button')
      expect(button.classes()).toContain('px-5')
      expect(button.classes()).toContain('py-3')
    })
  })

  describe('Layout', () => {
    it('renders horizontal layout by default', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
        },
      })

      expect(wrapper.find('div').classes()).toContain('flex-row')
    })

    it('renders vertical layout when specified', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          vertical: true,
        },
      })

      expect(wrapper.find('div').classes()).toContain('flex-col')
      expect(wrapper.find('div').classes()).toContain('w-full')
    })

    it('applies full width to buttons in vertical mode', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          vertical: true,
        },
      })

      const buttons = wrapper.findAll('button')
      buttons.forEach(button => {
        expect(button.classes()).toContain('w-full')
      })
    })
  })

  describe('Border Radius', () => {
    it('rounds first button left in horizontal mode', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          vertical: false,
        },
      })

      const buttons = wrapper.findAll('button')
      expect(buttons[0].classes()).toContain('rounded-l-lg')
    })

    it('rounds last button right in horizontal mode', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          vertical: false,
        },
      })

      const buttons = wrapper.findAll('button')
      expect(buttons[2].classes()).toContain('rounded-r-lg')
    })

    it('rounds first button top in vertical mode', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          vertical: true,
        },
      })

      const buttons = wrapper.findAll('button')
      expect(buttons[0].classes()).toContain('rounded-t-lg')
    })

    it('rounds last button bottom in vertical mode', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          vertical: true,
        },
      })

      const buttons = wrapper.findAll('button')
      expect(buttons[2].classes()).toContain('rounded-b-lg')
    })
  })

  describe('Disabled State', () => {
    it('disables all buttons when disabled prop is true', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          disabled: true,
        },
      })

      const buttons = wrapper.findAll('button')
      buttons.forEach(button => {
        expect(button.attributes('disabled')).toBe('')
      })
    })

    it('applies disabled styles', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          disabled: true,
        },
      })

      const buttons = wrapper.findAll('button')
      buttons.forEach(button => {
        expect(button.classes()).toContain('disabled:opacity-50')
        expect(button.classes()).toContain('disabled:cursor-not-allowed')
      })
    })
  })

  describe('Type Attribute', () => {
    it('sets type to button by default', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
        },
      })

      wrapper.findAll('button').forEach(button => {
        expect(button.attributes('type')).toBe('button')
      })
    })

    it('sets custom type when specified', () => {
      const wrapper = mount(ButtonGroup, {
        props: {
          options: mockOptions,
          modelValue: 'option1',
          type: 'submit',
        },
      })

      wrapper.findAll('button').forEach(button => {
        expect(button.attributes('type')).toBe('submit')
      })
    })
  })
})
