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

const globalStubs = {
  MButton: {
    emits: ['click'],
    template: `<button @click="$emit('click', $event)"><slot /></button>`,
  },
  MDivider: {
    template: `<hr />`,
  },
};

describe('MStepperBottomBar component', () => {
  it('renders cancel button by default', () => {
    const wrapper = mount(MStepperBottomBar, {
      global: { stubs: globalStubs },
    });

    expect(wrapper.text()).toContain('Cancel');
  });

  it('does not render cancel button when cancel is false', () => {
    const wrapper = mount(MStepperBottomBar, {
      props: { cancel: false },
      global: { stubs: globalStubs },
    });

    expect(wrapper.text()).not.toContain('Cancel');
  });

  it('does not render previous button when step is 0', () => {
    const wrapper = mount(MStepperBottomBar, {
      props: { modelValue: 0 },
      global: { stubs: globalStubs },
    });

    expect(wrapper.text()).not.toContain('Previous');
  });

  it('renders previous button when step > 0', () => {
    const wrapper = mount(MStepperBottomBar, {
      props: { modelValue: 1 },
      global: { stubs: globalStubs },
    });

    expect(wrapper.text()).toContain('Previous');
  });

  it('emits update:modelValue with decremented value on previous click', async () => {
    const wrapper = mount(MStepperBottomBar, {
      props: { modelValue: 2 },
      global: { stubs: globalStubs },
    });

    const buttons = wrapper.findAll('button');
    const previousButton = buttons.find((b) => b.text() === 'Previous')!;

    await previousButton.trigger('click');

    const emitted = wrapper.emitted('update:modelValue')!;
    expect(emitted.at(-1)).toEqual([1]);
  });

  it('emits update:modelValue with incremented value on next click', async () => {
    const wrapper = mount(MStepperBottomBar, {
      props: {
        modelValue: 1,
        steps: 3,
      },
      global: { stubs: globalStubs },
    });

    const nextButton = wrapper
      .findAll('button')
      .find((b) => b.text() === 'Next')!;

    await nextButton.trigger('click');

    const emitted = wrapper.emitted('update:modelValue')!;
    expect(emitted.at(-1)).toEqual([2]);
  });

  it('emits validate when clicking next on last step', async () => {
    const wrapper = mount(MStepperBottomBar, {
      props: {
        modelValue: 3,
        steps: 3,
      },
      global: { stubs: globalStubs },
    });

    const validateButton = wrapper
      .findAll('button')
      .find((b) => b.text() === 'Validate')!;

    await validateButton.trigger('click');

    expect(wrapper.emitted('validate')).toBeTruthy();
  });

  it('emits cancel when cancel button is clicked', async () => {
    const wrapper = mount(MStepperBottomBar, {
      global: { stubs: globalStubs },
    });

    const cancelButton = wrapper
      .findAll('button')
      .find((b) => b.text() === 'Cancel')!;

    await cancelButton.trigger('click');

    expect(wrapper.emitted('cancel')).toBeTruthy();
  });

  it('renders custom labels', () => {
    const wrapper = mount(MStepperBottomBar, {
      props: {
        cancelLabel: 'Abort',
        previousLabel: 'Back',
        nextLabel: 'Continue',
        validateLabel: 'Submit',
        modelValue: 1,
        steps: 1,
      },
      global: { stubs: globalStubs },
    });

    expect(wrapper.text()).toContain('Abort');
    expect(wrapper.text()).toContain('Back');
    expect(wrapper.text()).toContain('Submit');
  });
});
