// composables/useFloatingDrag.ts
// 浮窗拖动逻辑 — Pointer Events 统一处理鼠标和触屏

import { ref, onBeforeUnmount, type Ref } from "vue";

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

export function useFloatingDrag(
  position: Ref<DragPosition>,
  elementRef: Ref<HTMLElement | null>
) {
  const isDragging = ref(false);
  const dragMoved = ref(false);
  let dragResetTimer: ReturnType<typeof setTimeout> | null = null;

  /** 清理拖拽期间注册的事件监听器（组件卸载时使用） */
  function cleanupDragListeners(): void {
    const el = elementRef.value;
    if (el) {
      el.removeEventListener("pointermove", onPointerMove);
      el.removeEventListener("pointerup", onPointerUp);
      el.removeEventListener("pointercancel", onPointerUp);
    }
    if (dragResetTimer) {
      clearTimeout(dragResetTimer);
      dragResetTimer = null;
    }
  }

  onBeforeUnmount(() => {
    cleanupDragListeners();
  });

  /** pointerdown 时记录的元素尺寸和指针在元素内的偏移 */
  let dragMeta: {
    width: number;
    height: number;
    offsetX: number;
    offsetY: number;
    hasMoved: boolean;
  } | null = null;

  function onPointerDown(e: PointerEvent): void {
    // 只响应主按键（左键 / 单指触屏）
    if (e.button !== 0 && e.pointerType === "mouse") return;

    const el = elementRef.value;
    if (!el) return;

    const rect = el.getBoundingClientRect();

    dragMeta = {
      width: rect.width,
      height: rect.height,
      offsetX: e.clientX - rect.left,
      offsetY: e.clientY - rect.top,
      hasMoved: false
    };

    // 先 capture 指针以保证可靠追踪，但先不标记为拖拽中
    // isDragging 推迟到 pointermove 超过阈值才设置，避免点击按钮时闪一下 grab 光标
    el.setPointerCapture(e.pointerId);

    el.addEventListener("pointermove", onPointerMove);
    el.addEventListener("pointerup", onPointerUp);
    el.addEventListener("pointercancel", onPointerUp);
  }

  function onPointerMove(e: PointerEvent): void {
    if (!dragMeta) return;

    const vw = window.innerWidth;
    const vh = window.innerHeight;

    let newX = e.clientX - dragMeta.offsetX;
    let newY = e.clientY - dragMeta.offsetY;

    // 边界钳制
    newX = Math.max(0, Math.min(newX, vw - dragMeta.width));
    newY = Math.max(0, Math.min(newY, vh - dragMeta.height));

    // 移动超过 3px 才标记为拖拽（避免误触）
    if (!dragMeta.hasMoved && (Math.abs(newX - position.value.x) > 3 || Math.abs(newY - position.value.y) > 3)) {
      dragMeta.hasMoved = true;
      isDragging.value = true;
    }

    if (dragMeta.hasMoved) {
      position.value = { x: newX, y: newY };
    }
  }

  function onPointerUp(_e: PointerEvent): void {
    const didMove = dragMeta?.hasMoved ?? false;

    const el = elementRef.value;
    if (el) {
      el.removeEventListener("pointermove", onPointerMove);
      el.removeEventListener("pointerup", onPointerUp);
      el.removeEventListener("pointercancel", onPointerUp);
    }

    isDragging.value = false;

    // Pointer up 先于 click 触发，用 dragMoved 标记本次是否为拖拽，
    // click 处理器可通过 dragMoved 跳过拖拽后的误触展开
    if (didMove) {
      dragMoved.value = true;
      if (dragResetTimer) clearTimeout(dragResetTimer);
      dragResetTimer = setTimeout(() => {
        dragMoved.value = false;
        dragResetTimer = null;
      }, 300);
    }

    dragMeta = null;
  }

  return {
    isDragging,
    dragMoved,
    onPointerDown
  };
}
