<template>
  <!-- Filtre dynamique RÉUTILISABLE : recherche + groupes de chips (tag/compétence/statut…) + presets sauvegardés (par utilisateur).
       Contrôleur d'ÉTAT : possède { search, chips } et émet ; le parent applique (filtre client OU requête serveur). -->
  <div class="dynamic-filter" :class="{ dense }">
    <div class="df-row">
      <q-input dense outlined :model-value="state.search" clearable :placeholder="searchPlaceholder" class="df-search"
               @update:model-value="v => setSearch(v || '')">
        <template #prepend><q-icon name="search" size="18px" /></template>
      </q-input>
      <q-space />
      <span v-if="filteredCount != null" class="df-count">{{ filteredCount }}<span v-if="totalCount != null" class="text-grey-5"> / {{ totalCount }}</span></span>
      <q-btn v-if="hasActiveFilter" flat dense no-caps size="sm" icon="filter_alt_off" label="Effacer" color="grey-7" @click="clearAll" />
      <q-btn v-if="enablePresets" dense outline no-caps size="sm" icon="bookmark" :label="activePreset || 'Presets'" color="primary">
        <q-menu anchor="bottom right" self="top right">
          <q-list dense style="min-width:230px">
            <q-item-label header class="q-py-xs">Filtres enregistrés</q-item-label>
            <q-item v-for="p in presets" :key="p.name" clickable @click="applyPreset(p)">
              <q-item-section avatar><q-icon :name="p.name === activePreset ? 'bookmark' : 'bookmark_border'" size="18px" :color="p.name === activePreset ? 'primary' : 'grey-6'" /></q-item-section>
              <q-item-section>{{ p.name }}</q-item-section>
              <q-item-section side><q-btn flat dense round size="xs" icon="delete" color="grey-6" @click.stop="deletePreset(p)"><q-tooltip>Supprimer</q-tooltip></q-btn></q-item-section>
            </q-item>
            <q-item v-if="!presets.length"><q-item-section class="text-grey-6">Aucun filtre enregistré</q-item-section></q-item>
            <q-separator />
            <q-item clickable v-close-popup :disable="!hasActiveFilter" @click="saveCurrent">
              <q-item-section avatar><q-icon name="bookmark_add" color="primary" /></q-item-section>
              <q-item-section>Enregistrer le filtre actuel…</q-item-section>
            </q-item>
          </q-list>
        </q-menu>
      </q-btn>
    </div>
    <div v-for="g in chipGroups" :key="g.key" class="df-chips">
      <span v-if="g.label" class="df-chips-lbl"><q-icon v-if="g.icon" :name="g.icon" size="14px" :color="g.color || 'grey-6'" class="q-mr-xs" />{{ g.label }}</span>
      <button v-for="o in g.options" :key="String(o.value)" type="button" class="df-chip" :class="{ on: isOn(g, o.value) }"
              :style="isOn(g, o.value) && (o.color || g.color) ? { background: o.color || g.color, borderColor: o.color || g.color, color: '#fff' } : {}"
              @click="toggleChip(g, o.value)">{{ o.label }}</button>
    </div>
  </div>
</template>

<script setup>
import { reactive, computed, watch, ref } from 'vue'
import { useQuasar } from 'quasar'
import { useUserPrefs } from 'src/composables/useUserPrefs'

const props = defineProps({
  modelValue: { type: Object, default: () => ({ search: '', chips: {} }) },
  searchPlaceholder: { type: String, default: 'Rechercher…' },
  // [{ key, label, icon?, color?, options:[{value,label,color?}], multiple?:bool }]
  chipGroups: { type: Array, default: () => [] },
  presetKey: { type: String, default: '' }, // clé useUserPrefs (ex. 'filter.clients') ; requis pour les presets
  enablePresets: { type: Boolean, default: true },
  filteredCount: { type: Number, default: null },
  totalCount: { type: Number, default: null },
  dense: { type: Boolean, default: false },
})
const emit = defineEmits(['update:modelValue', 'change', 'clear'])
const $q = useQuasar()

const state = reactive({ search: props.modelValue.search || '', chips: { ...(props.modelValue.chips || {}) } })
watch(() => props.modelValue, (v) => { if (v) { state.search = v.search || ''; state.chips = { ...(v.chips || {}) } } })

function emitAll () { const snapshot = { search: state.search, chips: { ...state.chips } }; emit('update:modelValue', snapshot); emit('change', snapshot); activePreset.value = matchPresetName() }
function setSearch (v) { state.search = v; emitAll() }
function isOn (g, val) { const c = state.chips[g.key]; return g.multiple ? Array.isArray(c) && c.includes(val) : c === val }
function toggleChip (g, val) {
  if (g.multiple) { const arr = Array.isArray(state.chips[g.key]) ? [...state.chips[g.key]] : []; const i = arr.indexOf(val); if (i >= 0) arr.splice(i, 1); else arr.push(val); if (arr.length) state.chips[g.key] = arr; else delete state.chips[g.key] } else { if (state.chips[g.key] === val) delete state.chips[g.key]; else state.chips[g.key] = val }
  emitAll()
}
const hasActiveFilter = computed(() => !!state.search || Object.keys(state.chips).length > 0)
function clearAll () { state.search = ''; state.chips = {}; emitAll(); emit('clear') }

// ── Presets (par utilisateur, via useUserPrefs) ──
const { prefs, save } = useUserPrefs(props.presetKey || 'filter.default', { presets: [] })
const presets = computed(() => (prefs.value.presets || []))
const activePreset = ref('')
function serial (s) { return JSON.stringify({ search: s.search || '', chips: s.chips || {} }) }
function matchPresetName () { const cur = serial(state); const hit = presets.value.find(p => serial(p.state) === cur); return hit ? hit.name : '' }
function applyPreset (p) { state.search = p.state.search || ''; state.chips = { ...(p.state.chips || {}) }; emitAll() }
function deletePreset (p) { save({ presets: presets.value.filter(x => x.name !== p.name) }); if (activePreset.value === p.name) activePreset.value = '' }
function saveCurrent () {
  $q.dialog({ title: 'Enregistrer le filtre', message: 'Nom du filtre :', prompt: { model: '', type: 'text' }, cancel: true, ok: { label: 'Enregistrer', noCaps: true } })
    .onOk(name => { name = String(name || '').trim(); if (!name) return; const others = presets.value.filter(p => p.name !== name); save({ presets: [...others, { name, state: { search: state.search, chips: { ...state.chips } } }] }); activePreset.value = name })
}
</script>

<style scoped>
.dynamic-filter { display: flex; flex-direction: column; gap: 6px; }
.df-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.df-search { flex: 1 1 220px; min-width: 0; max-width: 340px; }
.df-count { font-size: 12px; color: var(--ops-text-secondary, #64748b); font-weight: 600; white-space: nowrap; }
.df-chips { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; }
.df-chips-lbl { display: inline-flex; align-items: center; font-size: 11.5px; font-weight: 600; color: var(--ops-text-secondary, #64748b); margin-right: 2px; }
.df-chip { display: inline-flex; align-items: center; padding: 3px 11px; border: 1px solid var(--ops-border, #cbd5e1); border-radius: 13px; background: #fff; font-size: 12px; font-weight: 600; color: #475569; cursor: pointer; user-select: none; transition: border-color .12s, background .12s; }
.df-chip:hover { border-color: #6366f1; }
.df-chip.on { background: #6366f1; border-color: #6366f1; color: #fff; }
.dense .df-chip { padding: 2px 9px; font-size: 11.5px; }
</style>
