import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'

export const ISLANDER_POSITION_KEY = 'haixun.islander.pos'
export const ISLANDER_EXPANDED_KEY = 'haixun.islander.expanded'

export const ISLANDER_DOCK_WIDTH = 72
export const ISLANDER_DOCK_HEIGHT = 96
export const ISLANDER_DOCK_SIZE = ISLANDER_DOCK_WIDTH
export const ISLANDER_EDGE_PADDING = 12
export const ISLANDER_MOBILE_DOCK_HEIGHT = 96
export const ISLANDER_DRAG_THRESHOLD = 5

export type IslanderPosition = { x: number; y: number }

export type IslanderDragSession = {
  active: boolean
  moved: boolean
  pointerId: number
  startX: number
  startY: number
  originX: number
  originY: number
}

function readStoredPosition(): IslanderPosition | null {
  try {
    const raw = localStorage.getItem(ISLANDER_POSITION_KEY)
    if (!raw) return null
    const parsed = JSON.parse(raw) as IslanderPosition
    if (typeof parsed.x === 'number' && typeof parsed.y === 'number') return parsed
  } catch {
    // ignore
  }
  return null
}

export function defaultIslanderPosition() {
  const mobile = window.innerWidth < 1024
  const bottomGap = mobile ? ISLANDER_MOBILE_DOCK_HEIGHT : ISLANDER_EDGE_PADDING
  return {
    x: Math.max(
      ISLANDER_EDGE_PADDING,
      window.innerWidth - ISLANDER_EDGE_PADDING - ISLANDER_DOCK_WIDTH,
    ),
    y: Math.max(ISLANDER_EDGE_PADDING, window.innerHeight - bottomGap - ISLANDER_DOCK_HEIGHT),
  }
}

export function clampIslanderPosition(
  position: IslanderPosition,
  size: { width: number; height: number },
): IslanderPosition {
  const maxX = Math.max(ISLANDER_EDGE_PADDING, window.innerWidth - size.width - ISLANDER_EDGE_PADDING)
  const maxY = Math.max(ISLANDER_EDGE_PADDING, window.innerHeight - size.height - ISLANDER_EDGE_PADDING)
  return {
    x: Math.min(Math.max(position.x, ISLANDER_EDGE_PADDING), maxX),
    y: Math.min(Math.max(position.y, ISLANDER_EDGE_PADDING), maxY),
  }
}

export function readIslanderExpandedPreference() {
  try {
    return localStorage.getItem(ISLANDER_EXPANDED_KEY) === '1'
  } catch {
    return false
  }
}

export function useIslanderPosition() {
  const [position, setPosition] = useState<IslanderPosition>(defaultIslanderPosition)
  const [dragging, setDragging] = useState(false)
  const dragRef = useRef<IslanderDragSession>({
    active: false,
    moved: false,
    pointerId: -1,
    startX: 0,
    startY: 0,
    originX: 0,
    originY: 0,
  })

  const persistPosition = useCallback((next: IslanderPosition) => {
    try {
      localStorage.setItem(ISLANDER_POSITION_KEY, JSON.stringify(next))
    } catch {
      // ignore
    }
  }, [])

  const syncClampedPosition = useCallback(() => {
    setPosition((prev) => {
      const next = clampIslanderPosition(prev, {
        width: ISLANDER_DOCK_WIDTH,
        height: ISLANDER_DOCK_HEIGHT,
      })
      if (next.x === prev.x && next.y === prev.y) return prev
      persistPosition(next)
      return next
    })
  }, [persistPosition])

  useLayoutEffect(() => {
    setPosition(readStoredPosition() ?? defaultIslanderPosition())
  }, [])

  useEffect(() => {
    const onResize = () => syncClampedPosition()
    window.addEventListener('resize', onResize)
    return () => window.removeEventListener('resize', onResize)
  }, [syncClampedPosition])

  const updatePosition = useCallback(
    (next: IslanderPosition) => {
      const clamped = clampIslanderPosition(next, {
        width: ISLANDER_DOCK_WIDTH,
        height: ISLANDER_DOCK_HEIGHT,
      })
      setPosition(clamped)
      persistPosition(clamped)
    },
    [persistPosition],
  )

  return {
    position,
    dragging,
    setDragging,
    dragRef,
    updatePosition,
    syncClampedPosition,
  }
}