import { act, render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import {
  Sidebar,
  SidebarButton,
  SidebarContent,
  ViewType,
  useSidebar,
} from './sidebar';
import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { VegaIconNames } from '@vegaprotocol/ui-toolkit';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import { Routes as AppRoutes } from '../../lib/links';

jest.mock('../node-health', () => ({
  NodeHealthContainer: () => <span data-testid="node-health" />,
}));

jest.mock('@vegaprotocol/accounts', () => ({
  TransferContainer: () => <div data-testid="transfer" />,
}));

jest.mock('@vegaprotocol/deposits', () => ({
  DepositContainer: () => <div data-testid="deposit" />,
}));

jest.mock('../settings', () => ({
  Settings: () => <div data-testid="settings" />,
}));

jest.mock('../welcome-dialog', () => ({
  GetStarted: () => <div data-testid="get-started" />,
}));

const walletContext = {
  pubKeys: [{ publicKey: 'pubkey' }],
} as VegaWalletContextShape;

describe('Sidebar', () => {
  beforeEach(() => {
    useSidebar.setState({ views: {} });
  });

  it('renders options prop', () => {
    render(
      <VegaWalletContext.Provider value={walletContext}>
        <MemoryRouter>
          <Sidebar options={<div data-testid="options" />} />
        </MemoryRouter>
      </VegaWalletContext.Provider>
    );

    expect(screen.getByTestId(ViewType.ViewAs)).toBeInTheDocument();
    expect(screen.getByTestId(ViewType.Settings)).toBeInTheDocument();
    expect(screen.getByTestId('node-health')).toBeInTheDocument();
    expect(screen.getByTestId('options')).toBeInTheDocument();
  });

  it('renders selected state', async () => {
    const routeId = '/markets/ABC';
    render(
      <VegaWalletContext.Provider value={walletContext}>
        <MemoryRouter initialEntries={[routeId]}>
          <Sidebar
            options={
              <SidebarButton
                view={ViewType.Deposit}
                icon={VegaIconNames.DEPOSIT}
                tooltip="Deposit"
                routeId={'/markets/:marketId'}
              />
            }
          />
        </MemoryRouter>
      </VegaWalletContext.Provider>
    );

    const settingsButton = screen.getByTestId(ViewType.Settings);
    const depositButton = screen.getByTestId(ViewType.Deposit);

    // select settings first
    await userEvent.click(settingsButton);
    expect(settingsButton).toHaveClass('bg-vega-yellow text-black');

    // switch to deposit
    await userEvent.click(depositButton);

    expect(settingsButton).not.toHaveClass('bg-vega-yellow text-black');
    expect(depositButton).toHaveClass('bg-vega-yellow text-black');

    // close order
    await userEvent.click(depositButton);
    expect(depositButton).not.toHaveClass('bg-vega-yellow text-black');
  });
});

describe('SidebarContent', () => {
  beforeEach(() => {
    useSidebar.setState({ views: {} });
  });

  it('renders the correct content', () => {
    const { container } = render(
      <VegaWalletContext.Provider value={walletContext}>
        <MemoryRouter initialEntries={['/markets/ABC']}>
          <Routes>
            <Route
              path="/markets/:marketId"
              id={AppRoutes.MARKET}
              element={<SidebarContent />}
            />
          </Routes>
        </MemoryRouter>
      </VegaWalletContext.Provider>
    );

    expect(container).toBeEmptyDOMElement();

    act(() => {
      useSidebar.setState({
        views: { [AppRoutes.MARKET]: { type: ViewType.Transfer } },
      });
    });

    expect(screen.getByTestId('transfer')).toBeInTheDocument();

    act(() => {
      useSidebar.setState({
        views: { [AppRoutes.MARKET]: { type: ViewType.Deposit } },
      });
    });

    expect(screen.getByTestId('deposit')).toBeInTheDocument();
  });

  it('closes sidebar if market id is required but not present', () => {
    const { container } = render(
      <VegaWalletContext.Provider value={walletContext}>
        <MemoryRouter initialEntries={['/portfolio']}>
          <Routes>
            <Route
              path="/portfolio"
              id={AppRoutes.PORTFOLIO}
              element={<SidebarContent />}
            />
          </Routes>
        </MemoryRouter>
      </VegaWalletContext.Provider>
    );

    act(() => {
      useSidebar.setState({
        views: { [AppRoutes.PORTFOLIO]: { type: ViewType.Order } },
      });
    });

    expect(container).toBeEmptyDOMElement();

    act(() => {
      useSidebar.setState({
        views: { [AppRoutes.PORTFOLIO]: { type: ViewType.Settings } },
      });
    });

    expect(screen.getByTestId('settings')).toBeInTheDocument();

    act(() => {
      useSidebar.setState({
        views: { [AppRoutes.PORTFOLIO]: { type: ViewType.Info } },
      });
    });

    expect(container).toBeEmptyDOMElement();
  });
});

describe('SidebarButton', () => {
  it.each([ViewType.Info, ViewType.Deposit, ViewType.ViewAs])(
    'runs given callback regardless of requested view (%s)',
    async (view) => {
      const onClick = jest.fn();
      render(
        <SidebarButton
          icon={VegaIconNames.INFO}
          tooltip="INFO"
          onClick={onClick}
          view={view}
          routeId="current-route-id"
        />
      );

      const btn = screen.getByTestId(view);
      await userEvent.click(btn);

      expect(onClick).toBeCalled();
    }
  );
});