import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TrackListEmpty } from './TrackListEmpty';

describe('TrackListEmpty', () => {
  it('should render empty state', () => {
    render(<TrackListEmpty />);
    expect(screen.getByText('Aucune piste disponible')).toBeInTheDocument();
  });

  it('should display custom message', () => {
    render(<TrackListEmpty message="Pas de résultats" />);
    expect(screen.getByText('Pas de résultats')).toBeInTheDocument();
  });

  it('should display default description for music icon', () => {
    render(<TrackListEmpty icon="music" />);
    expect(
      screen.getByText('Commencez par ajouter des pistes à votre bibliothèque'),
    ).toBeInTheDocument();
  });

  it('should display default description for search icon', () => {
    render(<TrackListEmpty icon="search" hasSearch={true} />);
    const descriptions = screen.getAllByText(
      /Essayez de modifier vos critères de recherche/,
    );
    expect(descriptions.length).toBeGreaterThan(0);
  });

  it('should display default description for filter icon', () => {
    render(<TrackListEmpty icon="filter" hasFilters={true} />);
    const descriptions = screen.getAllByText(/Essayez de modifier vos filtres/);
    expect(descriptions.length).toBeGreaterThan(0);
  });

  it('should display custom description', () => {
    render(<TrackListEmpty description="Description personnalisée" />);
    expect(screen.getByText('Description personnalisée')).toBeInTheDocument();
  });

  it('should display action when provided', () => {
    render(<TrackListEmpty action={<button>Ajouter une piste</button>} />);
    expect(screen.getByText('Ajouter une piste')).toBeInTheDocument();
  });

  it('should display music icon by default', () => {
    const { container } = render(<TrackListEmpty />);
    const svg = container.querySelector('svg');
    expect(svg).toBeInTheDocument();
  });

  it('should display search icon when icon prop is search', () => {
    const { container } = render(<TrackListEmpty icon="search" />);
    const svg = container.querySelector('svg');
    expect(svg).toBeInTheDocument();
  });

  it('should display filter icon when icon prop is filter', () => {
    const { container } = render(<TrackListEmpty icon="filter" />);
    const svg = container.querySelector('svg');
    expect(svg).toBeInTheDocument();
  });

  it('should apply custom className', () => {
    const { container } = render(<TrackListEmpty className="custom-class" />);
    const empty = container.querySelector('[role="status"]');
    expect(empty).toHaveClass('custom-class');
  });

  it('should have accessible attributes', () => {
    render(<TrackListEmpty />);
    const status = screen.getByRole('status');
    expect(status).toHaveAttribute('aria-live', 'polite');
  });

  describe('Empty state types', () => {
    it('should display no-tracks state by default', () => {
      render(<TrackListEmpty />);
      expect(screen.getByText('Aucune piste disponible')).toBeInTheDocument();
      expect(
        screen.getByText(
          'Commencez par ajouter des pistes à votre bibliothèque',
        ),
      ).toBeInTheDocument();
    });

    it('should display no-results state when type is no-results', () => {
      render(<TrackListEmpty type="no-results" />);
      expect(screen.getByText('Aucun résultat trouvé')).toBeInTheDocument();
    });

    it('should display error state when type is error', () => {
      render(<TrackListEmpty type="error" />);
      expect(screen.getByText('Erreur lors du chargement')).toBeInTheDocument();
      const errorDescriptions = screen.getAllByText(/Une erreur est survenue/);
      expect(errorDescriptions.length).toBeGreaterThan(0);
    });

    it('should automatically determine no-results type when hasFilters is true', () => {
      render(<TrackListEmpty hasFilters={true} />);
      expect(screen.getByText('Aucun résultat trouvé')).toBeInTheDocument();
    });

    it('should automatically determine no-results type when hasSearch is true', () => {
      render(<TrackListEmpty hasSearch={true} />);
      expect(screen.getByText('Aucun résultat trouvé')).toBeInTheDocument();
    });

    it('should display appropriate description when hasFilters and hasSearch are both true', () => {
      render(<TrackListEmpty hasFilters={true} hasSearch={true} />);
      const descriptions = screen.getAllByText(
        /modifier vos critères de recherche ou vos filtres/,
      );
      expect(descriptions.length).toBeGreaterThan(0);
    });
  });

  describe('Error state', () => {
    it('should display error icon when type is error', () => {
      const { container } = render(<TrackListEmpty type="error" />);
      const svg = container.querySelector('svg');
      expect(svg).toBeInTheDocument();
    });

    it('should use alert role for error state', () => {
      render(<TrackListEmpty type="error" />);
      const alert = screen.getByRole('alert');
      expect(alert).toBeInTheDocument();
      expect(alert).toHaveAttribute('aria-live', 'assertive');
    });

    it('should display retry button when onRetry is provided', () => {
      const mockRetry = vi.fn();
      render(<TrackListEmpty type="error" onRetry={mockRetry} />);
      const retryButton = screen.getByLabelText('Réessayer');
      expect(retryButton).toBeInTheDocument();
    });

    it('should call onRetry when retry button is clicked', async () => {
      const user = userEvent.setup();
      const mockRetry = vi.fn();
      render(<TrackListEmpty type="error" onRetry={mockRetry} />);

      const retryButton = screen.getByLabelText('Réessayer');
      await user.click(retryButton);

      expect(mockRetry).toHaveBeenCalledTimes(1);
    });

    it('should display both action and retry button', () => {
      const mockRetry = vi.fn();
      render(
        <TrackListEmpty
          type="error"
          onRetry={mockRetry}
          action={<button>Action personnalisée</button>}
        />,
      );
      expect(screen.getByText('Action personnalisée')).toBeInTheDocument();
      expect(screen.getByLabelText('Réessayer')).toBeInTheDocument();
    });
  });

  describe('Icon colors', () => {
    it('should apply error color class for error type', () => {
      const { container } = render(<TrackListEmpty type="error" />);
      const svg = container.querySelector('svg');
      expect(svg).toHaveClass('text-red-500');
    });

    it('should apply default color class for non-error types', () => {
      const { container } = render(<TrackListEmpty type="no-tracks" />);
      const svg = container.querySelector('svg');
      expect(svg).toHaveClass('text-gray-400');
    });
  });

  describe('Text colors', () => {
    it('should apply error text colors for error type', () => {
      const { container } = render(<TrackListEmpty type="error" />);
      const heading = container.querySelector('h3');
      expect(heading).toHaveClass('text-red-900');
    });

    it('should apply default text colors for non-error types', () => {
      const { container } = render(<TrackListEmpty type="no-tracks" />);
      const heading = container.querySelector('h3');
      expect(heading).toHaveClass('text-gray-900');
    });
  });
});
