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

import MAccordionList from './MAccordionList.vue';
import {
  AccordionStateKey,
  AccordionToggleFnKey,
} from './m-accordion-list.const';

const AccordionItemsMock = defineComponent({
  setup() {
    const toggle = inject(AccordionToggleFnKey)!;
    const openIds = inject(AccordionStateKey);
    return { toggle, openIds };
  },
  template: `
      <div>
        <button id="a" @click="toggle('a')" />
        <button id="b" @click="toggle('b')" />
      </div>
    `,
});

describe('MAccordionList', () => {
  it('renders default slot content', () => {
    const wrapper = mount(MAccordionList, {
      slots: {
        default: '<div class="slot-content">Content</div>',
      },
    });

    expect(wrapper.find('.slot-content').exists()).toBe(true);
  });

  it('applies ghost modifier class when appearance is ghost', () => {
    const wrapper = mount(MAccordionList, {
      props: {
        appearance: 'ghost',
      },
    });

    expect(wrapper.classes()).toContain('mc-accordion--ghost');
  });

  it('does not apply ghost modifier class by default', () => {
    const wrapper = mount(MAccordionList);

    expect(wrapper.classes()).not.toContain('mc-accordion--ghost');
  });

  it('provides openIds state based on modelValue', async () => {
    const wrapper = mount(MAccordionList, {
      props: {
        modelValue: ['a', 'b'],
      },
      slots: {
        default: AccordionItemsMock,
      },
    });

    const consumer = wrapper.findComponent(AccordionItemsMock);
    expect(consumer.vm.openIds).toEqual(['a', 'b']);
  });

  it('emits update:modelValue when toggling in multiple mode', async () => {
    const wrapper = mount(MAccordionList, {
      props: {
        modelValue: [],
        behavior: 'multiple',
      },
      slots: {
        default: AccordionItemsMock,
      },
    });

    await wrapper.findAll('button')[0].trigger('click');

    expect(wrapper.emitted('update:modelValue')).toEqual([[['a']]]);
  });

  it('adds and removes ids in multiple behavior', async () => {
    const Parent = defineComponent({
      components: { MAccordionList, AccordionItemsMock },
      data() {
        return {
          value: ['a'],
        };
      },
      template: `
      <MAccordionList v-model="value" behavior="multiple">
        <AccordionItemsMock />
      </MAccordionList>
    `,
    });

    const wrapper = mount(Parent);

    await wrapper.find('#b').trigger('click');
    expect(wrapper.vm.value).toEqual(['a', 'b']);

    await wrapper.find('#a').trigger('click');
    expect(wrapper.vm.value).toEqual(['b']);
  });

  it('allows only one open item in single behavior', async () => {
    const wrapper = mount(MAccordionList, {
      props: {
        modelValue: ['a'],
        behavior: 'single',
      },
      slots: {
        default: AccordionItemsMock,
      },
    });

    await wrapper.find('#b').trigger('click');
    expect(wrapper.emitted('update:modelValue')?.[0][0]).toEqual(['b']);
  });

  it('closes the open item when toggled again in single mode', async () => {
    const wrapper = mount(MAccordionList, {
      props: {
        modelValue: ['a'],
        behavior: 'single',
      },
      slots: {
        default: AccordionItemsMock,
      },
    });

    await wrapper.findAll('button')[0].trigger('click');

    expect(wrapper.emitted('update:modelValue')?.[0][0]).toEqual([]);
  });
});
