import { mount } from '@vue/test-utils';
import { describe, it, expect } from 'vitest';
import MBuiltInMenu, { type MenuItem } from './MBuiltInMenu.vue';
import { defineComponent } from 'vue';

// Dummy icon component to simulate passed icon
const DummyIcon = defineComponent({
  name: 'DummyIcon',
  template: '<svg class="dummy-icon" />',
});

const items: MenuItem[] = [
  { label: 'Item 1', icon: DummyIcon },
  { label: 'Item 2', href: '/foo', target: '_blank' },
  { label: 'Item 3' },
];

describe('MBuiltInMenu', () => {
  it('renders all item labels', () => {
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: undefined },
    });
    const labels = wrapper.findAll('.mc-built-in-menu__label');
    expect(labels.length).toBe(3);
    expect(labels[0].text()).toBe('Item 1');
    expect(labels[1].text()).toBe('Item 2');
    expect(labels[2].text()).toBe('Item 3');
  });

  it('uses correct tags for link and buttons', () => {
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: undefined },
    });
    expect(wrapper.findAll('a').length).toBe(1);
    expect(wrapper.findAll('button').length).toBe(2);

    const links = wrapper.findAll('.mc-built-in-menu__link');
    const buttons = wrapper.findAll('.mc-built-in-menu__button');
    expect(links.length).toBe(1);
    expect(buttons.length).toBe(2);
  });

  it('renders an anchor with href and provided target', () => {
    const items: MenuItem[] = [
      { label: 'Anchor', href: '/path', target: '_blank' },
    ];
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: undefined },
    });

    const a = wrapper.find('a');
    expect(a).not.toBeNull();
    expect(a?.attributes('href')).toBe('/path');
    expect(a?.attributes('target')).toBe('_blank');
  });

  it('renders a router-link with to and default target when target omitted', () => {
    const items: MenuItem[] = [{ label: 'Router', to: '/route' }];
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: undefined },
    });

    const routerLink = wrapper.find('router-link');
    expect(routerLink).not.toBeNull();
    expect(routerLink?.attributes('to')).toBe('/route');
    expect(routerLink?.attributes('target')).toBe('_self');
  });

  it('emits update:modelValue when an item is clicked', async () => {
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: undefined },
    });
    const menuItems = wrapper.findAll(
      '.mc-built-in-menu__button, .mc-built-in-menu__link',
    );

    await menuItems[1].trigger('click');
    const emitted = wrapper.emitted('update:modelValue');
    expect(emitted).toBeTruthy();
    expect(emitted![0][0]).toBe(1);
  });

  it('marks the selected item with aria-current and selected class', () => {
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: 2 },
    });
    const lis = wrapper.findAll('li');
    const selectedItem = lis[2];
    // aria-current is on the interactive element, not the <li> container
    const interactiveEl = selectedItem.find('button, a');
    expect(interactiveEl.attributes('aria-current')).toBe('true');
    expect(selectedItem.classes()).toContain(
      'mc-built-in-menu__item--selected',
    );
  });

  it('renders provided icon component inside the item', () => {
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: undefined },
    });
    const firstItem = wrapper.findAll('li')[0];
    expect(firstItem.find('.dummy-icon').exists()).toBe(true);
  });

  it('applies outlined class when outlined prop is true', () => {
    const wrapper = mount(MBuiltInMenu, {
      props: { items, modelValue: undefined, outlined: true },
    });
    expect(wrapper.find('nav').classes()).toContain(
      'mc-built-in-menu--outlined',
    );
  });

  it('uses default aria-label "Menu" on nav when label prop is not provided', () => {
    const wrapper = mount(MBuiltInMenu, { props: { items } });
    expect(wrapper.find('nav').attributes('aria-label')).toBe('Menu');
  });

  it('uses custom label prop as aria-label on nav', () => {
    const wrapper = mount(MBuiltInMenu, {
      props: { items, label: 'Settings navigation' },
    });
    expect(wrapper.find('nav').attributes('aria-label')).toBe(
      'Settings navigation',
    );
  });

  it('sets aria-hidden on ChevronRight and item icons', () => {
    const wrapper = mount(MBuiltInMenu, { props: { items } });
    // All SVG icons inside items should be aria-hidden
    const ariaHiddenIcons = wrapper.findAll('[aria-hidden="true"]');
    expect(ariaHiddenIcons.length).toBeGreaterThan(0);
  });

  it('does not put aria-current on the <li>, only on the interactive element', () => {
    const wrapper = mount(MBuiltInMenu, { props: { items, modelValue: 0 } });
    const li = wrapper.findAll('li')[0];
    expect(li.attributes('aria-current')).toBeUndefined();
    const interactive = li.find('button, a');
    expect(interactive.attributes('aria-current')).toBe('true');
  });
});
