import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
import {
  useGetScreenOrientation,
  isOrientationCompatible,
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
import {
  useCurrentScreenData,
  useRoute,
  useIsTablet,
  useIsScreenActive,
} from "@applicaster/zapp-react-native-utils/reactHooks";
import { useMemo, useEffect, useState } from "react";
import { useSafeAreaFrame } from "react-native-safe-area-context";

type MemoizedSafeAreaFrameWithActiveStateOptions = {
  updateForInactiveScreens?: boolean;
  isActive: boolean;
};

/**
 * Base hook that wraps useSafeAreaFrame with memoization and inactive screen filtering.
 * Requires isActive to be passed explicitly - use useMemoizedSafeAreaFrame for automatic detection.
 *
 * @param options.updateForInactiveScreens - If false, frame won't update when screen is inactive (default: true)
 * @param options.isActive - Whether the screen is currently active
 * @returns The memoized safe area frame { x, y, width, height }
 */
export const useMemoizedSafeAreaFrameWithActiveState = (
  options: MemoizedSafeAreaFrameWithActiveStateOptions
) => {
  const { updateForInactiveScreens = true, isActive } = options;
  const frame = useSafeAreaFrame();

  const [memoFrame, setMemoFrame] = useState(frame);

  useEffect(() => {
    const shouldUpdate = isActive || updateForInactiveScreens;

    const dimensionsChanged =
      frame.width !== memoFrame.width || frame.height !== memoFrame.height;

    if (shouldUpdate && dimensionsChanged) {
      setMemoFrame(frame);
    }
  }, [
    frame.width,
    frame.height,
    isActive,
    updateForInactiveScreens,
    frame,
    memoFrame.width,
    memoFrame.height,
  ]);

  return memoFrame;
};

type MemoizedSafeAreaFrameOptions = {
  updateForInactiveScreens?: boolean;
};

/**
 * Hook that wraps useSafeAreaFrame with memoization and inactive screen filtering.
 * Uses useIsScreenActive() internally to determine active state - use useMemoizedSafeAreaFrameWithActiveState
 * if you need to pass isActive explicitly.
 *
 * @param options.updateForInactiveScreens - If false, frame won't update when screen is inactive (default: true)
 * @returns The memoized safe area frame { x, y, width, height }
 */
export const useMemoizedSafeAreaFrame = (
  options: MemoizedSafeAreaFrameOptions = {}
) => {
  const { updateForInactiveScreens = true } = options;
  const isActive = useIsScreenActive();

  return useMemoizedSafeAreaFrameWithActiveState({
    updateForInactiveScreens,
    isActive,
  });
};

export const useWaitForValidOrientation = () => {
  // Use memoized safe area frame to synchronize with Scene's dimension source
  // This prevents race conditions where the orientation check passes before
  // Scene's memoFrame has updated to the new dimensions
  const { width: screenWidth, height } = useMemoizedSafeAreaFrame({
    updateForInactiveScreens: false,
  });

  const currentScreenData = useCurrentScreenData();

  const { screenData } = useRoute();

  const [readyState, setReadyState] = useState(false);

  const isTablet = useIsTablet();

  const { appData } = usePickFromState(["appData"]);
  const isTabletPortrait = appData?.isTabletPortrait;

  const layoutData = useMemo(
    () => ({ isTablet, isTabletPortrait, width: screenWidth, height }),
    [isTablet, isTabletPortrait, screenWidth, height]
  );

  const targetScreenData =
    currentScreenData || (screenData as any)?.targetScreen || screenData;

  const orientation = useGetScreenOrientation(targetScreenData);

  const isReadyForDisplay = isOrientationCompatible({
    orientation,
    layoutData,
  });

  useEffect(() => {
    if (isReadyForDisplay && !readyState) {
      setReadyState(true);
    }
  }, [readyState, orientation, layoutData]);

  return readyState;
};
