import { computed, onBeforeUnmount, ref, type CSSProperties } from 'vue'

export interface FloatRect {
  x: number
  y: number
  w: number
  h: number
}

function loadRect(key: string, fallback: FloatRect): FloatRect {
  try {
    const raw = localStorage.getItem(key)
    if (!raw) return fallback
    const parsed = JSON.parse(raw) as FloatRect
    if (
      typeof parsed.x === 'number' &&
      typeof parsed.y === 'number' &&
      typeof parsed.w === 'number' &&
      typeof parsed.h === 'number'
    ) {
      return parsed
    }
  } catch {
    /* ignore */
  }
  return fallback
}

function saveRect(key: string, rect: FloatRect) {
  try {
    localStorage.setItem(key, JSON.stringify(rect))
  } catch {
    /* ignore */
  }
}

/** 可拖动浮动面板位置与尺寸（持久化到 localStorage） */
export function useFloatingPanel(storageKey: string, fallback: FloatRect) {
  const rect = ref<FloatRect>(loadRect(storageKey, fallback))

  let dragOrigin = { px: 0, py: 0, rx: 0, ry: 0 }
  let resizing = false
  let resizeOrigin = { px: 0, py: 0, rw: 0, rh: 0 }

  const panelStyle = computed((): CSSProperties => ({
    left: `${rect.value.x}px`,
    top: `${rect.value.y}px`,
    width: `${rect.value.w}px`,
    height: `${rect.value.h}px`,
  }))

  function clampToViewport() {
    const margin = 8
    const maxW = Math.min(window.innerWidth - margin * 2, 1400)
    const maxH = Math.min(window.innerHeight - margin * 2, 900)
    rect.value.w = Math.max(480, Math.min(rect.value.w, maxW))
    rect.value.h = Math.max(320, Math.min(rect.value.h, maxH))
    rect.value.x = Math.max(margin, Math.min(rect.value.x, window.innerWidth - rect.value.w - margin))
    rect.value.y = Math.max(margin, Math.min(rect.value.y, window.innerHeight - rect.value.h - margin))
  }

  function onDragMove(e: MouseEvent) {
    if (resizing) {
      rect.value.w = Math.max(480, resizeOrigin.rw + e.clientX - resizeOrigin.px)
      rect.value.h = Math.max(320, resizeOrigin.rh + e.clientY - resizeOrigin.py)
      clampToViewport()
      return
    }
    rect.value.x = dragOrigin.rx + e.clientX - dragOrigin.px
    rect.value.y = dragOrigin.ry + e.clientY - dragOrigin.py
    clampToViewport()
  }

  function onDragEnd() {
    resizing = false
    window.removeEventListener('mousemove', onDragMove)
    window.removeEventListener('mouseup', onDragEnd)
    saveRect(storageKey, rect.value)
  }

  function startDrag(e: MouseEvent) {
    if (e.button !== 0) return
    dragOrigin = { px: e.clientX, py: e.clientY, rx: rect.value.x, ry: rect.value.y }
    window.addEventListener('mousemove', onDragMove)
    window.addEventListener('mouseup', onDragEnd)
  }

  function startResize(e: MouseEvent) {
    if (e.button !== 0) return
    e.stopPropagation()
    resizing = true
    resizeOrigin = { px: e.clientX, py: e.clientY, rw: rect.value.w, rh: rect.value.h }
    window.addEventListener('mousemove', onDragMove)
    window.addEventListener('mouseup', onDragEnd)
  }

  function centerOnScreen() {
    rect.value.x = Math.max(16, (window.innerWidth - rect.value.w) / 2)
    rect.value.y = Math.max(16, (window.innerHeight - rect.value.h) / 2)
    saveRect(storageKey, rect.value)
  }

  onBeforeUnmount(() => {
    window.removeEventListener('mousemove', onDragMove)
    window.removeEventListener('mouseup', onDragEnd)
  })

  return {
    rect,
    panelStyle,
    startDrag,
    startResize,
    centerOnScreen,
    clampToViewport,
  }
}
