import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import InputBoxLine from '../src/canonical/InputBoxLine.vue'
import InputBoxFilled from '../src/canonical/InputBoxFilled.vue'
import Badge from '../src/canonical/Badge.vue'
import CheckBox from '../src/canonical/CheckBox.vue'
import InputNumber from '../src/canonical/InputNumber.vue'
import Notification from '../src/canonical/Notification.vue'
import Pagination from '../src/canonical/Pagination.vue'
import Progress from '../src/canonical/Progress.vue'
import Radio from '../src/canonical/Radio.vue'
import Rating from '../src/canonical/Rating.vue'
import Slider from '../src/canonical/Slider.vue'
import Switch from '../src/canonical/Switch.vue'
import Table from '../src/canonical/Table.vue'
import SelectBoxLine from '../src/canonical/SelectBoxLine.vue'
import SelectBoxFilled from '../src/canonical/SelectBoxFilled.vue'
import TopBar from '../src/canonical/TopBar.vue'
import Tooltip from '../src/canonical/Tooltip.vue'

describe('Canonical wrappers', () => {
  it('Badge maps Figma color/tag/type axes into a canonical badge render', () => {
    const wrapper = mount(Badge, {
      props: {
        color: 'Green',
        tag: 'Line',
        type: 'Rectangle',
      },
      slots: {
        default: 'Msg',
      },
    })

    const badge = wrapper.find('.canonical-badge')
    expect(badge.attributes('data-figma-component')).toBe('Badge')
    expect(badge.attributes('data-figma-color')).toBe('Green')
    expect(badge.attributes('data-figma-tag')).toBe('Line')
    expect(badge.attributes('data-figma-type')).toBe('Rectangle')
    expect(wrapper.attributes('style')).toContain('--badge-border: var(--brand)')
    expect(getComputedStyle(badge.element as HTMLElement).alignSelf).toBe('flex-start')
    expect(wrapper.text()).toContain('Msg')
  })

  it('InputBoxLine maps figma props to line input behavior', () => {
    const wrapper = mount(InputBoxLine, {
      props: {
        enable: 'off',
        ux: 'error',
        size: 'XL',
      },
    })

    const input = wrapper.find('input')
    expect(input.classes()).toContain('tvu-input--l')
    expect(input.classes()).toContain('tvu-input--error')
    expect((input.element as HTMLInputElement).disabled).toBe(true)
    expect(input.attributes('data-figma-component')).toBe('input box/line')
    expect(input.attributes('data-figma-size')).toBe('XL')
  })

  it('InputBoxFilled maps to filled variant', () => {
    const wrapper = mount(InputBoxFilled, {
      props: {
        size: 'M',
      },
    })

    const input = wrapper.find('input')
    expect(input.classes()).toContain('tvu-input--filled')
    expect(input.classes()).toContain('tvu-input--m')
    expect(input.attributes('data-figma-component')).toBe('input box/filled')
  })

  it('CheckBox maps some -> indeterminate and emits figma status values', async () => {
    const wrapper = mount(CheckBox, {
      props: {
        status: 'some',
        enable: 'yes',
      },
      slots: {
        default: 'Option 1',
      },
    })

    expect(wrapper.find('.cb-box--indeterminate').exists()).toBe(true)
    await wrapper.find('label').trigger('click')
    expect(wrapper.emitted('update:status')?.[0]).toEqual(['on'])
  })

  it('CheckBox maps enable=no to disabled checkbox', () => {
    const wrapper = mount(CheckBox, {
      props: {
        status: 'off',
        enable: 'no',
      },
    })

    expect(wrapper.find('.cb--disabled').exists()).toBe(true)
    expect(wrapper.find('label').attributes('data-figma-enable')).toBe('no')
  })

  it('Radio maps status and emits figma values', async () => {
    const wrapper = mount(Radio, {
      props: {
        status: 'off',
        enable: 'yes',
      },
      slots: {
        default: 'Option 1',
      },
    })

    expect(wrapper.find('.radio-circle--selected').exists()).toBe(false)
    await wrapper.find('label').trigger('click')
    expect(wrapper.emitted('update:status')?.[0]).toEqual(['on'])
  })

  it('Switch preserves live state when toggled on', async () => {
    const wrapper = mount(Switch, {
      props: {
        status: 'live',
        enable: 'yes',
        loading: 'no',
      },
    })

    expect(wrapper.find('button').attributes('data-figma-status')).toBe('live')
    await wrapper.find('button').trigger('click')
    expect(wrapper.emitted('update:status')?.[0]).toEqual(['off'])
  })

  it('SelectBoxLine maps line select figma props and uses custom trigger behavior', async () => {
    const wrapper = mount(SelectBoxLine, {
      props: {
        enable: 'off',
        ux: 'error',
        size: 'L',
        options: [{ label: 'One', value: '1' }],
      },
    })

    const selectWrap = wrapper.find('.select-wrap')
    const trigger = wrapper.find('.select-trigger')
    expect(selectWrap.attributes('data-figma-component')).toBe('select box/line')
    expect(selectWrap.attributes('data-figma-size')).toBe('L')
    expect((trigger.element as HTMLButtonElement).disabled).toBe(true)
    expect(wrapper.find('.select-wrap--line').exists()).toBe(true)
    expect(wrapper.find('.select-wrap--error').exists()).toBe(true)

    await wrapper.setProps({ enable: 'on', modelValue: '', placeholder: 'Select...', options: [{ label: 'One', value: '1' }] })
    await wrapper.find('.select-trigger').trigger('click')
    expect(wrapper.find('.dropdown-select').exists()).toBe(true)
  })

  it('SelectBoxFilled maps filled select variant and emits selected value', async () => {
    const wrapper = mount(SelectBoxFilled, {
      props: {
        size: 'M',
        options: [{ label: 'One', value: '1' }],
      },
    })

    expect(wrapper.find('.select-wrap').attributes('data-figma-component')).toBe('select box/filled')
    expect(wrapper.find('.select-wrap--filled').exists()).toBe(true)
    expect(wrapper.find('.select-wrap--m').exists()).toBe(true)

    await wrapper.find('.select-trigger').trigger('click')
    await wrapper.find('.dropdown-item').trigger('click')
    expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['1'])
  })

  it('SelectBoxLine renders multi select values as chips and toggles array values', async () => {
    const wrapper = mount(SelectBoxLine, {
      props: {
        status: 'multi select',
        modelValue: ['1'],
        options: [
          { label: 'One', value: '1' },
          { label: 'Two', value: '2' },
        ],
      },
    })

    expect(wrapper.find('.select-chip').exists()).toBe(true)
    await wrapper.find('.select-trigger').trigger('click')
    const items = wrapper.findAll('.dropdown-item')
    await items[1].trigger('click')
    expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['1', '2']])
  })

  it('SelectBoxLine multiple prop enables multi select sugar without status axis', async () => {
    const wrapper = mount(SelectBoxLine, {
      props: {
        multiple: true,
        modelValue: ['1'],
        options: [
          { label: 'One', value: '1' },
          { label: 'Two', value: '2' },
        ],
      },
    })

    expect(wrapper.find('.select-chip').exists()).toBe(true)
    await wrapper.find('.select-trigger').trigger('click')
    const items = wrapper.findAll('.dropdown-item')
    await items[1].trigger('click')
    expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['1', '2']])
  })

  it('SelectBoxFilled editable prop exposes editable state sugar without mutating ux axis', () => {
    const wrapper = mount(SelectBoxFilled, {
      props: {
        editable: true,
        ux: 'default',
        options: [{ label: 'One', value: '1' }],
      },
    })

    expect(wrapper.find('.select-wrap--editable').exists()).toBe(true)
    expect(wrapper.find('.select-wrap').attributes('data-figma-ux')).toBe('default')
  })

  it('SelectBoxLine renders a leading icon for time feature', () => {
    const wrapper = mount(SelectBoxLine, {
      props: {
        feature: 'time',
        options: [{ label: '09:00', value: '09:00' }],
      },
    })

    expect(wrapper.find('.select-feature-icon').exists()).toBe(true)
  })

  it('InputNumber maps Property 1 into runtime availability', () => {
    const wrapper = mount(InputNumber, {
      props: {
        property1: 'Only Add',
        min: 0,
        max: 10,
      },
    })

    const root = wrapper.find('.inputnum')
    const buttons = wrapper.findAll('button')
    expect(root.attributes('data-figma-component')).toBe('InputNumber')
    expect(root.attributes('data-figma-property1')).toBe('Only Add')
    expect((buttons[0].element as HTMLButtonElement).disabled).toBe(true)
    expect((buttons[1].element as HTMLButtonElement).disabled).toBe(false)
  })

  it('Progress maps Figma theme, status, and size axes into the base component', () => {
    const wrapper = mount(Progress, {
      props: {
        theme: 'light',
        status: 'warning',
        size: 'S',
        value: 60,
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('Progress')
    expect(wrapper.attributes('data-figma-theme')).toBe('light')
    expect(wrapper.attributes('data-figma-status')).toBe('warning')
    expect(wrapper.attributes('data-figma-size')).toBe('S')
    expect(wrapper.find('.progress').classes()).toContain('progress--light')
  })

  it('Rating maps value and re-emits update:value', async () => {
    const wrapper = mount(Rating, {
      props: {
        value: '3',
        readonly: false,
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('Rating')
    expect(wrapper.attributes('data-figma-value')).toBe('3')

    await wrapper.findAll('.rating-star')[4].trigger('click')
    expect(wrapper.emitted('update:value')?.[0]).toEqual(['5'])
  })

  it('Slider maps Figma theme and size into the runtime slider', () => {
    const wrapper = mount(Slider, {
      props: {
        theme: 'light',
        size: 'S',
        modelValue: 24,
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('Slider')
    expect(wrapper.attributes('data-figma-theme')).toBe('light')
    expect(wrapper.attributes('data-figma-size')).toBe('S')
    expect(wrapper.find('.slider').classes()).toContain('slider--light')
    expect(wrapper.find('.slider__input').classes()).toContain('slider__input--s')
  })

  it('Tooltip maps pointing and darkTheme into placement and theme', async () => {
    const wrapper = mount(Tooltip, {
      props: {
        darkTheme: 'on',
        pointing: 'right up',
        content: 'Description',
      },
      slots: {
        default: '<button>Trigger</button>',
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('Tooltip')
    expect(wrapper.attributes('data-figma-dark-theme')).toBe('on')
    expect(wrapper.attributes('data-figma-pointing')).toBe('right up')

    await wrapper.trigger('mouseenter')
    const box = wrapper.find('.tooltip-box')
    expect(box.classes()).toContain('tooltip-box--top-end')
    expect(box.classes()).toContain('tooltip-box--dark')
  })

  it('Notification maps figma status and theme into the runtime notification', () => {
    const wrapper = mount(Notification, {
      props: {
        status: 'secondary warning',
        theme: 'light',
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('Notification')
    expect(wrapper.attributes('data-figma-status')).toBe('secondary warning')
    expect(wrapper.attributes('data-figma-theme')).toBe('light')
    expect(wrapper.find('.notif').classes()).toContain('notif--secondary-warning')
  })

  it('Pagination maps figma type into the runtime composition flags', () => {
    const wrapper = mount(Pagination, {
      props: {
        type: 'Classic',
        total: 240,
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('Pagination')
    expect(wrapper.attributes('data-figma-type')).toBe('Classic')
    expect(wrapper.find('.pg-total').exists()).toBe(true)
    expect(wrapper.find('.pg-jumper').exists()).toBe(true)
  })

  it('Table maps figma align and type into the base table rendering', () => {
    const wrapper = mount(Table, {
      props: {
        align: 'Right',
        type: 'Tbody',
        columns: [{ key: 'amount', title: 'Amount' }],
        data: [{ amount: '$200' }],
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('Table')
    expect(wrapper.attributes('data-figma-align')).toBe('Right')
    expect(wrapper.attributes('data-figma-type')).toBe('Tbody')
    expect(wrapper.find('.tbl').classes()).toContain('tbl--striped')
    expect(wrapper.find('.tbl-cell').classes()).toContain('tbl-cell--right')
  })

  it('TopBar maps figma tag and keeps slot structure', () => {
    const wrapper = mount(TopBar, {
      props: {
        tag: 'After Login',
        title: 'Media Hub',
      },
      slots: {
        left: '<span>TVU</span>',
        menu: '<span>Live</span>',
        'right-content': '<span>User</span>',
      },
    })

    expect(wrapper.attributes('data-figma-component')).toBe('TopBar')
    expect(wrapper.attributes('data-figma-tag')).toBe('After Login')
    expect(wrapper.find('.topbar-title').text()).toBe('Media Hub')
    expect(wrapper.text()).toContain('TVU')
    expect(wrapper.text()).toContain('Live')
    expect(wrapper.text()).toContain('User')
  })
})
