<template>
  <!-- Champ d'assignation MULTIFONCTION (partagé jobDetail + IssueDetail). UN champ pour ajouter des participants
       + une échelle d'implication par personne + deux bascules « moi » (assister / suivre).
       – 1er ajouté = ASSIGNÉ / lead (chip À). Suivants = ASSISTANT par défaut.
       – Chaque participant (non-lead) a un menu d'implication : Suiveur ‹ Assistant ‹ Sur place (équipe).
         · Suiveur (#)   = reçoit les mises à jour, aucune place dans l'équipe.
         · Assistant (CC)= sur l'équipe, SANS bloc horaire.
         · Sur place     = assistant AVEC un bloc réservé dans son horaire (équipe) — si la surface le permet.
       – Deux bascules agissent sur MOI (l'utilisateur connecté) : m'ajouter comme assistant · suivre. -->
  <div class="asg-field">
    <div class="asg-chips row items-center q-gutter-xs">
      <HelpHint title="Assignation">
        Ajoutez des personnes à l'intervention. Le premier ajouté devient l'<b>assigné (À)</b> ; chacun a un niveau&nbsp;:
        <ul>
          <li><b>À</b> — technicien assigné (responsable).</li>
          <li><b>Assistant (CC)</b> — renfort sur l'équipe, <b>sans</b> bloc horaire réservé.</li>
          <li><b>Sur place</b> — assistant <b>avec</b> un bloc réservé dans son horaire.</li>
          <li><b>Suiveur (#)</b> — reçoit les mises à jour, sans place dans l'équipe.</li>
        </ul>
        Les deux bascules agissent sur vous : m'ajouter comme assistant · suivre.
      </HelpHint>
      <!-- À : lead / assigné -->
      <q-chip v-if="hasLead" dense removable @remove="$emit('unassign')" color="indigo-6" text-color="white" class="text-weight-bold asg-chip">
        <q-avatar color="indigo-9" text-color="white" size="20px">{{ ini(assignee.name || assignee.id) }}</q-avatar>
        À&nbsp;·&nbsp;{{ assignee.name || assignee.id }}
        <q-tooltip class="bg-grey-9" style="font-size:11px">Assigné / lead technique</q-tooltip>
      </q-chip>
      <q-chip v-else dense outline color="grey-7" text-color="grey-8" icon="person_off">Non assigné</q-chip>

      <!-- Participants (assistants + suiveurs) — chip par personne avec menu d'implication -->
      <q-chip v-for="p in participants" :key="p.id" dense removable
        @remove="removeParticipant(p)" :color="levelMeta(p.level).chipColor" :text-color="levelMeta(p.level).chipText" class="asg-chip asg-chip-part">
        <q-avatar :color="levelMeta(p.level).avaColor" text-color="white" size="20px">{{ ini(p.name) }}</q-avatar>
        {{ levelMeta(p.level).badge }}&nbsp;·&nbsp;{{ p.name }}
        <q-icon name="arrow_drop_down" size="16px" class="asg-caret" />
        <q-menu anchor="bottom left" self="top left" auto-close>
          <q-list dense style="min-width:210px">
            <q-item-label header class="text-caption q-py-xs">Niveau d'implication</q-item-label>
            <q-item clickable :active="p.level === 'follower'" active-class="asg-active" @click="setLevel(p, 'follower')">
              <q-item-section avatar style="min-width:28px"><q-icon name="visibility" size="18px" color="teal-6" /></q-item-section>
              <q-item-section><q-item-label>Suiveur</q-item-label><q-item-label caption>Reçoit les mises à jour</q-item-label></q-item-section>
            </q-item>
            <q-item clickable :active="p.level === 'assistant'" active-class="asg-active" @click="setLevel(p, 'assistant')">
              <q-item-section avatar style="min-width:28px"><q-icon name="group" size="18px" color="blue-grey-6" /></q-item-section>
              <q-item-section><q-item-label>Assistant</q-item-label><q-item-label caption>Sur l'équipe · sans bloc horaire</q-item-label></q-item-section>
            </q-item>
            <q-item v-if="canOnsite" clickable :active="p.level === 'onsite'" active-class="asg-active" @click="setLevel(p, 'onsite')">
              <q-item-section avatar style="min-width:28px"><q-icon name="construction" size="18px" color="deep-orange-6" /></q-item-section>
              <q-item-section><q-item-label>Sur place (équipe)</q-item-label><q-item-label caption>Réserve un bloc dans son horaire</q-item-label></q-item-section>
            </q-item>
            <q-separator />
            <q-item clickable @click="removeParticipant(p)">
              <q-item-section avatar style="min-width:28px"><q-icon name="close" size="18px" color="grey-6" /></q-item-section>
              <q-item-section><q-item-label>Retirer</q-item-label></q-item-section>
            </q-item>
          </q-list>
        </q-menu>
        <q-tooltip class="bg-grey-9" style="font-size:11px">{{ levelMeta(p.level).tip }} — cliquer pour changer</q-tooltip>
      </q-chip>
      <q-spinner v-if="assistLoading || followBusy" size="14px" color="blue-grey-6" />
    </div>

    <!-- Ajouter un participant : techs (avec compétences) en tête, puis tous les utilisateurs -->
    <TechSelect
      :model-value="null"
      :options="techOptions"
      :search-fn="assistSearch"
      no-option-label="Aucun résultat"
      :label="hasLead ? 'Ajouter un participant…' : 'Assigner (lead)…'"
      style="min-width:170px;flex:1" class="q-mt-xs"
      @update:model-value="onPick" />

    <!-- Bascules « moi » + slot droite (ex. contrôle de statut) -->
    <div class="asg-self row items-center q-gutter-md q-mt-xs">
      <q-toggle :model-value="assistSelfActive" :disable="!me" dense size="sm" color="blue-grey-6"
        @update:model-value="toggleAssistSelf">
        <span class="asg-self-lbl"><q-icon name="group_add" size="14px" /> M'ajouter comme assistant</span>
        <q-tooltip v-if="!me" class="bg-grey-9" style="font-size:11px">Session utilisateur requise</q-tooltip>
      </q-toggle>
      <q-toggle :model-value="followSelfActive" :disable="!me" dense size="sm" color="teal-6"
        @update:model-value="toggleFollowSelf">
        <span class="asg-self-lbl"><q-icon name="visibility" size="14px" /> Suivre</span>
      </q-toggle>
      <q-space />
      <slot name="right" />
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { useQuasar } from 'quasar'
import { HUB_URL } from 'src/config/hub'
import { useAuthStore } from 'src/stores/auth'
import { initials as ini, shortAgent } from 'src/composables/useFormatters'
import TechSelect from 'src/components/shared/TechSelect.vue'
import HelpHint from 'src/components/shared/HelpHint.vue'

const props = defineProps({
  doctype: { type: String, required: true }, // pour le suivi : 'Dispatch Job' | 'Issue' …
  docName: { type: String, default: '' },
  assignee: { type: Object, default: null }, // { id, name } — lead (chip « À »), propriété du parent
  assistants: { type: Array, default: () => [] }, // [{ id, name, onsite }] — assistants (onsite = bloc horaire)
  techOptions: { type: Array, default: () => [] }, // [{ label, value, capable }] — suggestions par défaut (techs + compétences)
  canOnsite: { type: Boolean, default: true }, // niveau « Sur place » (bloc horaire) disponible ? (jobDetail oui, ticket non)
  assistLoading: { type: Boolean, default: false },
})
const emit = defineEmits(['assign', 'unassign', 'set-assistant', 'remove-assistant', 'followers-changed'])
const $q = useQuasar()
const _authUser = useAuthStore().user
const me = (_authUser && _authUser !== 'authenticated') ? String(_authUser).toLowerCase() : ''
const meLabel = shortAgent(me) || me

const hasLead = computed(() => !!(props.assignee && (props.assignee.name || props.assignee.id)))

// ── Métadonnées d'affichage par niveau ──
function levelMeta (level) {
  if (level === 'follower') return { badge: '#', chipColor: 'teal-1', chipText: 'teal-9', avaColor: 'teal-6', tip: 'Suiveur (reçoit les mises à jour)' }
  if (level === 'onsite') return { badge: 'Sur place', chipColor: 'deep-orange-1', chipText: 'deep-orange-9', avaColor: 'deep-orange-6', tip: 'Sur place (équipe) — bloc réservé dans son horaire' }
  return { badge: 'CC', chipColor: 'blue-grey-1', chipText: 'blue-grey-9', avaColor: 'blue-grey-6', tip: 'Assistant — sur l\'équipe, sans bloc horaire' }
}

// ── Liste unifiée des participants (assistants + suiveurs), 1 personne = 1 niveau ──
// Clé unique par personne (id d'assistant = tech_id ; suiveur = courriel). L'assistant prime si doublon.
const participants = computed(() => {
  const out = []; const seen = new Set()
  for (const a of (props.assistants || [])) {
    const id = String(a.id || ''); if (!id) continue; const k = id.toLowerCase(); if (seen.has(k)) continue; seen.add(k)
    out.push({ id, name: a.name || id, level: a.onsite ? 'onsite' : 'assistant' })
  }
  for (const e of followers.value) {
    const id = String(e || ''); if (!id) continue; const k = id.toLowerCase(); if (seen.has(k)) continue; seen.add(k)
    out.push({ id, name: followerLabel(id), level: 'follower' })
  }
  return out
})

// ── Ajout via l'autosuggest : 1er = lead (assign) ; suivants = assistant par défaut ──
function onPick (value) {
  if (!value) return
  const opt = [...(props.techOptions || []), ...userOptCache].find(o => o.value === value)
  const label = opt ? (opt.label || String(value)) : String(value)
  if (!hasLead.value) emit('assign', value)
  else emit('set-assistant', { value, label, onsite: false })
}

// ── Changer le niveau d'un participant (transitions inter-magasins) ──
async function setLevel (p, level) {
  if (!p || level === p.level) return
  if (level === 'follower') {
    if (p.level !== 'follower') emit('remove-assistant', p.id) // sortir de l'équipe
    await addFollower(p.id, p.name) // suivi keyé par courriel si connu, sinon l'id (cf décision)
  } else {
    if (p.level === 'follower') await removeFollower(p.id) // sortir du suivi
    emit('set-assistant', { value: p.id, label: p.name, onsite: level === 'onsite' })
  }
}
function removeParticipant (p) {
  if (!p) return
  if (p.level === 'follower') removeFollower(p.id)
  else emit('remove-assistant', p.id)
}

// ── Bascules « moi » (utilisateur connecté) ──
const assistSelfActive = computed(() => !!me && (props.assistants || []).some(a => String(a.id).toLowerCase() === me))
const followSelfActive = computed(() => !!me && followers.value.map(e => String(e).toLowerCase()).includes(me))
function toggleAssistSelf (val) {
  if (!me) return
  if (val) emit('set-assistant', { value: me, label: meLabel, onsite: false })
  else emit('remove-assistant', me)
}
function toggleFollowSelf (val) {
  if (!me) return
  if (val) addFollower(me, meLabel); else removeFollower(me)
}

// ── Recherche du champ d'ajout : techs (avec compétences) puis tous les utilisateurs ──
let userOptCache = []
async function userSearch (val) {
  const q = String(val || '').trim()
  try {
    const r = await fetch(`${HUB_URL}/auth/users?search=${encodeURIComponent(q)}`)
    if (!r.ok) return []
    const d = await r.json()
    userOptCache = (d.users || d || []).filter(u => u && u.email).map(u => ({ label: u.name || u.email, value: u.email, sub: u.email }))
    return userOptCache
  } catch { return [] }
}
async function assistSearch (val) {
  const q = String(val || '').toLowerCase().trim()
  const techs = (props.techOptions || []).filter(o => !q || String(o.label || '').toLowerCase().includes(q) || String(o.value || '').toLowerCase().includes(q))
  if (!q) return techs // ouverture sans saisie : techs (avec compétences), rapide
  const users = await userSearch(val)
  const techVals = new Set(techs.map(t => t.value))
  return [...techs, ...users.filter(u => !techVals.has(u.value))] // techs en tête, puis les autres utilisateurs
}

// ── Suivi (# — abonnés). Géré ICI (identique partout) via /conversations/follow. ──
const followers = ref([]) // ids (courriels, ou tech_id en repli)
const followerNames = ref({}) // id → libellé connu
const followBusy = ref(false)
function followerLabel (id) { return followerNames.value[id] || shortAgent(id) || id }
const followHdr = () => (me ? { 'Content-Type': 'application/json', 'X-Authentik-Email': me } : { 'Content-Type': 'application/json' })

async function loadFollowers () {
  followers.value = []
  if (!props.docName || !props.doctype) return
  try {
    const r = await fetch(`${HUB_URL}/conversations/followers?doctype=${encodeURIComponent(props.doctype)}&name=${encodeURIComponent(props.docName)}`).then(x => x.json())
    followers.value = (r.followers || [])
  } catch { /* hub non déployé (aperçu) → dégrade proprement */ }
}
async function addFollower (id, label) {
  const e = String(id || '').toLowerCase()
  if (!e || !props.docName || followers.value.map(x => String(x).toLowerCase()).includes(e)) return
  followBusy.value = true
  try {
    const r = await fetch(`${HUB_URL}/conversations/follow`, { method: 'POST', headers: followHdr(), body: JSON.stringify({ doctype: props.doctype, name: props.docName, email: e, follow: true }) }).then(x => x.json())
    if (r.ok) {
      if (!followers.value.includes(e)) followers.value.push(e)
      if (label) followerNames.value[e] = String(label).split(' · ')[0].trim()
      emit('followers-changed', followers.value.slice())
      $q.notify({ type: 'positive', icon: 'visibility', message: followerLabel(e) + ' suit désormais cet élément', timeout: 2000 })
    } else $q.notify({ type: 'negative', message: r.error || 'Échec', timeout: 2500 })
  } catch (err) { $q.notify({ type: 'negative', message: err.message, timeout: 2500 }) } finally { followBusy.value = false }
}
async function removeFollower (id) {
  const e = String(id || '').toLowerCase()
  if (!e || !props.docName) return
  followBusy.value = true
  try {
    const r = await fetch(`${HUB_URL}/conversations/follow`, { method: 'POST', headers: followHdr(), body: JSON.stringify({ doctype: props.doctype, name: props.docName, email: e, follow: false }) }).then(x => x.json())
    if (r.ok) {
      followers.value = followers.value.filter(x => String(x).toLowerCase() !== e)
      emit('followers-changed', followers.value.slice())
    } else $q.notify({ type: 'negative', message: r.error || 'Échec', timeout: 2500 })
  } catch (err) { $q.notify({ type: 'negative', message: err.message, timeout: 2500 }) } finally { followBusy.value = false }
}

watch(() => [props.doctype, props.docName], loadFollowers)
onMounted(loadFollowers)
defineExpose({ reloadFollowers: loadFollowers })
</script>

<style scoped>
.asg-field { min-width: 0; }
.asg-chips { flex-wrap: wrap; }
.asg-chip :deep(.q-chip__content) { white-space: nowrap; }
.asg-chip-part { cursor: pointer; }
.asg-caret { margin-left: 2px; opacity: 0.7; }
.asg-self { flex-wrap: wrap; }
.asg-self-lbl { display: inline-flex; align-items: center; gap: 3px; font-size: 0.75rem; font-weight: 500; color: #475569; }
.asg-active { background: #eef2ff; }
</style>
