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

const showFloatingItemMock = vi.fn();
const hideFloatingItemMock = vi.fn();

vi.mock('../sidebar/use-floating-item.composable', () => ({
  useFloatingItem: () => ({
    showFloatingItem: showFloatingItemMock,
    hideFloatingItem: hideFloatingItemMock,
  }),
}));

import MSidebarNavItem from './MSidebarNavItem.vue';
import { h } from 'vue';
import { EXPANDED_SIDEBAR_KEY, SUB_ITEM_KEY } from '../sidebar/MSidebar.const';

const DummyIcon = {
  name: 'DummyIcon',
  render() {
    return h('svg', { class: 'dummy-icon' });
  },
};

describe('MSidebarNavItem', () => {
  it('renders label, href and aria-label', () => {
    const wrapper = mount(MSidebarNavItem, {
      props: { label: 'Home', href: '/home' },
      global: {
        provide: { [EXPANDED_SIDEBAR_KEY]: true, [SUB_ITEM_KEY]: false },
      },
    });

    const a = wrapper.get('a');
    expect(a.attributes('href')).toBe('/home');
    expect(a.attributes('aria-label')).toBe('Home');
    expect(wrapper.get('.mc-sidebar__text').text()).toBe('Home');
  });

  it('renders the passed icon component', () => {
    const wrapper = mount(MSidebarNavItem, {
      props: { label: 'Item', href: '#', icon: DummyIcon },
      global: {
        provide: { [EXPANDED_SIDEBAR_KEY]: true, [SUB_ITEM_KEY]: false },
      },
    });

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

  it('uses _blank target and shows ExternalLink24 when external is true', () => {
    const wrapper = mount(MSidebarNavItem, {
      props: { label: 'Ext', href: '/ext', external: true },
      global: {
        provide: { [EXPANDED_SIDEBAR_KEY]: true, [SUB_ITEM_KEY]: false },
      },
    });

    const a = wrapper.get('a');
    expect(a.attributes('target')).toBe('_blank');
  });

  it('shows Lock24 and locked class when locked is true', () => {
    const wrapper = mount(MSidebarNavItem, {
      props: { label: 'Locked', href: '/locked', locked: true },
      global: {
        provide: { [EXPANDED_SIDEBAR_KEY]: true, [SUB_ITEM_KEY]: false },
      },
    });

    const a = wrapper.get('a');
    expect(a.classes()).toContain('mc-sidebar__link--locked');
  });

  it('applies selected class when active is true', () => {
    const wrapper = mount(MSidebarNavItem, {
      props: { label: 'Active', href: '/active', active: true },
      global: {
        provide: { [EXPANDED_SIDEBAR_KEY]: true, [SUB_ITEM_KEY]: false },
      },
    });

    const a = wrapper.get('a');
    expect(a.classes()).toContain('mc-sidebar__link--selected');
  });

  describe('Component events', () => {
    let wrapper: ReturnType<typeof mount>;

    beforeEach(() => {
      showFloatingItemMock.mockClear();
      hideFloatingItemMock.mockClear();

      wrapper = mount(MSidebarNavItem, {
        props: { label: 'Item label', href: '#' },
        global: {
          provide: {
            [EXPANDED_SIDEBAR_KEY]: true,
            [SUB_ITEM_KEY]: false,
          },
        },
      });
    });

    it('calls showFloatingItem on mouseenter and focus', async () => {
      const anchor = wrapper.find('a');
      await anchor.trigger('mouseenter');
      await anchor.trigger('focus');
      expect(showFloatingItemMock).toHaveBeenCalledTimes(2);
    });

    it('calls hideFloatingItem on mouseleave and blur', async () => {
      const anchor = wrapper.find('a');
      await anchor.trigger('mouseleave');
      await anchor.trigger('blur');
      expect(hideFloatingItemMock).toHaveBeenCalledTimes(2);
    });

    it('emits click when anchor is clicked', async () => {
      const anchor = wrapper.find('a');
      await anchor.trigger('click');
      expect(wrapper.emitted()).toHaveProperty('click');
      expect(wrapper.emitted('click')?.[0]).toHaveLength(1);
    });
  });
});
