import { render, screen, mockMatchMedia } from '../test-utils';
import '@testing-library/jest-dom';
import TableCell, {
  TableCellCurrency,
  TableCellLeading,
  TableCellMedia,
  TableCellStatus,
  TableCellText,
} from './TableCell';

mockMatchMedia();

describe('TableCell Component', () => {
  const cellContentMocks = {
    leading: {
      type: 'leading',
      primaryText: 'Alice Johnson',
      secondaryText: 'Frontend Developer',
      avatar: {
        profileName: 'Alice Johnson',
      },
    } satisfies TableCellLeading,
    text: {
      type: 'text',
      text: 'JP, Tokyo',
    } satisfies TableCellText,
    currency: {
      type: 'currency',
      primaryCurrency: {
        amount: 56789.01,
        currency: 'jpy',
      },
      secondaryCurrency: {
        amount: 51000.0,
        currency: 'gbp',
      },
    } satisfies TableCellCurrency,
    status: {
      type: 'status',
      primaryText: 'Overdue',
      secondaryText: '6 days ago',
      sentiment: 'pending',
    } satisfies TableCellStatus,
    media: {
      type: 'media',
      primaryText: 'Media content',
      secondaryText: 'Media secondary content',
      media: {
        src: 'https://via.placeholder.com/150',
        alt: 'Media content alt',
      },
    } satisfies TableCellMedia,
    custom: <div>Custom content</div>,
  };

  it('renders without content', () => {
    render(<TableCell />);
    expect(screen.getByRole('cell')).toBeInTheDocument();
  });

  it('applies `right` alignment class', () => {
    render(<TableCell alignment="right" />);
    expect(screen.getByRole('cell')).toHaveClass('np-table-cell--right');
  });

  it('applies reversed class for cell with image and `right` alignment', () => {
    render(<TableCell cell={cellContentMocks.currency} alignment="right" />);
    expect(screen.getByTestId('np-table-content')).toHaveClass('np-table-content--reversed');
  });

  it('applies custom class', () => {
    render(<TableCell className="custom-class" />);
    expect(screen.getByRole('cell')).toHaveClass('custom-class');
  });

  it('renders with spanned columns', () => {
    render(<TableCell colSpan={2} />);
    expect(screen.getByRole('cell')).toHaveAttribute('colSpan', '2');
  });

  it('renders with `children` as a content', () => {
    render(<TableCell>{cellContentMocks.custom}</TableCell>);
    expect(screen.getByText('Custom content')).toBeInTheDocument();
  });

  it('renders `text` cell type', () => {
    render(<TableCell cell={{ ...cellContentMocks.text }} />);
    expect(screen.getByText('JP, Tokyo')).toBeInTheDocument();
  });

  it('renders `text` cell type with error', () => {
    render(<TableCell cell={{ ...cellContentMocks.text, status: 'error' }} />);
    expect(screen.getByText('JP, Tokyo')).toHaveClass('np-table-content--error');
    expect(screen.getByTestId('alert-icon')).toBeInTheDocument();
  });

  it('renders `text` cell type with success', () => {
    render(<TableCell cell={{ ...cellContentMocks.text, status: 'success' }} />);
    expect(screen.getByText('JP, Tokyo')).toHaveClass('np-table-content--success');
    expect(screen.getByTestId('check-icon')).toBeInTheDocument();
  });

  it('renders `leading` cell type with initials avatar when `profileName` is provided', () => {
    render(<TableCell cell={{ ...cellContentMocks.leading }} />);
    expect(screen.getByText('AJ')).toBeInTheDocument();
    expect(screen.getByText('Alice Johnson')).toBeInTheDocument();
    expect(screen.getByText('Frontend Developer')).toBeInTheDocument();
  });

  it('renders `leading` cell type without media content when `avatar` is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.leading,
          avatar: undefined,
        }}
      />,
    );
    expect(screen.queryByText('AJ')).not.toBeInTheDocument();
    expect(screen.getByText('Alice Johnson')).toBeInTheDocument();
    expect(screen.getByText('Frontend Developer')).toBeInTheDocument();
    expect(screen.queryByTestId('np-table-content-media')).not.toBeInTheDocument();
  });

  it('renders `leading` cell without primary text if is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.leading,
          primaryText: undefined,
        }}
      />,
    );
    expect(screen.getByText('AJ')).toBeInTheDocument();
    expect(screen.queryByText('Alice Johnson')).not.toBeInTheDocument();
    expect(screen.getByText('Frontend Developer')).toBeInTheDocument();
  });

  it('renders `leading` cell without secondary text if it is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.leading,
          secondaryText: undefined,
        }}
      />,
    );
    expect(screen.getByText('AJ')).toBeInTheDocument();
    expect(screen.getByText('Alice Johnson')).toBeInTheDocument();
    expect(screen.queryByText('Frontend Developer')).not.toBeInTheDocument();
  });

  it('applies an `error` class, renders an `alert-icon` for `leading` cell type with `error` status', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.leading,
          status: 'error',
        }}
      />,
    );
    expect(screen.getByText('Alice Johnson')).toBeInTheDocument();
    expect(screen.getByText('Alice Johnson')).toHaveClass('np-table-content--error');
    expect(screen.getByTestId('alert-icon')).toBeInTheDocument();
  });

  it('applies a `success` class, renders an `check-icon` for `leading` cell type with `success` status', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.leading,
          status: 'success',
        }}
      />,
    );
    expect(screen.getByText('Alice Johnson')).toBeInTheDocument();
    expect(screen.getByText('Alice Johnson')).toHaveClass('np-table-content--success');
    expect(screen.getByTestId('check-icon')).toBeInTheDocument();
  });

  it('renders `currency` cell type', () => {
    render(<TableCell cell={{ ...cellContentMocks.currency }} alignment="right" />);
    expect(screen.getByTestId('np-table-content-media')).toBeInTheDocument();
    expect(screen.getByText('56,789 JPY')).toBeInTheDocument();
    expect(screen.getByText('51,000.00 GBP')).toBeInTheDocument();
  });

  it('renders `currency` cell without media content when currency amount of `primaryCurrency` is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.currency,
          primaryCurrency: {
            amount: cellContentMocks.currency.primaryCurrency.amount,
            currency: '',
          },
        }}
        alignment="right"
      />,
    );
    expect(screen.queryByRole('presentation')).not.toBeInTheDocument();
    expect(screen.getByText('56,789.01')).toBeInTheDocument();
    expect(screen.getByText('51,000.00 GBP')).toBeInTheDocument();
    expect(screen.queryByTestId('np-table-content-media')).not.toBeInTheDocument();
  });

  it('renders `currency` cell without primary currency when it is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.currency,
          primaryCurrency: undefined,
        }}
        alignment="right"
      />,
    );
    expect(screen.queryByText('56,789 JPY')).not.toBeInTheDocument();
    expect(screen.getByText('51,000.00 GBP')).toBeInTheDocument();
  });

  it('renders `currency` cell without secondary currency when it is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.currency,
          secondaryCurrency: undefined,
        }}
        alignment="right"
      />,
    );
    expect(screen.getByText('56,789 JPY')).toBeInTheDocument();
    expect(screen.queryByText('51,000.00 GBP')).not.toBeInTheDocument();
  });

  it('renders `currency` cell with error content', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.currency,
          status: 'error',
        }}
        alignment="right"
      />,
    );
    expect(screen.getByText('56,789 JPY')).toBeInTheDocument();
    expect(screen.getByText('56,789 JPY')).toHaveClass('np-table-content--error');
    expect(screen.getByTestId('alert-icon')).toBeInTheDocument();
  });

  it('renders `currency` cell with `success` content', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.currency,
          status: 'success',
        }}
        alignment="right"
      />,
    );
    expect(screen.getByText('56,789 JPY')).toBeInTheDocument();
    expect(screen.getByText('56,789 JPY')).toHaveClass('np-table-content--success');
    expect(screen.getByTestId('check-icon')).toBeInTheDocument();
  });

  it('renders a `status` cell type content', () => {
    render(<TableCell cell={{ ...cellContentMocks.status }} />);
    expect(screen.getByTestId('status-icon')).toBeInTheDocument();
    expect(screen.getByTestId('status-icon')).toHaveClass('pending');
    expect(screen.getByText('Overdue')).toBeInTheDocument();
    expect(screen.getByText('6 days ago')).toBeInTheDocument();
  });

  it('renders an `info-icon` for `status` cell type if `sentiment` is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.status,
          sentiment: undefined,
        }}
      />,
    );
    expect(screen.getByTestId('info-icon')).toBeInTheDocument();
  });

  it('renders `status` cell type without `primary` text if it is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.status,
          primaryText: undefined,
        }}
      />,
    );
    expect(screen.queryByText('Overdue')).not.toBeInTheDocument();
  });

  it('renders `status` cell type without `secondary` text if it is not provided', () => {
    render(
      <TableCell
        cell={{
          ...cellContentMocks.status,
          secondaryText: undefined,
        }}
      />,
    );
    expect(screen.queryByText('6 days ago')).not.toBeInTheDocument();
  });

  it('renders `media` cell type content', () => {
    render(<TableCell cell={{ ...cellContentMocks.media }} />);
    expect(screen.getByTestId('np-table-content-media')).toBeInTheDocument();
    expect(screen.getByAltText('Media content alt')).toBeInTheDocument();
    expect(screen.getByText('Media content')).toBeInTheDocument();
  });
});
