// ── Selection composable: lasso, multi-select, hover linking, batch ops ───────
import { ref, computed } from 'vue'
import { localDateStr } from './useHelpers'

export function useSelection (deps) {
  const { store, periodStart, smartAssign, invalidateRoutes, fullUnassign } = deps

  const hoveredJobId = ref(null)
  const selectedJob  = ref(null)   // { job, techId, isAssist?, assistTechId? }
  const multiSelect  = ref([])     // [{ job, techId, isAssist?, assistTechId? }]

  // ── Select / toggle ─────────────────────────────────────────────────────────
  function selectJob (job, techId, isAssist = false, assistTechId = null, event = null, rightPanel = null) {
    const entry = { job, techId, isAssist, assistTechId }
    const isMulti = event && (event.ctrlKey || event.metaKey)
    if (isMulti) {
      const idx = multiSelect.value.findIndex(s => s.job.id === job.id && s.isAssist === isAssist)
      if (idx >= 0) multiSelect.value.splice(idx, 1)
      else multiSelect.value.push(entry)
      selectedJob.value = entry
    } else {
      multiSelect.value = []
      const same = selectedJob.value?.job?.id === job.id && selectedJob.value?.isAssist === isAssist && selectedJob.value?.assistTechId === assistTechId
      selectedJob.value = same ? null : entry
      if (!same && rightPanel !== undefined) {
        const tech = store.technicians.find(t => t.id === (techId || job.assignedTech))
        if (rightPanel !== null && typeof rightPanel === 'object' && 'value' in rightPanel) {
          rightPanel.value = { mode: 'details', data: { job, tech: tech || null } }
        }
      } else if (rightPanel !== null && typeof rightPanel === 'object' && 'value' in rightPanel) {
        rightPanel.value = null
      }
    }
  }

  function isJobMultiSelected (jobId, isAssist = false) {
    return multiSelect.value.some(s => s.job.id === jobId && s.isAssist === isAssist)
  }

  // ── Batch ops (grouped undo) ──────────────────────────────────────────────────
  function batchUnassign (pushUndo) {
    if (!multiSelect.value.length) return
    // Snapshot all jobs before unassign — single undo entry
    const assignments = multiSelect.value.filter(s => !s.isAssist).map(s => ({
      jobId: s.job.id, techId: s.job.assignedTech, routeOrder: s.job.routeOrder,
      scheduledDate: s.job.scheduledDate, assistants: [...(s.job.assistants || [])]
    }))
    const prevQueues = {}
    store.technicians.forEach(t => { prevQueues[t.id] = [...t.queue] })

    multiSelect.value.forEach(s => {
      if (s.isAssist && s.assistTechId) store.removeAssistant(s.job.id, s.assistTechId)
      else store.fullUnassign(s.job.id)
    })

    if (pushUndo && assignments.length) {
      pushUndo({ type: 'batchAssign', assignments, prevQueues })
    }
    multiSelect.value = []; selectedJob.value = null
    invalidateRoutes()
  }

  function batchMoveTo (techId, dayStr, pushUndo) {
    if (!multiSelect.value.length) return
    const day = dayStr || localDateStr(periodStart.value)
    const jobs = multiSelect.value.filter(s => !s.isAssist)
    // Snapshot for grouped undo
    const assignments = jobs.map(s => ({
      jobId: s.job.id, techId: s.job.assignedTech, routeOrder: s.job.routeOrder,
      scheduledDate: s.job.scheduledDate, assistants: [...(s.job.assistants || [])]
    }))
    const prevQueues = {}
    store.technicians.forEach(t => { prevQueues[t.id] = [...t.queue] })

    jobs.forEach(s => smartAssign(s.job, techId, day))

    if (pushUndo && assignments.length) {
      pushUndo({ type: 'batchAssign', assignments, prevQueues })
    }
    multiSelect.value = []; selectedJob.value = null
    invalidateRoutes()
  }

  // ── Lasso ─────────────────────────────────────────────────────────────────────
  const lasso = ref(null)
  const boardScroll = ref(null)

  const lassoStyle = computed(() => {
    if (!lasso.value) return {}
    const l = lasso.value
    return {
      left: Math.min(l.x1, l.x2) + 'px', top: Math.min(l.y1, l.y2) + 'px',
      width: Math.abs(l.x2 - l.x1) + 'px', height: Math.abs(l.y2 - l.y1) + 'px',
    }
  })

  function startLasso (e) {
    if (e.target.closest('.sb-block, .sb-chip, .sb-res-cell, .sb-travel-trail, button, input, select, a')) return
    if (e.button !== 0) return
    e.preventDefault()
    if (!e.ctrlKey && !e.metaKey) {
      if (selectedJob.value || multiSelect.value.length) {
        selectedJob.value = null; multiSelect.value = []
      }
    }
    const rect = boardScroll.value.getBoundingClientRect()
    const x = e.clientX - rect.left + boardScroll.value.scrollLeft
    const y = e.clientY - rect.top + boardScroll.value.scrollTop
    lasso.value = { x1: x, y1: y, x2: x, y2: y }
  }

  function moveLasso (e) {
    if (!lasso.value) return
    e.preventDefault()
    const rect = boardScroll.value.getBoundingClientRect()
    lasso.value.x2 = e.clientX - rect.left + boardScroll.value.scrollLeft
    lasso.value.y2 = e.clientY - rect.top + boardScroll.value.scrollTop
  }

  function endLasso () {
    if (!lasso.value) return
    const l = lasso.value
    const w = Math.abs(l.x2 - l.x1), h = Math.abs(l.y2 - l.y1)
    if (w > 10 && h > 10) {
      const boardRect = boardScroll.value.getBoundingClientRect()
      const lassoLeft = Math.min(l.x1, l.x2) - boardScroll.value.scrollLeft + boardRect.left
      const lassoTop = Math.min(l.y1, l.y2) - boardScroll.value.scrollTop + boardRect.top
      const lassoRight = lassoLeft + w, lassoBottom = lassoTop + h
      const blocks = boardScroll.value.querySelectorAll('.sb-block[data-job-id], .sb-chip')
      const selected = []
      blocks.forEach(el => {
        const r = el.getBoundingClientRect()
        if (r.right > lassoLeft && r.left < lassoRight && r.bottom > lassoTop && r.top < lassoBottom) {
          const jobId = el.dataset?.jobId
          if (jobId) {
            const job = store.jobs.find(j => j.id === jobId)
            if (job) selected.push({ job, techId: job.assignedTech, isAssist: false, assistTechId: null })
          }
        }
      })
      if (selected.length) {
        multiSelect.value = selected
        if (selected.length === 1) selectedJob.value = selected[0]
      }
    }
    lasso.value = null
  }

  // ── Hover linking helpers ─────────────────────────────────────────────────────
  function techHasLinkedJob (tech) {
    const hId = hoveredJobId.value, sId = selectedJob.value?.job?.id
    if (hId && (tech.assistJobs || []).some(j => j.id === hId)) return true
    if (hId && tech.queue.some(j => j.id === hId)) return true
    if (sId && !selectedJob.value?.isAssist && (tech.assistJobs || []).some(j => j.id === sId)) return true
    if (sId && selectedJob.value?.isAssist && tech.queue.some(j => j.id === sId)) return true
    return false
  }

  function techIsHovered (tech) {
    const hId = hoveredJobId.value
    if (!hId) return false
    const job = tech.queue.find(j => j.id === hId)
    return job && job.assistants?.length > 0
  }

  return {
    hoveredJobId, selectedJob, multiSelect,
    selectJob, isJobMultiSelected, batchUnassign, batchMoveTo,
    lasso, boardScroll, lassoStyle, startLasso, moveLasso, endLasso,
    techHasLinkedJob, techIsHovered,
  }
}
