import { useEffect, useRef } from "react";
import Konva from "konva";
import { Layer, Line } from "react-konva";
import type { Guide } from "./useSnap";

/** پروداکشن: `sessionStorage.setItem('DEBUG_GUIDE_DRAG','1')` سپس رفرش */
function guideDragLog(stage: string, detail: Record<string, unknown>): void {
  if (typeof window === "undefined") return;
  const dev = import.meta.env.DEV;
  let enabled = dev;
  try {
    if (!enabled) enabled = window.sessionStorage.getItem("DEBUG_GUIDE_DRAG") === "1";
  } catch {
    /* private mode */
  }
  if (!enabled) return;
  console.info("[guide-drag]", new Date().toISOString(), stage, detail);
}

type GuidesLayerProps = {
  guides: Guide[];
  stageWidth: number;
  stageHeight: number;
  activeGuideIds: string[];
  selectedGuideId: string | null;
  draftGuide: { orientation: Guide["orientation"]; position: number } | null;
  onGuideSelect: (id: string) => void;
  onGuideDragEnd: (id: string, position: number, shouldRemove: boolean) => void;
};

const GuidesLayer = ({
  guides,
  stageWidth,
  stageHeight,
  activeGuideIds,
  selectedGuideId,
  draftGuide,
  onGuideSelect,
  onGuideDragEnd,
}: GuidesLayerProps) => {
  const abortActiveSessionRef = useRef<(() => void) | null>(null);

  useEffect(
    () => () => {
      abortActiveSessionRef.current?.();
      abortActiveSessionRef.current = null;
    },
    [],
  );

  const finalizeGuideDrag = (
    guideId: string,
    orientation: Guide["orientation"],
    x: number,
    y: number,
    reason?: string,
  ) => {
    const nextPosition = orientation === "vertical" ? x : y;
    const shouldRemove =
      orientation === "vertical"
        ? nextPosition < 0 || nextPosition > stageWidth
        : nextPosition < 0 || nextPosition > stageHeight;
    guideDragLog("finalize", {
      guideId,
      orientation,
      x,
      y,
      nextPosition,
      shouldRemove,
      reason,
    });
    onGuideDragEnd(guideId, nextPosition, shouldRemove);
  };

  const attachPointerGuideDrag = (
    guide: Guide,
    e: Konva.KonvaEventObject<PointerEvent>,
  ) => {
    const evt = e.evt;
    if (evt.pointerType === "mouse" && evt.button !== 0) return;

    const node = e.target as Konva.Line;
    const stage = node.getStage();
    if (!stage) {
      guideDragLog("abort-no-stage", { guideId: guide.id });
      return;
    }

    const container = stage.container();

    abortActiveSessionRef.current?.();
    abortActiveSessionRef.current = null;

    let settled = false;
    const settle = (reason: string) => {
      if (settled) return;
      settled = true;
      guideDragLog("settle", { guideId: guide.id, pointerId: evt.pointerId, reason });

      window.removeEventListener("pointermove", onPointerMove);
      window.removeEventListener("pointerup", onPointerEnd);
      window.removeEventListener("pointercancel", onPointerEnd);
      window.removeEventListener("blur", onBlur);
      document.removeEventListener("visibilitychange", onVisibilityHidden);

      try {
        if (typeof container.releasePointerCapture === "function") {
          container.releasePointerCapture(evt.pointerId);
        }
      } catch {
        /* ignore */
      }

      abortActiveSessionRef.current = null;

      const x = node.x();
      const y = node.y();
      const nextPosition = guide.orientation === "vertical" ? x : y;
      const guidesWillRemove =
        guide.orientation === "vertical"
          ? nextPosition < 0 || nextPosition > stageWidth
          : nextPosition < 0 || nextPosition > stageHeight;

      if (!guidesWillRemove) {
        onGuideSelect(guide.id);
      }

      finalizeGuideDrag(guide.id, guide.orientation, x, y, reason);
    };

    const onPointerMove = (moveEvt: PointerEvent) => {
      if (moveEvt.pointerId !== evt.pointerId) return;
      moveEvt.preventDefault();
      const pp = stage.getPointerPosition();
      if (!pp) {
        guideDragLog("move-no-pointer-pos", {});
        return;
      }
      const x = pp.x / stage.scaleX();
      const y = pp.y / stage.scaleY();

      const isVertical = guide.orientation === "vertical";
      if (isVertical) {
        node.x(x);
        node.y(0);
      } else {
        node.x(0);
        node.y(y);
      }
      node.getLayer()?.batchDraw();
    };

    const onPointerEnd = (endEvt: PointerEvent) => {
      if (endEvt.pointerId !== evt.pointerId) return;
      settle(endEvt.type === "pointercancel" ? "pointercancel" : "pointerup");
    };

    const onBlur = () => settle("window-blur");

    const onVisibilityHidden = () => {
      if (document.visibilityState === "hidden") settle("document-hidden");
    };

    abortActiveSessionRef.current = () => settle("session-aborted");

    window.addEventListener("pointermove", onPointerMove, { passive: false });
    window.addEventListener("pointerup", onPointerEnd);
    window.addEventListener("pointercancel", onPointerEnd);
    window.addEventListener("blur", onBlur);
    document.addEventListener("visibilitychange", onVisibilityHidden);

    guideDragLog("pointerdown-attached", {
      guideId: guide.id,
      pointerId: evt.pointerId,
      pointerType: evt.pointerType,
    });

    try {
      container.setPointerCapture(evt.pointerId);
    } catch (err) {
      guideDragLog("set-pointer-capture-failed", {
        pointerId: evt.pointerId,
        message: String(err),
      });
    }
  };

  return (
    <Layer>
      {guides.map((guide) => {
        const isVertical = guide.orientation === "vertical";
        const isActive = activeGuideIds.includes(guide.id);
        const isSelected = selectedGuideId === guide.id;

        return (
          <Line
            key={guide.id}
            id={guide.id}
            name="guide-line"
            x={isVertical ? guide.position : 0}
            y={isVertical ? 0 : guide.position}
            points={isVertical ? [0, 0, 0, stageHeight] : [0, 0, stageWidth, 0]}
            stroke={isSelected ? "#2563eb" : isActive ? "#1d4ed8" : "#60a5fa"}
            strokeWidth={isSelected ? 2.5 : isActive ? 2 : 1}
            dash={[6, 6]}
            hitStrokeWidth={12}
            listening
            draggable={false}
            onPointerDown={(e) => {
              e.cancelBubble = true;
              attachPointerGuideDrag(guide, e);
            }}
          />
        );
      })}
      {draftGuide && (
        <Line
          name="guide-line-draft"
          listening={false}
          draggable={false}
          x={draftGuide.orientation === "vertical" ? draftGuide.position : 0}
          y={draftGuide.orientation === "vertical" ? 0 : draftGuide.position}
          points={
            draftGuide.orientation === "vertical"
              ? [0, 0, 0, stageHeight]
              : [0, 0, stageWidth, 0]
          }
          stroke="#2563eb"
          strokeWidth={1.5}
          dash={[6, 6]}
          opacity={0.9}
        />
      )}
    </Layer>
  );
};

export default GuidesLayer;
