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

// Multi-select over a photo list. Selection lives here (not in the gallery)
// so it survives lightbox open/close, and is pruned automatically when
// photos disappear from the list (deletes, polling refreshes).
export default function useSelection(photos) {
  const [selected, setSelected] = useState(() => new Set())
  // Anchor for shift-click range selection: the photo last toggled.
  const lastToggled = useRef(null)

  useEffect(() => {
    setSelected((prev) => {
      if (prev.size === 0) return prev
      const valid = new Set(photos.map((p) => p.id))
      const next = new Set([...prev].filter((id) => valid.has(id)))
      return next.size === prev.size ? prev : next
    })
  }, [photos])

  // Shift-toggle selects the whole range from the previously toggled photo
  // (both directions), so contiguous runs don't need per-photo clicks. The
  // range walks `list` — the photo order the user is actually looking at —
  // which callers with a filtered view must pass explicitly, so hidden
  // photos are never swept into the selection. Anchor updates and range
  // computation stay out of the setSelected updater: React may re-invoke
  // updaters (StrictMode does), so they must be pure.
  const toggle = (photoId, shift = false, list = photos) => {
    const anchor = lastToggled.current
    lastToggled.current = photoId
    if (shift && anchor) {
      const a = list.findIndex((p) => p.id === anchor)
      const b = list.findIndex((p) => p.id === photoId)
      if (a >= 0 && b >= 0) {
        const range = list.slice(Math.min(a, b), Math.max(a, b) + 1).map((p) => p.id)
        setSelected((prev) => new Set([...prev, ...range]))
        return
      }
    }
    setSelected((prev) => {
      const next = new Set(prev)
      if (next.has(photoId)) next.delete(photoId)
      else next.add(photoId)
      return next
    })
  }

  // Adds `list` (the caller's currently visible photos) to the selection —
  // additive, so selecting all of one filtered view keeps picks from another.
  const selectAll = (list) =>
    setSelected((prev) => new Set([...prev, ...list.map((p) => p.id)]))
  const clear = () => {
    // Reset the anchor too — a shift-click after Clear must start fresh, not
    // extend a range from a photo selected before the wipe.
    lastToggled.current = null
    setSelected(new Set())
  }
  const selectedBytes = photos.reduce((sum, p) => sum + (selected.has(p.id) ? p.size_bytes : 0), 0)
  const totalBytes = photos.reduce((sum, p) => sum + p.size_bytes, 0)

  return { selected, toggle, selectAll, clear, selectedBytes, totalBytes }
}
