import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';

import { JestDOM } from '@leafygreen-ui/testing-lib';

import { hostDefaults, urlFixtures } from '../../data';

import { UserMenuProps } from './UserMenu';
import UserMenu from '.';

const defaultAccount = {
  firstName: 'Leafy',
  lastName: 'Green',
  email: 'leafy@mongodb.com',
  hasLegacy2fa: true,
  admin: false,
};
const onLogout = jest.fn();
const onProductChange = jest.fn();

function renderUserMenu(
  props: Partial<UserMenuProps> = {},
  account = defaultAccount,
  hostOptions?: boolean,
) {
  const utils = render(
    <UserMenu
      account={account}
      onLogout={onLogout}
      onProductChange={onProductChange}
      urls={urlFixtures}
      hosts={hostDefaults(hostOptions)}
      {...props}
    />,
  );

  return utils;
}

describe('packages/mongo-nav/user-menu', () => {
  test('by default, renders closed UserMenu with users name in button', () => {
    const { getByTestId } = renderUserMenu();
    const trigger = getByTestId('user-menu-trigger');
    expect(trigger).toBeInTheDocument();
    expect(trigger.getAttribute('aria-expanded')).toBe('false');
  });

  test('when "activePlatform" is set to "cloud", renders Cloud MenuItems', () => {
    const { getByTestId, getByText } = renderUserMenu({
      activePlatform: 'cloud',
    });
    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);

    const userPreferences = getByText('User Preferences');
    const invitations = getByText('Invitations');
    const organizations = getByText('Organizations');
    const mfa = getByText('Legacy 2FA');

    expect(userPreferences).toBeInTheDocument();
    expect(invitations).toBeInTheDocument();
    expect(organizations).toBeInTheDocument();
    expect(mfa).toBeInTheDocument();
  });

  test('when "shouldSeeAccountMfaBanner" is set to false, does not render the Account MFA Banner', () => {
    const { getByTestId, queryByTestId } = renderUserMenu({
      account: {
        ...defaultAccount,
        shouldSeeAccountMfaBanner: false,
      },
    });

    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);
    const accountMfaBanner = queryByTestId('user-menu-mfa-banner');

    expect(accountMfaBanner).not.toBeInTheDocument();
  });

  test('when "shouldSeeAccountMfaBanner" is set to true, renders the Account MFA Banner', () => {
    const { getByTestId, queryByTestId } = renderUserMenu({
      account: {
        ...defaultAccount,
        shouldSeeAccountMfaBanner: true,
      },
    });
    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);

    const accountMfaBanner = queryByTestId('user-menu-mfa-banner');
    expect(accountMfaBanner).toBeInTheDocument();
  });

  test('when "hasLegacy2fa" is set to false, does not render mfa menu item', () => {
    const { queryByText, getByTestId } = renderUserMenu({
      activePlatform: 'cloud',
      account: {
        ...defaultAccount,
        hasLegacy2fa: false,
      },
    });

    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);
    expect(queryByText('Legacy 2FA')).not.toBeInTheDocument();
  });

  test('when "hasLegacy2fa" is set to true, render the mfa menu item', () => {
    const { queryByText, getByTestId } = renderUserMenu({
      activePlatform: 'cloud',
      account: {
        ...defaultAccount,
        hasLegacy2fa: true,
      },
    });

    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);
    expect(queryByText('Legacy 2FA')).toBeInTheDocument();
  });

  describe('SubMenus link to their respective URL', () => {
    beforeEach(() => {
      renderUserMenu({ activePlatform: 'cloud' });

      const trigger = screen.getByTestId('user-menu-trigger');
      fireEvent.click(trigger);
    });

    test('Atlas SubMenu links to cloud.mongodb.com', () => {
      const cloud = screen.getByText('Atlas').closest('a');
      expect(cloud?.href).toBe('https://cloud.mongodb.com/');
    });

    test('University SubMenu item links to learn.mongodb.com', () => {
      const cloud = screen.getByText('University').closest('a');
      expect(cloud?.href).toBe('https://learn.mongodb.com/');
    });

    test('Forums SubMenu links to developer.mongodb.com', () => {
      const cloud = screen.getByText('Forums').closest('a');
      expect(cloud?.href).toBe('http://forums.mongodb.com/');
    });

    test('DevHub SubMenu links to developer.mongodb.com', () => {
      const cloud = screen.getByText('Developer Center').closest('a');
      expect(cloud?.href).toBe('https://developer.mongodb.com/');
    });

    test('Docs MenuItem links to docs.mongodb.com', () => {
      const cloud = screen.getByText('Documentation').closest('a');
      expect(cloud?.href).toBe('https://docs.mongodb.com/');
    });

    test('Support SubMenu links to support.mongodb.com', () => {
      const cloud = screen.getByText('Support').closest('a');
      expect(cloud?.href).toBe('https://support.mongodb.com/');
    });
  });

  test('onLogout fires when logout is clicked', async () => {
    const { getByText, getByTestId } = renderUserMenu({
      activePlatform: 'cloud',
    });
    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);
    const logout = getByText('Log out');

    await JestDOM.silenceNavigationErrors(async waitForNavigation => {
      fireEvent.click(logout);

      await waitForNavigation();
    });

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

  test('renders the account link as a disabled button when set to the empty string', () => {
    const { getByTestId } = renderUserMenu({
      activePlatform: 'account',
    });
    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);
    const accountButton = getByTestId(
      'user-menu-account-button',
    ) as HTMLButtonElement;

    expect(accountButton.tagName.toLowerCase()).toBe('button');
    expect(accountButton).toHaveAttribute('aria-disabled', 'true');
  });

  test('does not render atlas MenuItems when a non-cloud product is active', () => {
    const { queryByText, getByTestId } = renderUserMenu({
      activePlatform: 'account',
    });
    const trigger = getByTestId('user-menu-trigger');
    fireEvent.click(trigger);

    const userPreferences = queryByText('User Preferences');
    const invitations = queryByText('Invitations');
    const organizations = queryByText('Organizations');
    const mfa = queryByText('Two-Factor Authentication');

    expect(userPreferences).toBeNull();
    expect(invitations).toBeNull();
    expect(organizations).toBeNull();
    expect(mfa).toBeNull();
  });

  describe('renders appropriate links to SubMenu Items based on overrides prop', () => {
    test('renders particular url override, when the urls prop is set', () => {
      const { getByTestId } = renderUserMenu({
        activePlatform: 'forum',
        urls: {
          ...urlFixtures,
          userMenu: {
            forums: {
              forumsPreferences: 'https://forum.mongodb.com/override-test',
            },
          },
        },
      });

      const trigger = getByTestId('user-menu-trigger');
      fireEvent.click(trigger);

      const SubMenuItem = getByTestId('user-menuitem-forum-preferences');
      expect((SubMenuItem as HTMLAnchorElement).href).toBe(
        'https://forum.mongodb.com/override-test',
      );
    });
  });

  describe('when the environment is set to "government"', () => {
    test('it renders "Atlas for Government" as the title of Cloud SubMenu', () => {
      const { getByTestId, getByText } = renderUserMenu({
        activePlatform: 'cloud',
        environment: 'government',
      });

      const trigger = getByTestId('user-menu-trigger');
      fireEvent.click(trigger);
      const menuTitleElement = getByText('Atlas for Government');

      expect(menuTitleElement).toBeInTheDocument();
    });

    test('it renders "cloud.mongodbgov.com" as description for Cloud SubMenu', () => {
      const { getByTestId, getByText } = renderUserMenu({
        activePlatform: 'cloud',
        environment: 'government',
      });

      const trigger = getByTestId('user-menu-trigger');
      fireEvent.click(trigger);
      const menuDesctiptionElement = getByText('cloud.mongodbgov.com');
      expect(menuDesctiptionElement).toBeInTheDocument();
    });

    test('mfa menu item does not appear', () => {
      const { queryByText, getByTestId } = renderUserMenu({
        activePlatform: 'cloud',
        environment: 'government',
      });

      const trigger = getByTestId('user-menu-trigger');
      fireEvent.click(trigger);
      expect(queryByText('Legacy 2FA')).not.toBeInTheDocument();
    });

    test('Support SubMenu uses gov url', () => {
      const { getByTestId, getByText } = renderUserMenu(
        {
          activePlatform: 'cloud',
          environment: 'government',
        },
        undefined,
        true,
      );

      const trigger = getByTestId('user-menu-trigger');
      fireEvent.click(trigger);

      const cloud = getByText('Support').closest('a');
      expect(cloud?.href).toBe('https://support.mongodbgov.com/');
    });

    test('it renders "support.mongodbgov.com" as description for Support SubMenu', () => {
      const { getByTestId, getByText } = renderUserMenu({
        activePlatform: 'cloud',
        environment: 'government',
      });

      const trigger = getByTestId('user-menu-trigger');
      fireEvent.click(trigger);
      expect(getByText('support.mongodbgov.com')).toBeInTheDocument();
    });
  });

  // eslint-disable-next-line jest/no-disabled-tests
  describe.skip('the types behave as expected', () => {
    // eslint-disable-next-line jest/expect-expect
    test('does not error when all URLS are passed to urls prop', () => {
      <UserMenu urls={urlFixtures} />;
    });
    // eslint-disable-next-line jest/expect-expect
    test('does not error when only userMenu object is passed to urls prop', () => {
      <UserMenu
        urls={{
          userMenu: {
            cloud: {
              userPreferences: 'string',
              invitations: 'string',
              mfa: 'string',
              organizations: 'string',
            },
            university: {
              faqs: 'string',
              transcript: 'string',
            },
            support: {
              userPreferences: 'string',
            },
          },
        }}
      />;
    });
  });
});
