import expect from 'expect';
import {
  Balloon,
  BalloonDirection,
  BalloonSize,
  ButtonIcon,
  ButtonIconType,
  ButtonSize,
  Layout,
  SVGAsset,
} from 'twitch-core-ui';

import { partialPropShallowWrapper } from 'mtest/helpers/partialPropWrappers';
import { trackClickMock, testClickTracking } from 'mtest/helpers/tracking';
import { CHANNEL_DETAILS } from 'mtest/fetchMocks/channel';

import {
  TopNavMenu,
  TopNavMenuProps,
  MenuItem,
  MenuItemProps,
  MenuItemType,
  generateSubscriptionUrl,
  INTERACTION_CONTENT_MENU,
} from 'mweb/common/components/topNavMenu';
import { ChannelSubscribableStatus } from 'mweb/common/reducers/data/channels';
import { TrackClickHandler } from 'mweb/common/tracking/withTracking';
import { InteractionMedium } from 'mweb/common/tracking/extendInteractionMedium';

const SWITCH_TO_DESKTOP_INDEX = 4;
const SUBSCRIBE_INDEX = 5;

describe('<TopNavMenu />', () => {
  const DEFAULT_PROPS: TopNavMenuProps = {
    switchToDesktop: () => undefined,
    currentChannel: CHANNEL_DETAILS,
    trackClick: trackClickMock(),
  };

  const subject = partialPropShallowWrapper(TopNavMenu, DEFAULT_PROPS);

  it('has a ButtonIcon with the correct props', () => {
    const buttonIcon = subject().find(ButtonIcon);

    expect(buttonIcon.length).toEqual(1);
    expect(buttonIcon).toHaveProps({
      type: ButtonIconType.Primary,
      size: ButtonSize.Large,
      icon: SVGAsset.More,
    });
  });

  it('has a Balloon with the correct props', () => {
    const balloon = subject().find(Balloon);

    expect(balloon.length).toEqual(1);
    expect(balloon).toHaveProps({
      direction: BalloonDirection.BottomRight,
      size: BalloonSize.Small,
      noTail: true,
    });
  });

  it('renders the list of links and separators', () => {
    const linkContainer = subject()
      .find(InteractionMedium)
      .find(Layout);

    expect(linkContainer.children().length).toEqual(15);
  });

  it('passes switch to desktop function appropriately', () => {
    const switchItem = subject()
      .find(InteractionMedium)
      .find(Layout)
      .childAt(SWITCH_TO_DESKTOP_INDEX);

    expect(switchItem.prop('onClick')).toEqual(DEFAULT_PROPS.switchToDesktop);
  });

  describe('channel subscribe', () => {
    it('is not hidden when channel is subscribable (ChannelSubscribableStatus.CanSubscribe)', () => {
      const subscribe = subject({
        currentChannel: {
          subscribableStatus: ChannelSubscribableStatus.CanSubscribe,
          name: 'BigAndy',
        },
      })
        .find(InteractionMedium)
        .find(Layout)
        .childAt(SUBSCRIBE_INDEX);

      expect(subscribe.prop('hidden')).toEqual(false);
      expect(subscribe.prop('linkTo')).toEqual(
        generateSubscriptionUrl('BigAndy'),
      );
    });

    it('is hidden when channel is not subscribable (ChannelSubscribableStatus.CannotSubscribe)', () => {
      const subscribe = subject({
        currentChannel: {
          subscribableStatus: ChannelSubscribableStatus.CannotSubscribe,
          name: 'BigAndy',
        },
      })
        .find(InteractionMedium)
        .find(Layout)
        .childAt(SUBSCRIBE_INDEX);

      expect(subscribe.prop('hidden')).toEqual(true);
    });

    it('is hidden when channel is subscribaleStatus is unknown (ChannelSubscribableStatus.Unknown)', () => {
      const subscribe = subject({
        currentChannel: {
          subscribableStatus: ChannelSubscribableStatus.Unknown,
          name: 'BigAndy',
        },
      })
        .find(InteractionMedium)
        .find(Layout)
        .childAt(SUBSCRIBE_INDEX);

      expect(subscribe.prop('hidden')).toEqual(true);
    });
  });

  testClickTracking({
    title: 'tracks clicks on the menu button',
    expectedPayload: {
      interactionContent: INTERACTION_CONTENT_MENU,
    },
    clickTargetBuilder: (trackClick: TrackClickHandler) =>
      subject({ trackClick }).find(ButtonIcon),
  });
});

describe('<MenuItem/>', () => {
  const DEFAULT_PROPS: MenuItemProps = {
    trackClick: trackClickMock(),
    type: MenuItemType.Link,
    text: 'text',
  };

  const subject = partialPropShallowWrapper(MenuItem, DEFAULT_PROPS);

  testClickTracking({
    title: 'tracks clicks when given tracking is configured',
    expectedPayload: {
      interactionContent: 'content',
      interactionTargetPath: 'path',
    },
    clickTargetBuilder: (trackClick: TrackClickHandler) =>
      subject({
        trackClick,
        tracking: {
          interactionContent: 'content',
          interactionTargetPath: 'path',
        },
      }),
  });
});
