import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import KsButton from '../KsButton.vue'
import KsTextField from '../KsTextField.vue'
import { nativeUiAdapter } from '../../adapter/native'
import { uiAdapterKey } from '../../adapter/contracts'

const primeVueHarness = {
  stubs: {
    Button: {
      props: ['label', 'type', 'loading', 'disabled'],
      template: '<button :type="type" :disabled="disabled || loading" @click="$emit(\'click\', $event)">{{ label }}<span v-if="loading">…</span><slot /></button>',
    },
    InputText: {
      props: ['modelValue', 'inputId', 'type', 'disabled', 'invalid', 'placeholder'],
      template: '<input :id="inputId" :value="modelValue" :type="type" :disabled="disabled" :aria-invalid="invalid ? \'true\' : undefined" @input="$emit(\'update:modelValue\', $event.target.value)" />',
    },
  },
}

describe('core shared control contracts', () => {
  it('keeps a loading button disabled and forwards its semantic type', () => {
    const wrapper = mount(KsButton, {
      props: { label: 'Save', type: 'submit', loading: true },
      global: primeVueHarness,
    })

    const button = wrapper.get('button')
    expect(button.attributes()).toMatchObject({ type: 'submit', disabled: '' })
    expect(button.text()).toContain('…')
  })

  it('forwards activation through the vendor-neutral click event', async () => {
    const wrapper = mount(KsButton, {
      props: { label: 'Retry' },
      global: primeVueHarness,
    })

    await wrapper.get('button').trigger('click')
    expect(wrapper.emitted('click')).toBeTruthy()
  })

  it('connects text-field label, invalid state, and model updates', async () => {
    const wrapper = mount(KsTextField, {
      props: { modelValue: 'old', label: 'Name', inputId: 'name', error: 'Required', type: 'email' },
      global: { ...primeVueHarness, provide: { [uiAdapterKey as unknown as string]: nativeUiAdapter } },
    })

    const input = wrapper.get('input')
    expect(wrapper.get('label').attributes('for')).toBe('name')
    expect(input.attributes()).toMatchObject({
      id: 'name',
      type: 'email',
      'aria-describedby': 'name-message',
      'aria-invalid': 'true',
    })
    expect(input.attributes('aria-required')).toBeUndefined()

    await input.setValue('new@example.com')
    expect(wrapper.emitted('update:modelValue')).toEqual([['new@example.com']])
  })
})
