import * as R from "ramda";

import { RequestBuilder } from "@applicaster/zapp-pipes-v2-client";

import { TYPE, SCREEN_ID, FEED_LOCATOR, OMITTED_PARAMS } from "../const";

type Query = Record<string, unknown> &
  Partial<{
    type: string;
    screen_id: string;
    feed_locator: string;
    id: string;
    position: number;
    state: "inline" | "fullscreen";
  }>;

type ResolveQueryDataArgs = {
  query: Query;
  rivers: Record<string, ZappRiver>;
  contentTypes: ZappContentTypes;
};

type ResolvedQuery = {
  targetScreen: ZappRiver;
  entry?: Partial<ZappEntry>;
};

export const queryIsValid = R.anyPass([
  R.has(TYPE),
  R.has(SCREEN_ID),
  R.has(FEED_LOCATOR),
]);

export const getTypeMappedScreen = (type, rivers, contentTypes) =>
  R.compose(
    R.propOr(null, R.__, rivers),
    R.path([type, "screen_id"])
  )(contentTypes);

export const getEntryById = R.curry(
  (entries, { id }) => R.find(({ id: entryId }) => entryId == id, entries) // eslint-disable-line eqeqeq
);

export const getEntryByPosition = R.curry((entries, { position }) =>
  R.nth(Math.max(position - 1, 0), entries)
);

// second arg is not used here, but required by R.curry
export const getFirstEntry = R.curry((entries, _) => R.nth(0, entries));

export const getEntry = R.curry((entries, query) =>
  R.cond([
    [R.has("id"), getEntryById(entries)],
    [R.has("position"), getEntryByPosition(entries)],
    [R.T, getFirstEntry(entries)],
  ])(query)
);

export const formatEntry = (query: Query): Partial<ZappEntry> => {
  const params = R.omit([...OMITTED_PARAMS], query);
  const extensions = R.clone(params);

  if (query.type) {
    params.type = { value: query.type };
  }

  params.extensions = extensions;

  return params;
};

export const getHomeScreenId = R.compose(
  R.prop("id"),
  R.find(R.propEq("home", true)),
  R.values
);

export async function resolveQueryData({
  query,
  rivers,
  contentTypes,
}: ResolveQueryDataArgs): Promise<ResolvedQuery> {
  const { type, screen_id, feed_locator } = query;

  if (feed_locator) {
    const url = decodeURIComponent(feed_locator);
    const request = new RequestBuilder();

    if (!url) {
      throw new Error("Feed locator is missing");
    }

    const { response: feed, error } = await request
      .setUrl(url)
      .call<ZappFeed>();

    if (error) {
      throw error;
    }

    const entries = feed?.entry ?? [];
    const selectedEntry = getEntry(entries, query);

    const typeMappedScreen = getTypeMappedScreen(
      type ?? selectedEntry?.type?.value,
      rivers,
      contentTypes
    );

    const screen = R.prop(selectedEntry?.screen_type ?? screen_id, rivers);
    const targetScreen = screen ?? typeMappedScreen;

    return {
      targetScreen,
      entry: selectedEntry,
    };
  }

  const typeMappedScreen = getTypeMappedScreen(type, rivers, contentTypes);
  const screenFromId = R.prop(screen_id, rivers);
  const targetScreen = screenFromId ?? typeMappedScreen;

  const data = {
    targetScreen,
    entry: formatEntry(query),
  };

  return data;
}

const normalizeInitialPlayerState = (initialPlayerState: string): string => {
  return initialPlayerState.toLowerCase() === "inline"
    ? "inline"
    : "fullscreen";
};

export const withInitialPlayerState = (query, entry) => {
  const initialPlayerState = normalizeInitialPlayerState(
    R.pathOr("fullscreen", ["state"], query)
  );

  const initialPlayerStateLens = R.lensPath([
    "extensions",
    "initial_player_state",
  ]);

  return R.set(initialPlayerStateLens, initialPlayerState, entry);
};

export function wait(delay = 200) {
  return new Promise((resolve) => setTimeout(resolve, delay));
}
