import { render } from '@testing-library/react';
import React, { ReactNode } from 'react';
import ContentLoader from 'react-content-loader';
import type { Mock } from 'vitest';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { Loader } from './Loader';

vi.mock('react-content-loader', async () => {
  const ActualReact = await vi.importActual<typeof import('react')>('react');
  return {
    __esModule: true,
    default: vi.fn(
      ({
        speed: _speed,
        backgroundColor: _bg,
        foregroundColor: _fg,
        children,
        ...svgProps
      }) => ActualReact.createElement('svg', svgProps, children),
    ),
  };
});

const mockedContentLoader = ContentLoader as Mock;

describe('Loader component', () => {
  beforeEach(() => {
    mockedContentLoader.mockClear();
  });

  it('renders the container div if showLoader is set to true', () => {
    const { container } = render(<Loader showLoader={true} />);
    expect(container.querySelector('.container')).toBeInTheDocument();
  });

  it('container div should not be rendered if showLoader is set to false', () => {
    const { container } = render(<Loader showLoader={false} />);
    expect(container.querySelector('.container')).not.toBeInTheDocument();
  });

  it('container is styled with default styles if no optional styles are provided', () => {
    const { container } = render(<Loader showLoader={true} />);
    const loaderContainer = container.querySelector(
      '.container',
    ) as HTMLDivElement;
    expect(loaderContainer.style.width).toBe('100px');
  });

  it('container is styled with the custom width if width is provided with props', () => {
    const width = 120;
    const { container } = render(<Loader showLoader={true} width={width} />);
    const loaderContainer = container.querySelector(
      '.container',
    ) as HTMLDivElement;
    expect(loaderContainer.style.width).toBe(`${width}px`);
  });

  it('replaces default loading SVG with a custom SVG', () => {
    const mockId = 'mock-id';
    const mockSVG: ReactNode = (
      <svg id={mockId}>
        <circle r="50" />
      </svg>
    );

    const { container } = render(
      <Loader showLoader={true} loadingSkeleton={mockSVG} />,
    );

    const svg = container.querySelector(`#${mockId}`);

    expect(svg).toBeInTheDocument();
  });

  it('passes svg viewbox, animation speed, color props to ContentLoader', () => {
    const mockSpeed = 1;
    const mockBackgroundColor = '#CCC';
    const mockForegroundColor = '#FFF';
    const mockViewbox = '75 75 75 75';
    render(
      <Loader
        showLoader={true}
        speed={mockSpeed}
        backgroundColor={mockBackgroundColor}
        foregroundColor={mockForegroundColor}
        viewBox={mockViewbox}
      />,
    );

    const lastCallProps =
      mockedContentLoader.mock.calls[
        mockedContentLoader.mock.calls.length - 1
      ][0];

    expect(lastCallProps.speed).toBe(mockSpeed);
    expect(lastCallProps.backgroundColor).toBe(mockBackgroundColor);
    expect(lastCallProps.foregroundColor).toBe(mockForegroundColor);
    expect(lastCallProps.viewBox).toBe(mockViewbox);
  });

  // Height attr is not tested here since its set inside the SVG image
});
