import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageSingleSelectProvider";
import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
import React, { useEffect } from "react";
import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
import { BehaviorSubject } from "rxjs";
import { masterCellLogger } from "../logger";
import get from "lodash/get";

const parseContextKey = (key: string): string | null => {
  if (!key?.startsWith("@{ctx/")) return null;

  return key.substring("@{ctx/".length, key.length - 1);
};

const getDataSourceProvider = (
  behavior: Behavior
): BehaviorSubject<string[] | string> | null => {
  if (!behavior) return null;

  const selection = String(behavior.current_selection);
  const contextKey = parseContextKey(selection);

  if (contextKey) {
    if (behavior.select_mode === "multi") {
      return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
    }

    if (behavior.select_mode === "single") {
      return StorageSingleValueProvider.getProvider(contextKey).getObservable();
    }
  }

  if (behavior.selection_source === "@{push/topics}") {
    return PushTopicManager.getInstance().getEntryObservable();
  }

  return null;
};

export const useBehaviorUpdate = (behavior: Behavior) => {
  const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
  const player = usePlayer();

  const triggerUpdate = () => setLastUpdate(Date.now());

  useEffect(() => {
    if (!behavior) return;

    const dataSource = getDataSourceProvider(behavior);

    if (dataSource) {
      const subscription = dataSource.subscribe(triggerUpdate);

      return () => subscription.unsubscribe();
    }
  }, [behavior]);

  useEffect(() => {
    if (!behavior || !player || behavior.selection_source !== "now_playing") {
      return;
    }

    const subscription = player.getEntryObservable().subscribe(triggerUpdate);

    return () => subscription.unsubscribe();
  }, [behavior, player]);

  return lastUpdate;
};

// We cant use async in this function (its inside render),
// so we rely on useBehaviorUpdate to update current value and trigger re-render
export const isCellSelected = (
  item: ZappEntry,
  behavior?: Behavior
): boolean => {
  if (!behavior) return false;

  const id = behavior.selector ? get(item, behavior.selector) : item.id;

  if (behavior.selection_source === "now_playing") {
    const player = playerManager.getActivePlayer();

    return player?.entry?.id === id;
  }

  if (behavior.selection_source === "@{push/topics}") {
    if (behavior.select_mode === "single") {
      masterCellLogger.warning(
        "Unexpected single selection mode for push topics"
      );
    }

    const tags = PushTopicManager.getInstance().getRegisteredTags();

    return tags.includes(String(id));
  }

  const selection = String(behavior.current_selection);
  const contextKey = parseContextKey(selection);

  if (contextKey) {
    if (behavior.select_mode === "single") {
      const selectedItem =
        StorageSingleValueProvider.getProvider(contextKey)?.getValue();

      return selectedItem === String(id);
    }

    if (behavior.select_mode === "multi") {
      const selectedItems =
        StorageMultiSelectProvider.getProvider(contextKey)?.getSelectedItems();

      return selectedItems?.includes(String(id));
    }
  }

  if (behavior.select_mode === "single") {
    return behavior.current_selection === id;
  }

  if (
    behavior.select_mode === "multi" &&
    Array.isArray(behavior.current_selection)
  ) {
    const currentSelection: string[] = behavior.current_selection.map(
      (item): string => String(item)
    );

    return currentSelection.includes(String(id));
  }

  return false;
};
