import { describe, it, expect, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import MToaster from './MToaster.vue';
import {
  InfoCircleFilled32,
  WarningCircleFilled32,
  CrossCircleFilled32,
  CheckCircleFilled32,
} from '@mozaic-ds/icons-vue';

describe('MToaster.vue', () => {
  it('renders description text', () => {
    const wrapper = mount(MToaster, {
      props: { description: 'Test message' },
    });
    expect(wrapper.text()).toContain('Test message');
  });

  it('renders correct icon for each status', () => {
    const statuses = {
      success: CheckCircleFilled32,
      warning: WarningCircleFilled32,
      error: CrossCircleFilled32,
      info: InfoCircleFilled32,
    };

    for (const [status, component] of Object.entries(statuses)) {
      const wrapper = mount(MToaster, {
        props: { description: 'Test', status },
      });
      expect(wrapper.findComponent(component).exists()).toBe(true);
    }
  });

  it('applies the correct classes for status and position', () => {
    const wrapper = mount(MToaster, {
      props: {
        description: 'Toast',
        status: 'error',
        position: 'bottom-center',
      },
    });

    expect(wrapper.classes()).toContain('mc-toaster--error');
    expect(wrapper.classes()).toContain('mc-toaster--bottom-center');
  });

  it('renders close button when closable is true', () => {
    const wrapper = mount(MToaster, {
      props: { description: 'Closable toast', closable: true },
    });

    expect(wrapper.find('.mc-toaster__close').exists()).toBe(true);
  });

  it('does not render close button when closable is false', () => {
    const wrapper = mount(MToaster, {
      props: { description: 'Non-closable toast', closable: false },
    });

    expect(wrapper.find('.mc-toaster__close').exists()).toBe(false);
  });

  it('emits update:open event with false when close button is clicked', async () => {
    const wrapper = mount(MToaster, {
      props: { description: 'Closable toast', closable: true },
    });

    await wrapper.find('.mc-toaster__close').trigger('click');
    expect(wrapper.emitted('update:open')).toBeTruthy();
    expect(wrapper.emitted('update:open')![0]).toEqual([false]);
  });

  it('renders action slot when provided', () => {
    const wrapper = mount(MToaster, {
      props: { description: 'With action' },
      slots: {
        action: '<button class="custom-action">Retry</button>',
      },
    });

    const action = wrapper.find('.mc-toaster__action');
    expect(action.exists()).toBe(true);
    expect(action.text()).toContain('Retry');
  });

  it('does not render action slot wrapper if slot is not provided', () => {
    const wrapper = mount(MToaster, {
      props: { description: 'No action' },
    });

    expect(wrapper.find('.mc-toaster__action').exists()).toBe(false);
  });

  it('renders progress bar when progress is true', () => {
    const wrapper = mount(MToaster, {
      props: { description: 'Progress toast', progress: true, timeout: 1000 },
    });
    expect(
      wrapper.findComponent({ name: 'MLinearProgressbarBuffer' }).exists(),
    ).toBe(true);
  });

  it('auto-closes after timeout and updates progress bar', async () => {
    vi.useFakeTimers();

    const wrapper = mount(MToaster, {
      props: { description: 'Auto close toast', progress: true, timeout: 500 },
    });

    expect(
      wrapper.findComponent({ name: 'MLinearProgressbarBuffer' }).exists(),
    ).toBe(true);

    expect(wrapper.vm.progressValue).toBe(0);

    vi.advanceTimersByTime(600);

    expect(wrapper.emitted('update:open')).toBeTruthy();
    expect(wrapper.emitted('update:open')!.pop()).toEqual([false]);

    vi.useRealTimers();
  });
});
