import { mount } from '@vue/test-utils';
import VAlert from './VAlert.vue';
import VIcon from './VIcon.vue'; // VAlert uses VIcon
import { nextTick } from 'vue';

// Mock VIcon
vi.mock('./VIcon.vue', () => ({
  name: 'VIcon',
  props: ['name'],
  template: '<i :class="`mock-icon icon-${name}`"></i>',
}));

describe('VAlert.vue', () => {
  it('renders message prop when no default slot', () => {
    const messageText = 'This is a test alert.';
    const wrapper = mount(VAlert, { props: { message: messageText } });
    expect(wrapper.find('.alert-content').text()).toBe(messageText);
  });

  it('renders default slot content instead of message prop', () => {
    const slotContent = '<strong>Custom Alert Content</strong>';
    const wrapper = mount(VAlert, {
      props: { message: 'Ignored message' },
      slots: { default: slotContent },
    });
    expect(wrapper.find('.alert-content').html()).toContain(slotContent);
  });

  it('applies correct class based on type prop', () => {
    const wrapperInfo = mount(VAlert, { props: { type: 'info' } });
    expect(wrapperInfo.classes()).toContain('alert-info');

    const wrapperSuccess = mount(VAlert, { props: { type: 'success' } });
    expect(wrapperSuccess.classes()).toContain('alert-success');

    const wrapperWarning = mount(VAlert, { props: { type: 'warning' } });
    expect(wrapperWarning.classes()).toContain('alert-warning');

    const wrapperError = mount(VAlert, { props: { type: 'error' } });
    expect(wrapperError.classes()).toContain('alert-error');
  });

  it('shows close button and emits events when closable is true', async () => {
    const wrapper = mount(VAlert, { props: { closable: true, modelValue: true } });
    const closeButton = wrapper.find('.alert-close-btn');
    expect(closeButton.exists()).toBe(true);

    await closeButton.trigger('click');
    expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
    expect(wrapper.emitted()['update:modelValue'][0]).toEqual([false]);
    expect(wrapper.emitted()['close']).toBeTruthy();

    // Check if alert is hidden after internalModelValue updates (due to transition)
    await nextTick(); // Allow internalModelValue to update and transition to start
    // Depending on how transition is handled, the element might still be in DOM but display:none
    // or completely removed. VAlert uses v-if, so it should be removed.
    // Forcing internalModelValue directly for test simplicity if needed, or wait for transition.
    // wrapper.vm.internalModelValue = false; // If directly manipulating for test
    // await nextTick();
    expect(wrapper.find('.alert').exists()).toBe(false); // After click and model update, it should be gone
  });

  it('does not show close button when closable is false (default)', () => {
    const wrapper = mount(VAlert);
    expect(wrapper.find('.alert-close-btn').exists()).toBe(false);
  });

  it('displays icon by default and uses type-specific default icons', () => {
    const wrapperSuccess = mount(VAlert, { props: { type: 'success' } });
    expect(wrapperSuccess.find('.alert-icon').exists()).toBe(true);
    expect(wrapperSuccess.find('.icon-check-circle').exists()).toBe(true); // Mocked VIcon class

    const wrapperError = mount(VAlert, { props: { type: 'error' } });
    expect(wrapperError.find('.icon-alert-octagon').exists()).toBe(true);
  });

  it('displays custom icon when icon prop is provided', () => {
    const customIconName = 'custom-bell';
    const wrapper = mount(VAlert, { props: { icon: customIconName } });
    expect(wrapper.find('.alert-icon').exists()).toBe(true);
    expect(wrapper.find(`.icon-${customIconName}`).exists()).toBe(true);
  });

  it('does not display icon when showIcon is false', () => {
    const wrapper = mount(VAlert, { props: { showIcon: false } });
    expect(wrapper.find('.alert-icon').exists()).toBe(false);
  });

  it('renders actions slot content', () => {
    const actionsContent = '<button>Retry</button>';
    const wrapper = mount(VAlert, {
      slots: { actions: actionsContent },
    });
    const actionsDiv = wrapper.find('.alert-actions');
    expect(actionsDiv.exists()).toBe(true);
    expect(actionsDiv.html()).toContain(actionsContent);
  });

  it('does not render .alert-actions if slot is not provided', () => {
    const wrapper = mount(VAlert);
    expect(wrapper.find('.alert-actions').exists()).toBe(false);
  });

  it('is visible by default (modelValue true)', () => {
    const wrapper = mount(VAlert);
    expect(wrapper.find('.alert').exists()).toBe(true);
  });

  it('is hidden when modelValue is initially false', () => {
    const wrapper = mount(VAlert, { props: { modelValue: false } });
    expect(wrapper.find('.alert').exists()).toBe(false);
  });

  it('updates visibility when modelValue prop changes', async () => {
    const wrapper = mount(VAlert, { props: { modelValue: true } });
    expect(wrapper.find('.alert').exists()).toBe(true);

    await wrapper.setProps({ modelValue: false });
    // Wait for transition if any, or internalModelValue update
    await nextTick();
    expect(wrapper.find('.alert').exists()).toBe(false);

    await wrapper.setProps({ modelValue: true });
    await nextTick();
    expect(wrapper.find('.alert').exists()).toBe(true);
  });
});
