import { MobileWebCookie } from 'src/common/utils/cookie';
import { EventLocation } from 'src/lambda';
import url from 'url';

import { RedirectManager } from 'mweb/common/utils/redirectManager';

const BASE_DESKTOP_WEB_PARAMETERS = {
  protocol: 'https',
  host: 'www.twitch.tv',
};

const BASE_URL_QUERY_PARAMS = {
  'no-mobile-redirect': 'true',
};

const CHANNEL_PAGE_ALIASES = ['*/mobile', '*/rooms/*'];

const CHANNEL_ALIASES = {
  overwatchleague_allaccess: 'overwatchleague',
};

type AliasedChannel = keyof typeof CHANNEL_ALIASES;

export class LambdaRedirectManager extends RedirectManager {
  constructor(
    protected readonly location: EventLocation,
    pathParts: ReadonlyArray<string>,
    cookie: Readonly<MobileWebCookie>,
    protected readonly redirectFromDesktop: boolean,
    protected readonly medium: string | undefined,
    protected readonly content: string | undefined,
  ) {
    super(pathParts, cookie);
  }

  redirect(): boolean {
    return (
      this.redirectNotFound() ||
      this.isSpecialPath() ||
      this.isUpsellOptOut() ||
      this.isChannelPageAlias() ||
      this.isChannelAlias()
    );
  }

  redirectTo(): string {
    if (this.isChannelPageAlias()) {
      return this.redirectToChannelPage();
    }
    if (this.isChannelAlias()) {
      // We can infer that pathParts[0] is an aliased channel since
      // isChannelAlias checks this.
      return this.redirectToChannelAlias(this.pathParts[0] as AliasedChannel);
    }
    return this.redirectToDesktopSite();
  }
  protected redirectToChannelPage(): string {
    return url.format({
      query: this.buildTrackingParams(),
      pathname: this.buildChannelPath(),
    });
  }

  protected redirectToChannelAlias(channel: AliasedChannel): string {
    return url.format({
      query: this.buildTrackingParams(),
      pathname: `/${CHANNEL_ALIASES[channel]}`,
    });
  }

  protected redirectToDesktopSite(): string {
    return url.format({
      ...BASE_DESKTOP_WEB_PARAMETERS,
      query: {
        ...BASE_URL_QUERY_PARAMS,
        ...this.buildTrackingParams(),
      },
      pathname: this.buildPath(),
    });
  }

  protected buildTrackingParams(): { tt_content?: string; tt_medium?: string } {
    const trackingParams: {
      tt_content?: string;
      tt_medium?: string;
    } = {};
    if (this.content) {
      trackingParams.tt_content = this.content;
    }
    if (this.medium) {
      trackingParams.tt_medium = this.medium;
    }
    return trackingParams;
  }

  protected redirectNotFound(): boolean {
    return this.location === 'not_found' && this.isDesktopElligible();
  }

  protected isDesktopElligible(): boolean {
    return this.redirectFromDesktop;
  }

  private isChannelPageAlias(): boolean {
    return this.matchesPathGlob(CHANNEL_PAGE_ALIASES);
  }

  private isChannelAlias(): boolean {
    return (
      this.pathParts.length === 1 && this.isAliasedChannel(this.pathParts[0])
    );
  }

  private isAliasedChannel(channel: string): channel is AliasedChannel {
    return !!CHANNEL_ALIASES[channel as AliasedChannel];
  }

  private buildChannelPath(): string {
    return `/${this.pathParts[0]}`;
  }
}
