import React, { forwardRef, useCallback, useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import Header from "./Header/Header";
import Loading from "./Loading";
import useIphoneFocusFix from "./utils/useIphoneFocusFix";

import clsx from "clsx";
import { Theme } from "./const";
import { disableBodyScroll, enableBodyScroll } from "./utils/bodyScrollLock";
import useOnClickOutside from "./utils/useClickOutside";

export interface PropsType {
  className?: string;
  theme?: Theme;
  fixed?: boolean;
  opened: boolean;
  onClose?: () => void;
  onBack?: () => void;
  onScroll?: (e: any) => void;
  title?: string;
  renderTitle?: React.ReactNode;
  back?: boolean; // show back icon on left top
  close?: boolean; // show close icon on right top
  children: React.ReactNode;
  isLoading?: boolean;
  header?: React.ReactNode;
  bodyClassName?: string;
  bodyStyle?: React.CSSProperties;
  getContainer?: HTMLElement | (() => HTMLElement);
}

const Popup = (
  {
    className,
    fixed = true,
    title,
    renderTitle,
    theme = Theme.LIGHT,
    opened,
    close,
    back,
    children,
    onClose,
    onBack,
    isLoading,
    header,
    bodyClassName,
    bodyStyle,
    onScroll,
    getContainer,
  }: PropsType,
  ref: React.ForwardedRef<HTMLDivElement>,
) => {
  const bodyRef = useRef<HTMLDivElement>(null);

  // prevent PullToRefresh in ios
  const handleTouchMove = useCallback((e: TouchEvent) => {
    const target = e.target as HTMLElement;
    const isModalOverlay = target.id === "tomo-modal";
    const isScrollableArea = target.closest(".uikit-popup-enable-scroll");
    const isNonScrollableArea = target.closest(".uikit-popup-prevent-scroll");

    // Prevent default scroll behavior if:
    // 1. Target is modal overlay
    // 2. Target is not in a scrollable area
    // 3. Target is in an explicitly non-scrollable area
    const shouldPreventScroll = isModalOverlay || !isScrollableArea || isNonScrollableArea;

    if (shouldPreventScroll) {
      e.preventDefault();
    }
  }, []);

  useEffect(() => {
    const isNestPopup = checkParentForId(bodyRef?.current, "tomo-modal-body");
    if (isNestPopup) return;
    const targetElement = document.querySelector("body");

    if (opened) {
      disableBodyScroll(targetElement);
      document.addEventListener("touchmove", handleTouchMove, {
        passive: false,
      });
    } else {
      enableBodyScroll(targetElement);
      document.removeEventListener("touchmove", handleTouchMove);
    }

    return () => {
      enableBodyScroll(targetElement);
      document.removeEventListener("touchmove", handleTouchMove);
    };
  }, [opened, bodyRef, handleTouchMove]);

  useIphoneFocusFix(opened);
  const handleScroll = useCallback(
    (e: React.UIEvent<HTMLDivElement, UIEvent>) => {
      onScroll?.(e);
    },
    [onScroll],
  );

  useOnClickOutside(bodyRef, () => {
    onClose?.();
  });

  const popupContent = (
    <div
      ref={ref}
      id="tomo-modal"
      className={clsx(
        "uikit-select-none uikit-left-0 uikit-top-0 uikit-right-0 uikit-z-40 uikit-flex uikit-items-end uikit-h-full uikit-w-full uikit-bg-tc1/30 uikit-font-switzer uikit-overflow-auto uikit-text-primary uikit-box-border hide-scrollbar",
        { "uikit-hidden": !opened },
        fixed ? "uikit-fixed" : "uikit-absolute",
        `uikit-${theme}`,
        className,
      )}
      style={{
        overscrollBehavior: "none",
        WebkitOverflowScrolling: "touch",
      }}
      onClick={onClose}
      onScroll={handleScroll}
    >
      <div
        ref={bodyRef}
        id="tomo-modal-body"
        className={clsx(
          "uikit-relative uikit-max-h-full sm:uikit-relative uikit-flex uikit-flex-col uikit-bottom-0 uikit-left-0 uikit-w-full uikit-overflow-hidden uikit-rounded-t-2xl sm:uikit-rounded-b-2xl animate__animated animate__fadeInUp animate__faster uikit-transition-height uikit-duration-200 uikit-ease-in-out uikit-bg-white dark:uikit-bg-[#121214]",
          fixed ? "sm:uikit-m-auto sm:uikit-w-auto sm:uikit-animate-none sm:uikit-min-w-[375px]" : "",
          bodyClassName,
        )}
        style={{
          transition: "height 1s ease-in-out",
          boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.3)",
          animationDuration: "0.4s",
          animationFillMode: "initial !important",
          ...(bodyStyle || {}),
        }}
        onTouchEnd={(e) => e.stopPropagation()}
        onClick={(e) => e.stopPropagation()}
      >
        {header || (
          <Header title={title} renderTitle={renderTitle} close={close} back={back} onClose={onClose} onBack={onBack} />
        )}
        {children}
        {isLoading && <Loading />}
      </div>
    </div>
  );

  if (!getContainer) {
    return popupContent;
  }

  // 获取挂载容器
  let container: HTMLElement;
  if (typeof getContainer === "function") {
    container = getContainer();
  } else if (getContainer instanceof HTMLElement) {
    container = getContainer;
  } else {
    container = document.body;
  }

  return createPortal(popupContent, container || document.body);
};

export default forwardRef(Popup);

/**
 * Checks if any parent element of the given HTML element has the specified ID.
 *
 * @param element - The starting HTML element to check.
 * @param id - The ID to search for in the element's ancestors.
 * @returns `true` if an ancestor with the specified ID is found, otherwise `false`.
 */

const checkParentForId = (element: HTMLElement | null, id: string): boolean => {
  let parent = element?.parentElement;
  while (parent) {
    if (parent.id === id) {
      return true;
    }
    parent = parent.parentElement;
  }
  return false;
};
