import { memo, useCallback, useMemo, useRef, useState, type CSSProperties, type RefObject } from "react";
import BookPage from "@/pages/viewer/components/BookPage";
import type { PageData } from "@/pages/viewer/types";
import { resolvePageBackground, type PageBackgroundDefaults } from "@/pages/viewer/utils/pageBackground";
import { MAGNIFIER_SIZE, ZOOM_SCALE } from "./constants";
import styles from "./Magnifier.module.css";
import { useMagnifier } from "./useMagnifier";

const noopLinkClick = () => {};

export type MagnifierProps = {
  enabled: boolean;
  /** مرجع مختصات برای موقعیت‌دهی لنز (معمولاً ناحیهٔ اطراف کتاب) */
  containerRef: RefObject<HTMLElement | null>;
  /** ناحیه‌ای که رویدادهای موس روی آن گوش داده می‌شود (wrapper کتاب) */
  interactionRef: RefObject<HTMLElement | null>;
  /** صفحاتی که هم‌اکنون در DOM رندر شده‌اند (برای نگاشت pageId به داده) */
  pages: PageData[];
  pageWidth: number;
  pageHeight: number;
  contentScale: number;
  pageDefaults: PageBackgroundDefaults;
  useHardPage?: boolean;
  /** در حین انیمیشن ورق‌خوردن true است */
  isFlippingRef: RefObject<boolean>;
  /** در حالت تک‌صفحه (موبایل) همیشه صفحهٔ فعلی بزرگ‌نمایی می‌شود */
  lockedPageId?: number | null;
  blockFlipTouch?: boolean;
  /** با تغییر آن (ورق خوردن) ذره‌بین ریست می‌شود */
  pageIndex?: number;
};

const Magnifier = memo(
  ({
    enabled,
    containerRef,
    interactionRef,
    pages,
    pageWidth,
    pageHeight,
    contentScale,
    pageDefaults,
    useHardPage = false,
    isFlippingRef,
    lockedPageId = null,
    blockFlipTouch = false,
    pageIndex,
  }: MagnifierProps) => {
    const overlayRef = useRef<HTMLDivElement>(null);
    const lensRef = useRef<HTMLDivElement>(null);
    const mirrorRef = useRef<HTMLDivElement>(null);
    const [activePageId, setActivePageId] = useState<number | null>(null);

    const handleActivePageChange = useCallback((pageId: number | null) => {
      setActivePageId(pageId);
    }, []);

    useMagnifier({
      enabled,
      containerRef,
      interactionRef,
      overlayRef,
      lensRef,
      mirrorRef,
      isFlippingRef,
      lockedPageId,
      blockFlipTouch,
      pageIndex,
      onActivePageChange: handleActivePageChange,
    });

    const lockedPage = useMemo(
      () => (lockedPageId != null ? pages.find((p) => p.id === lockedPageId) : undefined),
      [lockedPageId, pages],
    );

    const activePage = useMemo(() => {
      if (lockedPage) return lockedPage;
      return activePageId != null ? pages.find((p) => p.id === activePageId) : undefined;
    }, [lockedPage, pages, activePageId]);

    const background = useMemo(
      () => (activePage ? resolvePageBackground(activePage, pageDefaults) : null),
      [activePage, pageDefaults],
    );

    return (
      <div
        ref={overlayRef}
        className={styles.root}
        aria-hidden
        data-magnifier-overlay
        style={{ display: enabled ? "block" : "none" }}
      >
        <div
          ref={lensRef}
          className={styles.lens}
          style={{ "--magnifier-size": `${MAGNIFIER_SIZE}px` } as CSSProperties}
        >
          <div className={styles.content}>
            {activePage && background && (
              <div ref={mirrorRef} className={styles.mirror}>
                <BookPage
                  page={activePage}
                  scale={contentScale * ZOOM_SCALE}
                  pageWidth={pageWidth * ZOOM_SCALE}
                  pageHeight={pageHeight * ZOOM_SCALE}
                  onLinkClick={noopLinkClick}
                  backgroundType={background.backgroundType}
                  backgroundColor={background.backgroundColor}
                  backgroundGradient={background.backgroundGradient}
                  backgroundImageUrl={background.backgroundImageUrl}
                  backgroundVideoUrl={background.backgroundVideoUrl}
                  useHardPage={useHardPage}
                  disableEntranceAnimations
                  showPaperShadow={false}
                  idSuffix="-magnifier"
                />
              </div>
            )}
          </div>
        </div>
      </div>
    );
  },
);

Magnifier.displayName = "Magnifier";

export default Magnifier;
