import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import MQuantitySelector from './MQuantitySelector.vue';

describe('MQuantitySelector component', () => {
  it('renders the component with default values', () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
      },
    });

    const input = wrapper.find('input');
    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    const decreaseButton = wrapper.find(
      '.mc-quantity-selector__button--decrease',
    );

    expect(input.exists()).toBe(true);
    expect(input.element.value).toBe('1');
    expect(input.attributes('min')).toBe('1');
    expect(input.attributes('max')).toBe('100');
    expect(input.attributes('step')).toBe('1');

    expect(increaseButton.exists()).toBe(true);
    expect(decreaseButton.exists()).toBe(true);
    expect(increaseButton.attributes('disabled')).toBeUndefined();
    expect(decreaseButton.attributes('disabled')).toBeDefined();
  });

  it('emits an update when value changes via input', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        modelValue: 5,
      },
    });

    const input = wrapper.find('input');
    await input.setValue(10);

    const emittedValue = wrapper.emitted('update:modelValue');
    expect(emittedValue).toBeTruthy();
    expect(emittedValue?.[0]).toEqual([10]);
  });

  it('increments value when increase button is clicked', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        modelValue: 5,
        max: 10,
        step: 1,
      },
    });

    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    await increaseButton.trigger('click');

    const input = wrapper.find('input');
    expect(input.element.value).toBe('6');
  });

  it('decrements value when decrease button is clicked', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        modelValue: 5,
        min: 1,
        step: 1,
      },
    });

    const decreaseButton = wrapper.find(
      '.mc-quantity-selector__button--decrease',
    );
    await decreaseButton.trigger('click');

    const input = wrapper.find('input');
    expect(input.element.value).toBe('4');
  });

  it('does not increment beyond max value', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        modelValue: 10,
        max: 10,
        step: 1,
      },
    });

    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    await increaseButton.trigger('click');

    const input = wrapper.find('input');
    expect(input.element.value).toBe('10');
  });

  it('does not decrement below min value', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        modelValue: 1,
        min: 1,
        step: 1,
      },
    });

    const decreaseButton = wrapper.find(
      '.mc-quantity-selector__button--decrease',
    );
    await decreaseButton.trigger('click');

    const input = wrapper.find('input');
    expect(input.element.value).toBe('1');
  });

  it('disables input and buttons when disabled prop is true', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        disabled: true,
      },
    });

    const input = wrapper.find('input');
    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    const decreaseButton = wrapper.find(
      '.mc-quantity-selector__button--decrease',
    );

    expect(input.attributes('disabled')).toBeDefined();
    expect(increaseButton.attributes('disabled')).toBeDefined();
    expect(decreaseButton.attributes('disabled')).toBeDefined();
  });

  it('renders with custom size class', () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        size: 's',
      },
    });

    const div = wrapper.find('.mc-quantity-selector');
    expect(div.classes()).toContain('mc-quantity-selector--s');
  });

  it('hides increase and decrease buttons when readonly is true', () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        readonly: true,
      },
    });

    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    const decreaseButton = wrapper.find(
      '.mc-quantity-selector__button--decrease',
    );

    expect(increaseButton.exists()).toBe(false);
    expect(decreaseButton.exists()).toBe(false);
  });

  it('renders and tests aria-label and aria-invalid for accessibility', () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        isInvalid: true,
        ariaLabel: 'Select quantity',
      },
    });

    const input = wrapper.find('input');
    expect(input.attributes('aria-label')).toBe('Select quantity');
    expect(input.attributes('aria-invalid')).toBe('true');
  });

  it('does not allow invalid input values (non-numeric)', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
      },
    });

    const input = wrapper.find('input');
    await input.setValue('abc');
    expect(input.element.value).toBe('1');
  });

  it('supports custom step values', async () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        modelValue: 10,
        step: 5,
      },
    });

    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    await increaseButton.trigger('click');

    const input = wrapper.find('input');
    expect(input.element.value).toBe('15');
  });

  it('renders custom increment and decrement labels', () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
        incrementlabel: 'Increase Quantity',
        decrementLabel: 'Decrease Quantity',
      },
    });

    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    const decreaseButton = wrapper.find(
      '.mc-quantity-selector__button--decrease',
    );

    expect(increaseButton.text()).toBe('Increase Quantity');
    expect(decreaseButton.text()).toBe('Decrease Quantity');
  });

  it('correctly sets aria-controls', () => {
    const wrapper = mount(MQuantitySelector, {
      props: {
        id: 'quantity-selector-1',
      },
    });

    const increaseButton = wrapper.find(
      '.mc-quantity-selector__button--increase',
    );
    const decreaseButton = wrapper.find(
      '.mc-quantity-selector__button--decrease',
    );

    expect(increaseButton.attributes('aria-controls')).toBe(
      'quantity-selector-1',
    );
    expect(decreaseButton.attributes('aria-controls')).toBe(
      'quantity-selector-1',
    );
  });
});
