import * as R from "ramda";
import url from "url";
import atob from "atob";
import { isScreenPlayable } from "@applicaster/zapp-react-native-utils/navigationUtils/itemTypes";
import { log_warning } from "../logger";
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";

type UrlSchemeParams = Record<string, unknown>;

type UrlScheme = {
  host?: string | null;
  path?: string | null;
  scheme?: string;
  query?: UrlSchemeParams;
  fragment?: string;
};

const escapedChars = [
  [/&quot;/g, '"'], // eslint-disable-line quotes
  [/&apos;/g, "'"],
  [/&lt;/g, "<"],
  [/&gt;/g, ">"],
  [/&amp;/g, "&"],
];

const unescape = R.compose(...R.map(R.apply(R.replace), escapedChars));

/**
 * tries to decode a url encoded to a base64 string.
 * returns the original string if decoding is not possible or fails
 */
export function decodeUrl(urlString: string): string {
  try {
    return atob(decodeURIComponent(urlString));
  } catch (error) {
    log_warning(`couldn't decode url: ${urlString}`, { error, urlString });

    return urlString;
  }
}

/**
 * parses a url string into an object, providing values for the different parts of the url
 * @param `urlString` to parse
 * @returns url object - see UrlScheme type above
 */
export function parseUrl(urlString: string): UrlScheme {
  const {
    protocol,
    hostname: host,
    pathname: path,
    query,
    hash,
  } = url.parse(unescape(urlString), true, true);

  const { data_source } = query;
  const scheme = R.replace(":", "", protocol || "");
  const fragment = R.replace("#", "", hash || "");

  if (query.data_source) {
    query.data_source = decodeUrl(data_source as string);
  }

  return {
    scheme,
    host,
    path,
    query,
    fragment,
  };
}

function goToHome({ navigator }) {
  navigator.goHome();
}

function navigateTo({ data, navigator, pushScreen = false }) {
  const newData = { ...data, isDeepLink: true };

  if (isTV()) {
    navigator.replace(newData);

    return;
  }

  if (isScreenPlayable(navigator.currentRoute)) {
    navigator.goBack(); // TODO: check it on start
    navigator.push(newData);

    return;
  }

  const navigatorMethod = pushScreen ? "push" : "replace";
  navigator?.[navigatorMethod]?.(newData);
}

export function handlePresentNavigation({
  data = null,
  navigator,
  pushScreen = false,
}: {
  data?: any;
  navigator: any;
  pushScreen?: any;
}) {
  if (R.isNil(data)) {
    goToHome({ navigator });
  } else {
    navigateTo({ data, navigator, pushScreen });
  }
}

export function findRiver({ screen_id, rivers }) {
  return rivers?.[screen_id] || null;
}

export function isInternalUrl(url = "") {
  const { query } = parseUrl(url);

  return query?.isInternalLink;
}

export function getKeyFromStorage<T extends unknown>(
  key: keyof SessionStorageKeys,
  sessionData: Partial<SessionStorageKeys>
): T {
  if (!sessionData[key]) {
    throw new Error(`${key} is not available in session storage data`);
  }

  return R.compose(R.replace(/"/g, ""), R.prop(key))(sessionData);
}
