import axios from "axios";
import camelize from "camelize";
import * as R from "ramda";
import { NativeModules } from "react-native";
import { URL_KEY_SUFFIX } from "./consts";
import { sessionStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/SessionStorage";

const { AppLoaderBridge } = NativeModules;

type FileResponse = {
  [key: string]: object | [];
};

const REMOTE_CONFIG_KEYS = {
  TABLET: {
    LAYOUT: "tablet_layout_url",
    CELL_STYLES: "tablet_cell_styles_url",
  },
  MOBILE: {
    LAYOUT: "layout_url",
    CELL_STYLES: "cell_styles_url",
  },
};

export const urlKeyToContext = R.compose(
  camelize,
  R.replace(URL_KEY_SUFFIX, "")
);

export function getPromiseForKey(runtimeConfigurationUrls) {
  return async function (urlKey) {
    const context = urlKeyToContext(urlKey);
    const url = R.prop(urlKey, runtimeConfigurationUrls);

    try {
      const response = await axios.get(url);

      const { data } = response;

      return {
        [context]: data,
      };
    } catch (e) {
      throw new Error("cannot retrieve configuration data for " + urlKey);
    }
  };
}

export async function prepareRuntimeConfigurationUrls(
  runtimeConfigurationUrls,
  isTablet
) {
  const layoutUrlKey = isTablet
    ? REMOTE_CONFIG_KEYS.TABLET.LAYOUT
    : REMOTE_CONFIG_KEYS.MOBILE.LAYOUT;

  const layoutUrl = R.prop(layoutUrlKey, runtimeConfigurationUrls);

  const cellStylesUrlKey = isTablet
    ? REMOTE_CONFIG_KEYS.TABLET.CELL_STYLES
    : REMOTE_CONFIG_KEYS.MOBILE.CELL_STYLES;

  const cellStylesUrl = R.prop(cellStylesUrlKey, runtimeConfigurationUrls);
  const context = urlKeyToContext(layoutUrlKey);

  try {
    const response = await axios.get(layoutUrl);
    const { data } = response;
    const layoutData = [{ [context]: data }];
    const { id: layoutId } = data;

    const preparedRuntimeConfigurationUrls = { ...runtimeConfigurationUrls };
    delete preparedRuntimeConfigurationUrls[layoutUrlKey];

    if (isTablet) {
      preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.LAYOUT] &&
        delete preparedRuntimeConfigurationUrls[
          REMOTE_CONFIG_KEYS.MOBILE.LAYOUT
        ];

      preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.CELL_STYLES] &&
        delete preparedRuntimeConfigurationUrls[
          REMOTE_CONFIG_KEYS.MOBILE.CELL_STYLES
        ];
    } else {
      delete preparedRuntimeConfigurationUrls[REMOTE_CONFIG_KEYS.TABLET.LAYOUT];

      delete preparedRuntimeConfigurationUrls[
        REMOTE_CONFIG_KEYS.TABLET.CELL_STYLES
      ];
    }

    if (cellStylesUrl && !cellStylesUrl.includes(layoutId)) {
      const splitedUrl = cellStylesUrl.split("/");
      const oldLayoutId = splitedUrl[splitedUrl.length - 2];
      await sessionStorage.setItem("rivers_configuration_id", layoutId);

      return {
        layoutData,
        preparedRuntimeConfigurationUrls: {
          ...preparedRuntimeConfigurationUrls,
          [cellStylesUrlKey]: cellStylesUrl.replace(oldLayoutId, layoutId),
        },
      };
    }

    return {
      layoutData,
      preparedRuntimeConfigurationUrls,
    };
  } catch (e) {
    return { preparedRuntimeConfigurationUrls: runtimeConfigurationUrls };
  }
}

export async function getPromiseForType(
  key: string
): Promise<FileResponse | never> {
  try {
    const response = await AppLoaderBridge?.getFile(key, null);

    return {
      [key]: JSON.parse(response),
    };
  } catch (e) {
    throw new Error("cannot retrieve configuration data for " + key);
  }
}

export const fetchPluginConfiguration = (pluginConfigurations) => (plugin) => {
  const configuration = R.compose(
    R.unless(
      R.isNil,
      R.compose(
        R.tryCatch(JSON.parse, R.flip(R.identity)),
        R.prop("configuration_json")
      )
    ),
    R.defaultTo(null),
    R.find(R.pathEq(["plugin", "identifier"], plugin.identifier))
  )(pluginConfigurations);

  return {
    ...plugin,
    configuration,
  };
};
