import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import Button from '../src/components/Button/Button.vue'
import CanonicalButton from '../src/canonical/ButtonBridge.vue'

describe('Button', () => {
  it('renders slot content', () => {
    const wrapper = mount(Button, { slots: { default: 'Save' } })
    expect(wrapper.text()).toBe('Save')
  })
  it('renders as a <button> element', () => {
    const wrapper = mount(Button)
    expect(wrapper.element.tagName).toBe('BUTTON')
  })
  it('applies variant class from canonical style+color', () => {
    const wrapper = mount(Button, { props: { canonicalStyle: 'filling', canonicalColor: 'green' } })
    expect(wrapper.classes()).toContain('btn--fill-green')
  })
  it('applies size class from canonicalSize', () => {
    const wrapper = mount(Button, { props: { canonicalSize: 'M' } })
    expect(wrapper.classes()).toContain('btn--m')
  })
  it('sets disabled attribute when canonicalStatus="disable"', () => {
    const wrapper = mount(Button, { props: { canonicalStatus: 'disable' } })
    expect((wrapper.element as HTMLButtonElement).disabled).toBe(true)
  })
  it('does not emit click when canonicalStatus="disable"', async () => {
    const wrapper = mount(Button, { props: { canonicalStatus: 'disable' } })
    await wrapper.trigger('click')
    expect(wrapper.emitted('click')).toBeFalsy()
  })
  it('emits click when enabled (default canonicalStatus)', async () => {
    const wrapper = mount(Button)
    await wrapper.trigger('click')
    expect(wrapper.emitted('click')).toBeTruthy()
  })
  it('does not emit click when canonicalStatus="loading"', async () => {
    const wrapper = mount(Button, { props: { canonicalStatus: 'loading' } })
    await wrapper.trigger('click')
    expect(wrapper.emitted('click')).toBeFalsy()
  })
  it('applies loading class when canonicalStatus="loading"', () => {
    const wrapper = mount(Button, { props: { canonicalStatus: 'loading' } })
    expect(wrapper.classes()).toContain('btn--loading')
  })
  it('bridges canonical button props into runtime classes and attrs', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'red',
        canonicalStyle: 'filling',
        canonicalSize: 'XS',
        canonicalRadius: 'round',
        canonicalStatus: 'hover',
        canonicalFixedWidth: 'yes',
      },
      slots: { default: 'Delete' },
    })

    expect(wrapper.classes()).toContain('btn--fill-red')
    expect(wrapper.classes()).toContain('btn--xs')
    expect(wrapper.classes()).toContain('btn--radius-round')
    expect(wrapper.classes()).toContain('btn--fixed-yes')
    expect(wrapper.classes()).toContain('btn--status-hover')
    expect(wrapper.attributes('data-figma-color')).toBe('red')
    expect(wrapper.attributes('data-figma-size')).toBe('XS')
  })
  it('treats canonical loading status as disabled loading button', async () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'ghost',
        canonicalStatus: 'loading',
      },
    })

    expect(wrapper.classes()).toContain('btn--loading')
    expect((wrapper.element as HTMLButtonElement).disabled).toBe(true)
    await wrapper.trigger('click')
    expect(wrapper.emitted('click')).toBeFalsy()
  })
  it('canonical wrapper forwards canonical axes to runtime bridge props', () => {
    const wrapper = mount(CanonicalButton, {
      props: {
        color: 'orange',
        style: 'rimless',
        size: 'S',
        status: 'disable',
        radius: 'round',
      },
      slots: { default: 'Later' },
    })

    expect(wrapper.attributes('data-figma-color')).toBe('orange')
    expect(wrapper.attributes('data-figma-style')).toBe('rimless')
    expect(wrapper.attributes('data-figma-size')).toBe('S')
    expect(wrapper.classes()).toContain('btn--text-orange')
    expect(wrapper.classes()).toContain('btn--s')
    expect((wrapper.element as HTMLButtonElement).disabled).toBe(true)
  })
  it('renders canonical icon assets through the runtime bridge', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'gray 1',
        canonicalStyle: 'ghost',
        canonicalIcon: 'left',
        canonicalSize: 'M',
      },
      slots: { default: 'Back' },
    })

    const icon = wrapper.find('.btn-icon--leading')
    expect(icon.exists()).toBe(true)
    expect(icon.attributes('aria-label')).toBe('arrow-dropdown')
  })
  it('uses the same dropdown asset for the canonical right icon and places it after the label', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'ghost',
        canonicalIcon: 'right',
        canonicalSize: 'M',
      },
      slots: { default: 'Next' },
    })

    const leadingIcon = wrapper.find('.btn-icon--leading')
    const trailingIcon = wrapper.find('.btn-icon--trailing')
    expect(leadingIcon.exists()).toBe(false)
    expect(trailingIcon.exists()).toBe(true)
    expect(trailingIcon.attributes('aria-label')).toBe('arrow-dropdown')
  })
  it('uses bucketed canonical fixed width values instead of the old single size map', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'filling',
        canonicalSize: 'M',
        canonicalIcon: 'right',
        canonicalFixedWidth: 'yes',
      },
      slots: { default: 'Next' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-fixed-width: 96px')
    expect(style).toContain('--btn-min-width: 96px')
  })
  it('uses the Figma round-M fixed width bucket for icon buttons instead of the square width', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'ghost',
        canonicalSize: 'M',
        canonicalIcon: 'right',
        canonicalRadius: 'round',
        canonicalFixedWidth: 'yes',
      },
      slots: { default: 'Next' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-fixed-width: 104px')
    expect(style).toContain('--btn-min-width: 104px')
    expect(style).toContain('--btn-padding-inline: 20px')
  })
  it('keeps canonical fixedWidth=no truly auto instead of reusing width buckets as min-width', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'filling',
        canonicalSize: 'M',
        canonicalIcon: 'left',
        canonicalFixedWidth: 'no',
      },
      slots: { default: 'Next' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-fixed-width: auto')
    expect(style).toContain('--btn-min-width: 0px')
  })
  it('applies the extracted ghost stroke weight and icon gap from Figma', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'ghost',
        canonicalSize: 'L',
        canonicalIcon: 'right',
        canonicalRadius: 'round',
      },
      slots: { default: 'Next' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-border-width: 1.2px')
    expect(style).toContain('--btn-gap: 8px')
    expect(style).toContain('--btn-radius-round: 20px')
  })
  it('maps loading status to the disabled palette state instead of inventing a separate loading color family', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'filling',
        canonicalStatus: 'loading',
        canonicalIcon: 'loading',
      },
      slots: { default: 'Button' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-bg: var(--brand-disable)')
    expect(style).toContain('--btn-color: var(--text-tips)')
    expect(style).toContain('--btn-opacity: 1')
  })
  it('keeps red loading on the saturated red filling token from Figma instead of a pale warning surface', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'red',
        canonicalStyle: 'filling',
        canonicalStatus: 'loading',
        canonicalIcon: 'loading',
      },
      slots: { default: 'Button' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-bg: var(--red)')
    expect(style).toContain('--btn-color: var(--text-primary-btn)')
    expect(style).toContain('--btn-opacity: 0.4')
  })
  it('keeps orange ghost loading on the same orange outline token from Figma', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'orange',
        canonicalStyle: 'ghost',
        canonicalStatus: 'loading',
        canonicalIcon: 'loading',
      },
      slots: { default: 'Button' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-border: var(--orange)')
    expect(style).toContain('--btn-color: var(--orange)')
    expect(style).toContain('--btn-opacity: 0.4')
  })
  it('applies the extracted container opacity to red disabled buttons instead of only swapping tokens', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'red',
        canonicalStyle: 'ghost',
        canonicalStatus: 'disable',
        canonicalIcon: 'right',
        canonicalRadius: 'round',
      },
      slots: { default: 'Button' },
    })

    const style = wrapper.attributes('style')
    expect(style).toContain('--btn-border: var(--red)')
    expect(style).toContain('--btn-color: var(--red)')
    expect(style).toContain('--btn-opacity: 0.4')
    expect(wrapper.attributes('data-figma-opacity')).toBe('0.4')
  })
  it('defaults data-figma-theme to dark when canonicalTheme is not provided', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'filling',
      },
      slots: { default: 'Save' },
    })
    expect(wrapper.attributes('data-figma-theme')).toBe('dark')
  })
  it('sets data-figma-theme to light when canonicalTheme="light"', () => {
    const wrapper = mount(Button, {
      props: {
        canonicalColor: 'green',
        canonicalStyle: 'filling',
        canonicalTheme: 'light',
      },
      slots: { default: 'Save' },
    })
    expect(wrapper.attributes('data-figma-theme')).toBe('light')
  })
  it('canonical bridge forwards theme axis to runtime data-figma-theme', () => {
    const wrapper = mount(CanonicalButton, {
      props: {
        color: 'green',
        style: 'filling',
        theme: 'light',
      },
      slots: { default: 'Save' },
    })
    expect(wrapper.attributes('data-figma-theme')).toBe('light')
  })
})
