import { useState, useRef, useCallback, useEffect, type RefObject } from 'react';
import { bindWindowDrag, clientXYFromReact, isPrimaryPointerButton } from '../utils/pointerDrag';

export interface DraggablePosition {
  x: number;
  y: number;
}

export interface UseDraggablePanelOptions {
  /** 마운트 후 패널 크기 기준 화면 중앙 배치 */
  centerOnMount?: boolean;
  initialPosition?: DraggablePosition;
  panelRef?: RefObject<HTMLElement | null>;
}

const DEFAULT_POS: DraggablePosition = { x: 80, y: 72 };

/**
 * 팝업 패널 타이틀바 드래그 이동 (마우스·터치·펜)
 */
export function useDraggablePanel(options: UseDraggablePanelOptions = {}) {
  const {
    centerOnMount = false,
    initialPosition = DEFAULT_POS,
    panelRef: externalRef,
  } = options;

  const internalRef = useRef<HTMLDivElement>(null);
  const panelRef = (externalRef ?? internalRef) as RefObject<HTMLDivElement | null>;
  const [pos, setPos] = useState<DraggablePosition>(initialPosition);
  const [dragging, setDragging] = useState(false);
  const dragOrigin = useRef({ mx: 0, my: 0, px: 0, py: 0 });
  const centeredOnce = useRef(false);
  const unbindDragRef = useRef<(() => void) | null>(null);

  useEffect(() => {
    if (!centerOnMount || centeredOnce.current) return;
    const el = panelRef.current;
    if (!el) return;

    const placeCenter = () => {
      const w = el.offsetWidth || 400;
      const h = el.offsetHeight || 320;
      setPos({
        x: Math.max(8, (window.innerWidth - w) / 2),
        y: Math.max(8, (window.innerHeight - h) / 2),
      });
      centeredOnce.current = true;
    };

    placeCenter();
    const id = requestAnimationFrame(placeCenter);
    return () => cancelAnimationFrame(id);
  }, [centerOnMount, panelRef]);

  const endDrag = useCallback(() => {
    unbindDragRef.current?.();
    unbindDragRef.current = null;
    setDragging(false);
  }, []);

  const onHeaderPointerDown = useCallback((e: React.PointerEvent) => {
    if (!isPrimaryPointerButton(e)) return;
    if ((e.target as HTMLElement).closest('button')) return;
    e.preventDefault();
    e.stopPropagation();
    const el = e.currentTarget as HTMLElement;
    try {
      el.setPointerCapture(e.pointerId);
    } catch {
      /* ignore */
    }
    const { x, y } = clientXYFromReact(e);
    setDragging(true);
    dragOrigin.current = { mx: x, my: y, px: pos.x, py: pos.y };

    unbindDragRef.current?.();
    unbindDragRef.current = bindWindowDrag(
      ({ x: cx, y: cy }) => {
        const o = dragOrigin.current;
        setPos({
          x: o.px + (cx - o.mx),
          y: o.py + (cy - o.my),
        });
      },
      endDrag,
    );
  }, [pos, endDrag]);

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

  const panelStyle: React.CSSProperties = {
    position: 'fixed',
    left: pos.x,
    top: pos.y,
  };

  return {
    panelRef: internalRef,
    pos,
    dragging,
    /** @deprecated onHeaderPointerDown 사용 */
    onHeaderMouseDown: onHeaderPointerDown,
    onHeaderPointerDown,
    panelStyle,
    headerCursor: dragging ? 'grabbing' : 'grab',
    headerTouchStyle: { touchAction: 'none' as const },
  };
}
