"use client"

import { useCallback, useRef, useState } from "react"
import {
  pathsInMarqueeRect,
  shouldIgnoreDriveMarqueeStart,
  type DriveMarqueeRect,
} from "@/lib/drive/drive-marquee"
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"

export function useDriveMarqueeSelection(enabled: boolean) {
  const selectedPaths = useDriveUIStore((s) => s.selectedPaths)
  const setSelectedPaths = useDriveUIStore((s) => s.setSelectedPaths)
  const clearSelection = useDriveUIStore((s) => s.clearSelection)

  const cardRefs = useRef(new Map<string, HTMLDivElement>())
  const dragRef = useRef<{
    startX: number
    startY: number
    additive: boolean
    baseSelection: Set<string>
  } | null>(null)
  const [marquee, setMarquee] = useState<DriveMarqueeRect | null>(null)

  const registerCardRef = useCallback((path: string, el: HTMLDivElement | null) => {
    if (el) cardRefs.current.set(path, el)
    else cardRefs.current.delete(path)
  }, [])

  const onSurfacePointerDown = useCallback(
    (e: React.PointerEvent) => {
      if (!enabled || e.button !== 0) return
      // Touch scroll on empty surface must not wipe mobile selection.
      if (e.pointerType === "touch") return
      const target = e.target as HTMLElement
      if (shouldIgnoreDriveMarqueeStart(target)) return

      const additive = e.ctrlKey || e.metaKey || e.shiftKey
      const baseSelection = additive ? new Set(selectedPaths) : new Set<string>()
      if (!additive) clearSelection()

      dragRef.current = {
        startX: e.clientX,
        startY: e.clientY,
        additive,
        baseSelection,
      }

      const update = (clientX: number, clientY: number) => {
        const state = dragRef.current
        if (!state) return
        const left = Math.min(state.startX, clientX)
        const top = Math.min(state.startY, clientY)
        const width = Math.abs(clientX - state.startX)
        const height = Math.abs(clientY - state.startY)
        const rect = { left, top, width, height }
        setMarquee(rect)
        const hit = pathsInMarqueeRect(cardRefs.current, rect)
        if (state.additive) {
          setSelectedPaths([...state.baseSelection, ...hit])
        } else {
          setSelectedPaths(hit)
        }
      }

      update(e.clientX, e.clientY)

      const onMove = (ev: PointerEvent) => update(ev.clientX, ev.clientY)
      const onUp = () => {
        dragRef.current = null
        setMarquee(null)
        window.removeEventListener("pointermove", onMove)
        window.removeEventListener("pointerup", onUp)
      }
      window.addEventListener("pointermove", onMove)
      window.addEventListener("pointerup", onUp)
    },
    [clearSelection, enabled, selectedPaths, setSelectedPaths]
  )

  return { registerCardRef, onSurfacePointerDown, marquee }
}
