import { mount } from '@vue/test-utils';
import VButton from './VButton.vue';
import VIcon from './VIcon.vue'; // Import VIcon as it's a child component
import { describe, it, expect, vi } from 'vitest';

// Mock VIcon to simplify testing VButton in isolation if needed,
// or allow it to render if its behavior is simple and reliable.
// For now, we'll allow it to render as it's part of the visual output.

describe('VButton.vue', () => {
  it('renders with default props', () => {
    const wrapper = mount(VButton);
    expect(wrapper.text()).toBe('Button');
    expect(wrapper.classes()).toContain('btn');
    expect(wrapper.classes()).toContain('btn-primary');
    expect(wrapper.classes()).toContain('btn-md');
    expect(wrapper.attributes('type')).toBe('button');
    expect(wrapper.attributes('disabled')).toBeUndefined();
  });

  it('renders with specified label', () => {
    const wrapper = mount(VButton, { props: { label: 'Click Me' } });
    expect(wrapper.text()).toBe('Click Me');
  });

  it('renders with slot content', () => {
    const wrapper = mount(VButton, {
      slots: {
        default: '<i>Slot Content</i>',
      },
    });
    expect(wrapper.html()).toContain('<i>Slot Content</i>');
  });

  it('applies variant classes', () => {
    const wrapper = mount(VButton, { props: { variant: 'secondary' } });
    expect(wrapper.classes()).toContain('btn-secondary');
  });

  it('applies size classes', () => {
    const wrapper = mount(VButton, { props: { size: 'sm' } });
    expect(wrapper.classes()).toContain('btn-sm');
  });

  it('is disabled when disabled prop is true', () => {
    const wrapper = mount(VButton, { props: { disabled: true } });
    expect(wrapper.attributes('disabled')).toBeDefined();
    expect(wrapper.classes()).toContain('btn-disabled');
  });

  it('emits click event when not disabled', async () => {
    const handleClick = vi.fn();
    const wrapper = mount(VButton, {
      attrs: {
        onClick: handleClick, // For native event handling by test runner
      }
    });
    await wrapper.trigger('click');
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('emits click event via emits options when not disabled', async () => {
    const wrapper = mount(VButton);
    await wrapper.trigger('click');
    expect(wrapper.emitted().click).toBeTruthy();
    expect(wrapper.emitted().click.length).toBe(1);
  });

  it('does not emit click event when disabled', async () => {
    const handleClick = vi.fn();
    const wrapper = mount(VButton, {
      props: { disabled: true },
      attrs: {
        onClick: handleClick, // For native event handling by test runner
      }
    });
    await wrapper.trigger('click');
    expect(handleClick).not.toHaveBeenCalled();

    // Check emitted events from component as well
    const wrapperEmitted = mount(VButton, { props: { disabled: true } });
    await wrapperEmitted.trigger('click');
    expect(wrapperEmitted.emitted().click).toBeUndefined();
  });

  it('renders left icon', () => {
    const wrapper = mount(VButton, {
      props: { iconLeft: 'search' },
      // Global stubs or components might be needed if VIcon isn't registered globally for tests
      global: { components: { VIcon } }
    });
    const icon = wrapper.findComponent(VIcon);
    expect(icon.exists()).toBe(true);
    expect(icon.props('name')).toBe('search');
    expect(wrapper.text()).toContain('Button'); // Label should still be there
  });

  it('renders right icon', () => {
    const wrapper = mount(VButton, {
      props: { iconRight: 'alert' },
      global: { components: { VIcon } }
    });
    const icon = wrapper.findComponent(VIcon);
    expect(icon.exists()).toBe(true);
    expect(icon.props('name')).toBe('alert');
  });

  it('renders icon only button', () => {
    const wrapper = mount(VButton, {
      props: { iconLeft: 'close', iconOnly: true, label: 'Close' },
      global: { components: { VIcon } }
    });
    const icon = wrapper.findComponent(VIcon);
    expect(icon.exists()).toBe(true);
    expect(icon.props('name')).toBe('close');
    expect(wrapper.classes()).toContain('btn-icon-only');
    // Label should be visually hidden but present for accessibility
    const labelSpan = wrapper.find('span');
    expect(labelSpan.exists()).toBe(true);
    expect(labelSpan.classes()).toContain('sr-only');
    expect(labelSpan.text()).toBe('Close');
  });

  it('renders icon only button with iconRight', () => {
    const wrapper = mount(VButton, {
      props: { iconRight: 'search', iconOnly: true, label: 'Search' },
      global: { components: { VIcon } }
    });
    const icon = wrapper.findComponent(VIcon);
    expect(icon.exists()).toBe(true);
    expect(icon.props('name')).toBe('search');
    expect(wrapper.classes()).toContain('btn-icon-only');
  });

  it('validates variant prop', () => {
    const validator = VButton.props.variant.validator;
    expect(validator('primary')).toBe(true);
    expect(validator('secondary')).toBe(true);
    expect(validator('neutral')).toBe(true);
    expect(validator('danger')).toBe(true);
    expect(validator('invalid-variant')).toBe(false);
  });

  it('validates size prop', () => {
    const validator = VButton.props.size.validator;
    expect(validator('sm')).toBe(true);
    expect(validator('md')).toBe(true);
    expect(validator('lg')).toBe(true);
    expect(validator('xl')).toBe(false);
  });

  it('validates type prop', () => {
    const validator = VButton.props.type.validator;
    expect(validator('button')).toBe(true);
    expect(validator('submit')).toBe(true);
    expect(validator('reset')).toBe(true);
    expect(validator('link')).toBe(false);
  });
});
