import { render } from '@testing-library/react';
import React from 'react';
import { describe, expect, it } from 'vitest';
import { SvgElement, SvgElementProps } from './SvgElement';

describe('SvgElement', () => {
  it('renders the component without crashing', () => {
    const { container } = render(<SvgElement />);

    expect(container).toBeTruthy();
  });

  it('renders with default viewBox', () => {
    const { container } = render(<SvgElement />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('viewBox', '0 0 40 40');
  });

  it('renders with custom viewBox', () => {
    const customViewBox = '0 0 24 24';
    const { container } = render(<SvgElement viewBox={customViewBox} />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('viewBox', customViewBox);
  });

  it('passes down className to svg element', () => {
    const testClass = 'custom-icon-class';
    const { container } = render(<SvgElement className={testClass} />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveClass(testClass);
  });

  it('renders children inside svg', () => {
    const d = 'M10 10L20 20';
    const cx = 15;
    const cy = 15;
    const r = 5;
    const { container } = render(
      <SvgElement>
        <path d={d} />
        <circle cx={cx} cy={cy} r={r} />
      </SvgElement>,
    );

    expect(container.querySelectorAll('path')).toHaveLength(1);
    expect(container.querySelectorAll('circle')).toHaveLength(1);
    expect(container.querySelector('path')).toHaveAttribute('d', d);
    expect(container.querySelector('circle')).toHaveAttribute('cx', String(cx));
    expect(container.querySelector('circle')).toHaveAttribute('cy', String(cy));
    expect(container.querySelector('circle')).toHaveAttribute('r', String(r));
  });

  it('renders as decorative icon by default', () => {
    const { container } = render(<SvgElement />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('role', 'presentation');
    expect(svg).toHaveAttribute('aria-hidden', 'true');
    expect(svg).not.toHaveAttribute('aria-label');
  });

  it('renders as semantic icon when aria-label is provided', () => {
    const ariaLabel = 'Custom icon description';
    const { container } = render(<SvgElement aria-label={ariaLabel} />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('role', 'img');
    expect(svg).not.toHaveAttribute('aria-hidden');
    expect(svg).toHaveAttribute('aria-label', ariaLabel);
  });

  it('renders as semantic icon when title is provided', () => {
    const title = 'Icon tooltip';
    const { container } = render(<SvgElement title={title} />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('role', 'img');
    expect(svg).not.toHaveAttribute('aria-hidden');
    expect(container.querySelectorAll('title')).toHaveLength(1);
    expect(container.querySelector('title')!.textContent).toBe(title);
  });

  it('renders as semantic icon when both aria-label and title are provided', () => {
    const ariaLabel = 'Icon description';
    const title = 'Icon tooltip';
    const { container } = render(
      <SvgElement aria-label={ariaLabel} title={title} />,
    );
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('role', 'img');
    expect(svg).not.toHaveAttribute('aria-hidden');
    expect(svg).toHaveAttribute('aria-label', ariaLabel);
    expect(container.querySelectorAll('title')).toHaveLength(1);
    expect(container.querySelector('title')!.textContent).toBe(title);
  });

  it('does not render title element when title prop is not provided', () => {
    const { container } = render(<SvgElement aria-label="Icon" />);

    expect(container.querySelectorAll('title')).toHaveLength(0);
  });

  it('applies default SVG attributes', () => {
    const { container } = render(<SvgElement />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('focusable', 'false');
  });

  it('passes through additional SVG attributes', () => {
    const customProps: SvgElementProps = {
      id: 'custom-id',
      fill: 'currentColor',
      stroke: 'red',
      strokeWidth: '2',
    };
    const { container } = render(<SvgElement {...customProps} />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('id', 'custom-id');
    expect(svg).toHaveAttribute('fill', 'currentColor');
    expect(svg).toHaveAttribute('stroke', 'red');
    expect(svg).toHaveAttribute('stroke-width', '2');
  });

  it('allows overriding default attributes', () => {
    const { container } = render(
      <SvgElement
        version="2.0"
        xmlns="http://custom-namespace.com"
        focusable="true"
      />,
    );
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('version', '2.0');
    expect(svg).toHaveAttribute('xmlns', 'http://custom-namespace.com');
    expect(svg).toHaveAttribute('focusable', 'true');
  });

  it('prioritizes explicit role over calculated role', () => {
    const { container } = render(
      <SvgElement role="button" aria-label="Click me" />,
    );
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('role', 'button');
  });

  it('prioritizes explicit aria-hidden over calculated value', () => {
    const { container } = render(<SvgElement aria-hidden="false" />);
    const svg = container.querySelector('svg')!;

    expect(svg).toHaveAttribute('aria-hidden', 'false');
    expect(svg).toHaveAttribute('role', 'presentation'); // Still decorative without label/title
  });
});
