/**
 * useResources — « rail » de ressources UNIFIÉE (techs + sous-groupes + recherche
 * + filtres + tri + masqués + scoring), partagée par TOUTES les vues.
 * -----------------------------------------------------------------------------
 * CONVERGENCE : aujourd'hui la liste de techs / sous-groupes / filtres est
 * RECRÉÉE dans chaque page (Dispatch: useResourceFilter ; Planification:
 * visibleTechs+groupFilter+search+hiddenTechs+priorityScores). On la définit ICI
 * UNE fois ; chaque vue la consomme. Agnostique de la source : on lui passe un
 * getter/ref du tableau de techs (modèle « union »).
 *
 * Modèle Tech union (champs lus ici, tous optionnels sauf id) :
 *   { id, name, fullName?, group?, status?, resourceType?, tags?[] }
 *
 * IDENTITÉ : `techKey(t)` normalise sur UNE clé (id) — corrige l'ambiguïté
 * docname Dispatch Technician vs technician_id repérée à la cartographie.
 */
import { ref, computed, watch, unref } from 'vue'

const lsGet = (k, d) => { try { const v = localStorage.getItem(k); return v == null ? d : JSON.parse(v) } catch { return d } }
const lsSet = (k, v) => { try { localStorage.setItem(k, JSON.stringify(v)) } catch { /* quota */ } }

export const techKey = (t) => (t && (t.id ?? t.technician_id ?? t.name)) || ''
const nameOf = (t) => t.fullName || t.full_name || t.name || ''
const lastName = (t) => nameOf(t).split(' ').pop().toLowerCase()

/**
 * @param techsSource  ref|getter renvoyant le tableau de techs
 * @param opts.lsPrefix      préfixe localStorage (persistance par contexte), défaut 'wf-'
 * @param opts.defaultType   '' | 'human' | 'material' — filtre type de ressource initial
 * @param opts.showHidden    ref<boolean> — si true, on affiche les masqués (grisés) au lieu de les cacher
 * @param opts.score         (t)=>number — score optionnel (Planification : compétence+vitesse+coût) → tri décroissant
 * @param opts.loadH         (t)=>number — charge horaire (pour le tri 'load')
 */
export function useResources (techsSource, opts = {}) {
  const P = opts.lsPrefix || 'wf-'
  const techs = () => (unref(typeof techsSource === 'function' ? techsSource() : techsSource)) || []

  const search = ref('')
  const groupFilter = ref(lsGet(P + 'group', '') || '')
  const resourceType = ref(opts.defaultType ?? '')      // '' | 'human' | 'material'
  const hidden = ref(lsGet(P + 'hidden', []) || [])      // ids masqués
  const sort = ref(lsGet(P + 'sort', 'default') || 'default') // 'default'|'alpha'|'load'
  const showHidden = opts.showHidden || ref(false)

  watch(groupFilter, v => lsSet(P + 'group', v))
  watch(hidden, v => lsSet(P + 'hidden', v), { deep: true })
  watch(sort, v => lsSet(P + 'sort', v))

  // Sous-groupes (tech_group) présents, triés.
  const groups = computed(() => { const s = new Set(); for (const t of techs()) if (t.group) s.add(t.group); return [...s].sort() })

  const isHidden = (t) => hidden.value.includes(techKey(t))

  // Liste filtrée + triée (humains avant matériel ; puis score|alpha|load|défaut).
  const filtered = computed(() => {
    let list = techs()
    if (resourceType.value) list = list.filter(t => (t.resourceType || 'human') === resourceType.value)
    if (search.value) { const q = search.value.toLowerCase(); list = list.filter(t => nameOf(t).toLowerCase().includes(q)) }
    if (groupFilter.value) list = list.filter(t => t.group === groupFilter.value)
    if (!showHidden.value) list = list.filter(t => !isHidden(t))
    list = [...list].sort((a, b) => {
      const at = a.resourceType === 'material' ? 1 : 0, bt = b.resourceType === 'material' ? 1 : 0
      if (at !== bt) return at - bt
      if (opts.score) return (opts.score(b) || 0) - (opts.score(a) || 0)
      if (sort.value === 'alpha') return lastName(a).localeCompare(lastName(b))
      if (sort.value === 'load' && opts.loadH) return (opts.loadH(a) || 0) - (opts.loadH(b) || 0)
      return 0
    })
    return list
  })

  // Regroupé par sous-groupe (groupes nommés d'abord, « Non assigné » à la fin).
  const grouped = computed(() => {
    const m = new Map()
    for (const t of filtered.value) { const g = t.group || ''; if (!m.has(g)) m.set(g, []); m.get(g).push(t) }
    return [...m.entries()]
      .sort((a, b) => (!a[0] && b[0]) ? 1 : (a[0] && !b[0]) ? -1 : a[0].localeCompare(b[0]))
      .map(([name, list]) => ({ name, label: name || 'Non assigné', techs: list }))
  })

  const toggleHidden = (id) => { hidden.value = hidden.value.includes(id) ? hidden.value.filter(x => x !== id) : [...hidden.value, id] }
  const hiddenCount = computed(() => hidden.value.length)
  const clearFilters = () => { search.value = ''; groupFilter.value = ''; resourceType.value = opts.defaultType ?? '' }

  return {
    // état
    search, groupFilter, resourceType, hidden, sort, showHidden,
    // dérivés
    groups, filtered, grouped, hiddenCount,
    // actions
    toggleHidden, clearFilters, isHidden, techKey,
  }
}
