import * as R from "ramda";

import { localStorage } from "../ZappStorage/LocalStorage";
import { subscriber } from "@applicaster/zapp-react-native-utils/functionUtils";

import { bridgeLogger } from "../logger";

const namespace = "local_favourites";
const key = "favourites";

type Item = ZappEntry | ZappFeed;

export const favoritesListener = subscriber({});

function itemExistInFavourites(favourites: Array<Item>, item: Item) {
  const itemsFound = R.filter((itemToFilter) => {
    return itemToFilter?.id?.toString() === item?.id?.toString();
  }, favourites);

  return itemsFound.length === 1;
}

export async function getAllFavorites(_url?: string) {
  try {
    const favourites: Array<Item> = await localStorage.getItem(key, namespace);

    if (!favourites) {
      await localStorage.setItem(key, [], namespace);

      return [];
    }

    return favourites;
  } catch (err) {
    bridgeLogger.error(err);
    throw err;
  }
}

export async function isFavorite(item: Item) {
  try {
    const favourites = await getAllFavorites();

    return itemExistInFavourites(favourites, item);
  } catch (e) {
    bridgeLogger.error(e);
    throw e;
  }
}

export async function setAsFavorite(item: Item) {
  const favourites = await getAllFavorites();

  if (!favourites) {
    throw new Error("Couldn't find favourites object");
  }

  const itemToAdd: Item = JSON.parse(JSON.stringify(item));

  if (itemExistInFavourites(favourites, item)) {
    throw new Error(
      `entry with id ${item?.id} is already in the favourites list`
    );
  }

  const newFavourites = R.append(itemToAdd, favourites);

  try {
    await localStorage.setItem(key, newFavourites, namespace);
    favoritesListener.invokeHandler("FAVORITES_CHANGED", newFavourites);

    return newFavourites;
  } catch (err) {
    bridgeLogger.error(err);
    throw err;
  }
}

export async function removeFromFavorites(item: Item) {
  try {
    const favourites = await getAllFavorites();

    if (!favourites) {
      throw new Error("Couldn't find favourites object");
    }

    if (!itemExistInFavourites(favourites, item)) {
      throw new Error(
        `entry with id ${item?.id} is not in the favourites list`
      );
    }

    const newFavourites = R.filter((itemToFilter) => {
      return itemToFilter?.id?.toString() !== item?.id?.toString();
    }, favourites);

    await localStorage.setItem(key, newFavourites, namespace);
    favoritesListener.invokeHandler("FAVORITES_CHANGED", newFavourites);

    return newFavourites;
  } catch (err) {
    bridgeLogger.error(err);
    throw err;
  }
}

export async function setAllFavorites(items: Array<Item>) {
  try {
    await localStorage.setItem(key, items, namespace);
    favoritesListener.invokeHandler("FAVORITES_CHANGED", items);

    return items;
  } catch (err) {
    bridgeLogger.error(err);
    throw err;
  }
}
