import type { CSSProperties } from "react";
import type { EditorObject } from "@/pages/editor/store/editorStore";
import type { EntrancePhase } from "@/pages/viewer/hooks/useBookEntranceController";
import {
  DEFAULT_ENTRANCE_DURATION_MS,
  DEFAULT_ENTRANCE_DELAY_MS,
  ENTRANCE_ANIMATION_BASE_DELAY_MS,
  MAX_ENTRANCE_DELAY_MS,
} from "@/shared/entranceAnimation";

const ANIMATION_NAMES: Record<
  NonNullable<EditorObject["entranceAnimation"]>,
  string
> = {
  none: "",
  fade: "viewer-entrance-fade",
  flyInLeft: "viewer-entrance-fly-left",
  flyInRight: "viewer-entrance-fly-right",
  flyInTop: "viewer-entrance-fly-top",
  flyInBottom: "viewer-entrance-fly-bottom",
  zoomIn: "viewer-entrance-zoom-in",
  zoomOut: "viewer-entrance-zoom-out",
};

/** فاصلهٔ حرکت برای fly تا از بیرون کادر صفحه وارد شود (حداقل به اندازهٔ پهنا/ارتفاع صفحه) */
function flyTravelDistancePx(
  type: EditorObject["entranceAnimation"],
  layoutW: number,
  layoutH: number,
  scale: number,
): number {
  const pad = 32;
  const fallback = Math.max(80, Math.round(56 * scale));

  switch (type) {
    case "flyInLeft":
    case "flyInRight":
      return Math.max(layoutW + pad, fallback);
    case "flyInTop":
    case "flyInBottom":
      return Math.max(layoutH + pad, fallback);
    default:
      return fallback;
  }
}

export function mergeEntranceAnimationStyle(
  base: CSSProperties,
  obj: EditorObject,
  scale: number,
  elementIndex: number,
  phase: EntrancePhase,
  options?: {
    transformOrigin?: CSSProperties["transformOrigin"];
    rotationDeg?: number;
    /** ابعاد کادر صفحه (px) برای محاسبهٔ مسیر fly از بیرون */
    flyLayoutPx?: { width: number; height: number };
  },
): CSSProperties {
  const type = obj.entranceAnimation;
  if (!type || type === "none" || phase === "settled") {
    return base;
  }

  if (phase === "idle") {
    const { opacity: _o, ...rest } = base;
    return {
      ...rest,
      opacity: 0,
    };
  }

  const name = ANIMATION_NAMES[type];
  if (!name) return base;

  const durationSec =
    Math.min(4000, Math.max(100, obj.entranceDurationMs ?? DEFAULT_ENTRANCE_DURATION_MS)) /
    1000;
  const baseDelaySec = ENTRANCE_ANIMATION_BASE_DELAY_MS / 1000;
  const staggerSec = Math.min(elementIndex * 0.045, 1.2);
  const userDelayMs = Math.min(
    MAX_ENTRANCE_DELAY_MS,
    Math.max(DEFAULT_ENTRANCE_DELAY_MS, obj.entranceDelayMs ?? DEFAULT_ENTRANCE_DELAY_MS),
  );
  const userDelaySec = userDelayMs / 1000;

  const rot = options?.rotationDeg ?? obj.rotation ?? 0;
  const opacityEnd = (obj.opacity ?? 100) / 100;

  const layout = options?.flyLayoutPx;
  const isFly =
    type === "flyInLeft" ||
    type === "flyInRight" ||
    type === "flyInTop" ||
    type === "flyInBottom";
  const dist =
    layout && isFly
      ? Math.round(flyTravelDistancePx(type, layout.width, layout.height, scale))
      : Math.round(56 * scale);

  const { transform: _t, opacity: _o, ...restBase } = base;

  return {
    ...restBase,
    ["--ve-rot" as string]: `${rot}deg`,
    ["--ve-opacity-end" as string]: String(opacityEnd),
    ["--ve-dist" as string]: `${dist}px`,
    transformOrigin: options?.transformOrigin ?? base.transformOrigin ?? "top left",
    willChange: "transform, opacity",
    animationName: name,
    animationDuration: `${durationSec}s`,
    animationDelay: `${baseDelaySec + staggerSec + userDelaySec}s`,
    animationTimingFunction: "cubic-bezier(0.22, 1, 0.36, 1)",
    animationFillMode: "both",
  };
}
