import { describe, it, expect, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import { defineComponent, ref, type Component } from 'vue';
import MAccordionListItem from './MAccordionListItem.vue';
import {
  AccordionStateKey,
  AccordionToggleFnKey,
} from '../accordionlist/m-accordion-list.const';

type Props = {
  id: string;
  title: string;
  subtitle?: string;
  content?: string;
  icon?: Component;
};

describe('MAccordionListItem', () => {
  function mountItem(props: Props, openIds: string[] = []) {
    const state = ref(openIds);
    const toggle = vi.fn();

    const wrapper = mount(MAccordionListItem, {
      props,
      global: {
        provide: {
          [AccordionStateKey as symbol]: state,
          [AccordionToggleFnKey as symbol]: toggle,
        },
      },
    });

    return { wrapper, state, toggle };
  }

  it('renders title and content', () => {
    const { wrapper } = mountItem({
      id: '1',
      title: 'My Title',
      content: 'My Content',
    });

    expect(wrapper.find('.mc-accordion__title span').text()).toBe('My Title');
    expect(wrapper.find('.mc-accordion__content p').text()).toBe('My Content');
  });

  it('renders subtitle if provided', () => {
    const { wrapper } = mountItem({
      id: '1',
      title: 'Title',
      subtitle: 'Subtitle',
    });

    expect(wrapper.find('.mc-accordion__subtitle').text()).toBe('Subtitle');
  });

  it('renders slot content instead of default content', () => {
    const wrapper = mount(MAccordionListItem, {
      props: { id: '1', title: 'Title', content: 'Default' },
      slots: { default: '<div class="slot-content">Custom Slot</div>' },
      global: {
        provide: {
          [AccordionStateKey as symbol]: ref([]),
          [AccordionToggleFnKey as symbol]: vi.fn(),
        },
      },
    });

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

  it('sets aria-expanded correctly based on openIds', async () => {
    const { wrapper, state } = mountItem({ id: 'item-1', title: 'Title' }, []);

    const button = wrapper.find('button');
    expect(button.attributes('aria-expanded')).toBe('false');

    state.value.push('item-1');
    await wrapper.vm.$nextTick();

    expect(button.attributes('aria-expanded')).toBe('true');
  });

  it('sets inert correctly for content', async () => {
    const { wrapper, state } = mountItem({ id: 'item-1', title: 'Title' }, []);

    const content = wrapper.find('.mc-accordion__content');
    expect(content.attributes('inert')).not.toBeUndefined();

    state.value.push('item-1');
    await wrapper.vm.$nextTick();
    expect(content.attributes('inert')).toBeUndefined();
  });

  it('renders heading with default level h2', () => {
    const { wrapper } = mountItem({ id: '1', title: 'Title' });
    expect(wrapper.find('h2.mc-accordion__title').exists()).toBe(true);
  });

  it('renders heading with custom headingLevel prop', () => {
    const wrapper = mount(MAccordionListItem, {
      props: { id: '1', title: 'Title', tag: 'h3' },
      global: {
        provide: {
          [AccordionStateKey as symbol]: ref([]),
          [AccordionToggleFnKey as symbol]: vi.fn(),
        },
      },
    });
    expect(wrapper.find('h3.mc-accordion__title').exists()).toBe(true);
    expect(wrapper.find('h2').exists()).toBe(false);
  });

  it('calls toggleItem when button is clicked', async () => {
    const { wrapper, toggle } = mountItem({ id: 'item-1', title: 'Title' });

    await wrapper.find('button').trigger('click');
    expect(toggle).toHaveBeenCalledOnce();
    expect(toggle).toHaveBeenCalledWith('item-1');
  });

  it('renders icon if provided', () => {
    const DummyIcon = defineComponent({
      template: '<svg class="dummy-icon" />',
    });
    const { wrapper } = mountItem({ id: '1', title: 'Title', icon: DummyIcon });

    expect(wrapper.find('.mc-accordion__icon').exists()).toBe(true);
    expect(wrapper.find('svg.dummy-icon').exists()).toBe(true);
  });

  it('sets correct aria-controls and aria-labelledby attributes', () => {
    const { wrapper } = mountItem({ id: '42', title: 'Title' });
    const button = wrapper.find('button');
    const content = wrapper.find('.mc-accordion__content');

    expect(button.attributes('aria-controls')).toBe('content-42');
    expect(content.attributes('aria-labelledby')).toBe('accordion-42');
    expect(content.attributes('role')).toBe('region');
  });
});
