import React from 'react';
import { describe, test, expect } from 'vitest';
import { fireEvent, render, waitFor, screen } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import RankSourceSelector, { type RankSource } from './RankSourceSelector.js';

describe('RankSourceSelector Component', () => {
  test('Renders all options', async () => {
    const { container } = render(<RankSourceSelector accountId={'12345'} />);

    // Wait for the component to finish loading (placeholder changes from "Loading..." to "Select rank source")
    await waitFor(() => {
      // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- react-select internal DOM
      const input = container.querySelector('.rank-source-selector__input');
      expect(input).not.toHaveAttribute('disabled');
    });

    // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- react-select internal DOM
    fireEvent.mouseDown(container.querySelector('.rank-source-selector__dropdown-indicator')!, {
      button: 0,
    });

    await waitFor(() => {
      // eslint-disable-next-line testing-library/no-node-access -- react-select internal DOM
      const menu = document.querySelector('.rank-source-selector__menu');
      expect(menu).toBeInTheDocument();
    });
    // eslint-disable-next-line testing-library/no-node-access -- react-select internal DOM
    const menu = document.querySelector('.rank-source-selector__menu');
    expect(menu).toBeVisible();

    await waitFor(() =>
      expect(
        // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- react-select internal DOM
        container.querySelectorAll('.rank-source-selector__option[id*="-option-"]'),
      ).toHaveLength(223),
    );
  });

  test('Selects the option passed as a prop', async () => {
    const rankSource = {
      id: 1,
      description: 'Google (US / English)',
      isoLocale: 'en_US',
    };
    const setRankSource = vi.fn();
    render(
      <RankSourceSelector
        accountId={'12345'}
        rankSource={rankSource}
        setRankSource={setRankSource}
      />,
    );

    const selectedValue = await screen.findByText('Google (US / English)');
    expect(selectedValue).toBeInTheDocument();
  });

  test('External state is updated', async () => {
    const user = userEvent.setup();
    const rankSource = {};
    const setRankSource = vi.fn();
    const { container } = render(
      <RankSourceSelector
        accountId={'12345'}
        rankSource={rankSource}
        setRankSource={setRankSource}
      />,
    );

    // Wait for the component to finish loading
    await waitFor(() => {
      // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- react-select internal DOM
      const input = container.querySelector('.rank-source-selector__input');
      expect(input).not.toHaveAttribute('disabled');
    });

    // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- react-select internal DOM
    fireEvent.mouseDown(container.querySelector('.rank-source-selector__dropdown-indicator')!, {
      button: 0,
    });
    await user.click(screen.getByText('Google (Angola / English)'));

    expect(setRankSource).toHaveBeenCalledWith({
      id: 175,
      description: 'Google (Angola / English)',
      isoLocale: 'en_AO',
    });
  });

  test('Given an ID, description and isoLocale are populated', async () => {
    let rankSource: RankSource = {
      id: 1,
    };
    const setRankSource = (newRankSource: RankSource) => (rankSource = newRankSource);
    render(
      <RankSourceSelector
        accountId={'12345'}
        rankSource={rankSource}
        setRankSource={setRankSource}
      />,
    );

    expect(rankSource).toStrictEqual({
      id: 1,
      description: 'Google (US / English)',
      isoLocale: 'en_US',
    });
  });
});
