import React, { useCallback, useEffect } from "react";
import { TouchableOpacity, ViewStyle } from "react-native";

import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";

import Image from "./Image";
type Props = {
  item: ZappEntry | ZappFeed;
  flavour?: "flavour_1" | "flavour_2";
  asset?: {
    props: {};
    src: {
      active: string;
      inactive: string;
    } & Record<string, string>;
    style: {};
    type: "Image" | "Svg" | "Lottie";
  };
  action: {
    identifier: string;
    type?: string;
  };
  style: ViewStyle;
  testID?: string;
  accessibilityLabel?: string;
  cellUUID?: string;
  extraProps?: Record<string, any>;
};

function isStringAsset(asset) {
  return typeof asset === "string" || Array.isArray(asset);
}

function getAssetValue(asset, flavour, fallbackAsset = null) {
  if (!asset) {
    return null;
  }

  if (typeof asset === "string") return asset;

  if (Array.isArray(asset)) {
    const flavourIndex = Number(flavour.replace("flavour_", ""));
    if (flavour && flavourIndex > -1) return asset[flavourIndex - 1];

    return asset[0];
  }

  return asset.src || fallbackAsset;
}

export function ActionButton(props: Props) {
  const { item, action, asset, flavour = "flavour_1", cellUUID } = props;
  const actionContext = useActions(action?.identifier);

  // TODO: add subscription API for action availability
  const actionDisabled =
    typeof actionContext?.isActionAvailable === "function" &&
    !actionContext.isActionAvailable(item);

  // Note: in theory initialization is not needed anymore, we are using useEffect
  const [actionState, setActionState] = React.useState(
    actionDisabled || !actionContext
      ? null
      : actionContext.initialEntryState(item)
  );

  useEffect(() => {
    if (!((actionDisabled || !actionContext) && actionState !== null)) {
      setActionState(actionContext.initialEntryState(item));
    }
  }, [actionDisabled, item?.id, actionContext, action, setActionState]);

  const onPress = useCallback(() => {
    actionContext.invokeAction(item, {
      updateState: (state) => {
        setActionState(state);
      },
    });
  }, [actionState, actionContext?.state, item?.id]);

  useEffect(() => {
    if (typeof actionContext?.addListener === "function") {
      return actionContext?.addListener(String(item.id), (state) => {
        setActionState(state);
      });
    }
  }, [item?.id, setActionState, actionContext]);

  if (actionDisabled || !actionContext) return null;
  const AssetComponent = actionState?.asset;

  // Default state is not yet ready
  if (!AssetComponent) return null;

  return (
    <TouchableOpacity
      activeOpacity={1}
      onPress={onPress}
      testID={props?.testID || `${item?.id}`}
      accessibilityLabel={props?.accessibilityLabel || `${item?.id}`}
      accessible={!!(props?.testID || props?.accessibilityLabel)}
      style={props?.style}
    >
      {isStringAsset(actionState.asset) ? (
        <Image
          fadeDuration={0}
          style={asset?.style || props?.style}
          uri={getAssetValue(actionState.asset, flavour, asset?.src)}
          {...asset?.props}
        />
      ) : (
        <AssetComponent
          flavour={flavour}
          asset={getAssetValue(asset, flavour)}
          cellUUID={cellUUID}
          {...(props?.extraProps ?? {})}
        />
      )}
    </TouchableOpacity>
  );
}
