import React, { useMemo } from "react";
import { ImageStyle } from "react-native";
import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
import * as R from "ramda";
import { getXray } from "@applicaster/zapp-react-native-utils/logger";
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";

const { Logger } = getXray();

import {
  recursiveCloneElementsWithState,
  getFocusedButtonId,
} from "../../utils";

const logger = new Logger("plugin", "plugins/navigation-action");

type Props = Record<string, any> & {
  style: ImageStyle;
};

const getFocusableId = (prefixId, suffixId) => `${prefixId}___${suffixId}`;

export function FocusableView({ style, children, item, ...otherProps }: Props) {
  const {
    groupId,
    prefixId,
    suffixId,
    wrapperRef,
    focusedButtonId,
    normalStyles,
    focusedStyles,
    pluginIdentifier,
    preferredFocus,
  } = otherProps;

  const focusableId = getFocusableId(prefixId, suffixId);

  const focused =
    focusableId === focusedButtonId ||
    toBooleanWithDefaultFalse(otherProps.focused);

  const additionalStyles = focused ? focusedStyles : normalStyles;

  const actionContext = useActions(pluginIdentifier);

  const accessibilityManager = useAccessibilityManager({});

  const { ttsLabel = "" } =
    actionContext?.initialEntryState(item)?.getAccessibility?.(item) || {};

  const onPress = (event) => {
    event?.preventDefault?.();

    if (!actionContext) {
      logger.warning(
        `Cannot resolve action context for ${pluginIdentifier} - please make sure the plugin is installed and up to date`
      );

      return;
    }

    actionContext?.invokeAction?.(item);
  };

  const handleFocus = (focusable) => {
    const focusedButtonId = getFocusedButtonId(focusable);

    wrapperRef?.current?.measure((x, y, width, height, pageX, pageY) => {
      const top = pageY;
      const bottom = top + height;
      const left = pageX;
      const right = left + width;

      const boundingRect = {
        x,
        y,
        pageX,
        pageY,
        width,
        height,
        top,
        bottom,
        left,
        right,
      };

      otherProps?.onToggleFocus?.({
        focusable: {
          getRect: R.always(boundingRect),
        },
        focusedButtonId,
        mouse: focusable.mouse,
      });
    });

    if (ttsLabel) {
      accessibilityManager.readText({
        text: ttsLabel,
      });
    }
  };

  const handleBlur = (_focusable, _direction) => {
    otherProps?.onToggleFocus?.({ focusedButtonId: undefined });
  };

  const styles = useMemo(
    () => ({ ...style, ...additionalStyles }),
    [additionalStyles, style]
  );

  return (
    <Focusable
      id={focusableId}
      groupId={groupId}
      style={styles}
      onFocus={handleFocus}
      onBlur={handleBlur}
      onPress={onPress}
      preferredFocus={preferredFocus}
      skipFocusManagerRegistration={otherProps.skipFocusManagerRegistration}
      isFocusable={otherProps.isFocusable}
    >
      {(isFocused) => recursiveCloneElementsWithState(isFocused, children)}
    </Focusable>
  );
}
