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

describe('ActionButton', () => {
  describe('Rendering', () => {
    it('renders slot content', () => {
      const wrapper = mount(ActionButton, {
        slots: {
          default: 'Click Me',
        },
      })

      expect(wrapper.text()).toContain('Click Me')
    })

    it('renders with default props', () => {
      const wrapper = mount(ActionButton, {
        slots: {
          default: 'Test',
        },
      })

      const button = wrapper.find('button')
      expect(button.attributes('type')).toBe('button')
      expect(button.classes()).toContain('from-primary')
    })
  })

  describe('Variants', () => {
    it('applies primary variant classes', () => {
      const wrapper = mount(ActionButton, {
        props: { variant: 'primary' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).toContain('from-primary')
      expect(wrapper.find('button').classes()).toContain('to-blue-600')
    })

    it('applies secondary variant classes', () => {
      const wrapper = mount(ActionButton, {
        props: { variant: 'secondary' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).toContain('from-gray-600')
    })

    it('applies success variant classes', () => {
      const wrapper = mount(ActionButton, {
        props: { variant: 'success' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).toContain('from-green-600')
    })

    it('applies danger variant classes', () => {
      const wrapper = mount(ActionButton, {
        props: { variant: 'danger' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).toContain('from-red-600')
    })

    it('applies warning variant classes', () => {
      const wrapper = mount(ActionButton, {
        props: { variant: 'warning' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).toContain('from-yellow-500')
    })
  })

  describe('Sizes', () => {
    it('applies small size classes', () => {
      const wrapper = mount(ActionButton, {
        props: { size: 'sm' },
        slots: { default: 'Test' },
      })

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

    it('applies medium size classes', () => {
      const wrapper = mount(ActionButton, {
        props: { size: 'md' },
        slots: { default: 'Test' },
      })

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

    it('applies large size classes', () => {
      const wrapper = mount(ActionButton, {
        props: { size: 'lg' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).toContain('px-6')
      expect(wrapper.find('button').classes()).toContain('py-3')
    })
  })

  describe('States', () => {
    it('shows loading spinner when loading', () => {
      const wrapper = mount(ActionButton, {
        props: { loading: true },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('svg.animate-spin').exists()).toBe(true)
      expect(wrapper.find('button').attributes('disabled')).toBe('')
    })

    it('hides content when loading', () => {
      const wrapper = mount(ActionButton, {
        props: { loading: true },
        slots: { default: 'Test' },
      })

      const contentSpan = wrapper.find('span.invisible')
      expect(contentSpan.exists()).toBe(true)
    })

    it('disables button when disabled prop is true', () => {
      const wrapper = mount(ActionButton, {
        props: { disabled: true },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').attributes('disabled')).toBe('')
    })

    it('disables button when loading', () => {
      const wrapper = mount(ActionButton, {
        props: { loading: true },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').attributes('disabled')).toBe('')
    })
  })

  describe('Full Width', () => {
    it('applies full width class when fullWidth is true', () => {
      const wrapper = mount(ActionButton, {
        props: { fullWidth: true },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).toContain('w-full')
    })

    it('does not apply full width class by default', () => {
      const wrapper = mount(ActionButton, {
        props: { fullWidth: false },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').classes()).not.toContain('w-full')
    })
  })

  describe('Events', () => {
    it('emits click event when clicked', async () => {
      const wrapper = mount(ActionButton, {
        slots: { default: 'Test' },
      })

      await wrapper.find('button').trigger('click')
      expect(wrapper.emitted('click')).toBeTruthy()
      expect(wrapper.emitted('click')).toHaveLength(1)
    })

    it('does not emit click when disabled', async () => {
      const wrapper = mount(ActionButton, {
        props: { disabled: true },
        slots: { default: 'Test' },
      })

      await wrapper.find('button').trigger('click')
      expect(wrapper.emitted('click')).toBeFalsy()
    })

    it('does not emit click when loading', async () => {
      const wrapper = mount(ActionButton, {
        props: { loading: true },
        slots: { default: 'Test' },
      })

      await wrapper.find('button').trigger('click')
      expect(wrapper.emitted('click')).toBeFalsy()
    })

    it('emits MouseEvent in click handler', async () => {
      const wrapper = mount(ActionButton, {
        slots: { default: 'Test' },
      })

      await wrapper.find('button').trigger('click')
      const emitted = wrapper.emitted('click')
      expect(emitted).toBeTruthy()
      expect(emitted![0][0]).toBeInstanceOf(MouseEvent)
    })
  })

  describe('Type Attribute', () => {
    it('sets type to button by default', () => {
      const wrapper = mount(ActionButton, {
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').attributes('type')).toBe('button')
    })

    it('sets type to submit when specified', () => {
      const wrapper = mount(ActionButton, {
        props: { type: 'submit' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').attributes('type')).toBe('submit')
    })

    it('sets type to reset when specified', () => {
      const wrapper = mount(ActionButton, {
        props: { type: 'reset' },
        slots: { default: 'Test' },
      })

      expect(wrapper.find('button').attributes('type')).toBe('reset')
    })
  })
})
