<script setup>
/**
 * IdentityManager — gestion des IDENTITÉS UNIFIÉES (admins).
 *
 * Une personne = 1 identité { label (nom complet), primary_email (login SSO),
 * alias_emails[] (autres courriels utilisables), tech_id (lien Dispatch Technician) }.
 * Réconcilie le user système ↔ le tech, empêche les doublons d'assignation, et fait
 * afficher le nom complet partout (le hub résout tout alias/tech → label).
 * Écritures réservées admin (gaté côté hub) ; ré-échoue proprement sinon.
 */
import { ref, computed, onMounted } from 'vue'
import { Notify, Dialog } from 'quasar'
import { getIdentityMap, upsertIdentity, setAlias, mergeIdentity, deleteIdentity } from 'src/api/identity'
import { listTechnicians } from 'src/api/roster'
import { useIdentity } from 'src/composables/useIdentity'

const list = ref([])
const techs = ref([]) // [{ id, name }]
const loading = ref(false)
const search = ref('')
const editing = ref(null) // identité en cours d'édition (copie)
const aliasInput = ref('')
const identStore = useIdentity()

const techOptions = computed(() => techs.value.map(t => ({ label: t.name + ' (' + t.id + ')', value: t.id })))
const filtered = computed(() => {
  const q = search.value.trim().toLowerCase()
  if (!q) return list.value
  return list.value.filter(i => (i.label + ' ' + i.primary_email + ' ' + (i.alias_emails || []).join(' ')).toLowerCase().includes(q))
})

async function load () {
  loading.value = true
  try {
    const [m, t] = await Promise.all([getIdentityMap(), listTechnicians().catch(() => ({ technicians: [] }))])
    list.value = (m.list || []).sort((a, b) => String(a.label).localeCompare(b.label))
    techs.value = (t.technicians || []).map(x => ({ id: x.id, name: x.name }))
  } catch (e) { Notify.create({ type: 'negative', message: 'Chargement impossible : ' + (e.message || e) }) } finally { loading.value = false }
}
onMounted(load)

function newIdentity () { editing.value = { key: '', label: '', primary_email: '', alias_emails: [], tech_id: '', employee: '', active: true, kind: 'employee', _new: true } }
function edit (i) { editing.value = JSON.parse(JSON.stringify(i)) }
function cancel () { editing.value = null; aliasInput.value = '' }
function techNameOf (id) { const t = techs.value.find(x => x.id === id); return t ? t.name : id }

function addAlias () {
  const e = aliasInput.value.trim().toLowerCase(); if (!e) return
  if (!/.+@.+\..+/.test(e)) { Notify.create({ type: 'warning', message: 'Courriel invalide' }); return }
  if (!editing.value.alias_emails.includes(e) && e !== editing.value.primary_email) editing.value.alias_emails.push(e)
  aliasInput.value = ''
}
function removeAlias (e) { editing.value.alias_emails = editing.value.alias_emails.filter(x => x !== e) }

async function saveEdit () {
  const it = editing.value
  if (!it.label.trim() || !it.primary_email.trim()) { Notify.create({ type: 'warning', message: 'Nom complet + courriel principal requis' }); return }
  try {
    await upsertIdentity({ key: it.key || it.primary_email, label: it.label.trim(), primary_email: it.primary_email.trim().toLowerCase(), alias_emails: it.alias_emails, tech_id: it.tech_id, employee: it.employee, active: it.active !== false, kind: it.kind || 'employee' })
    Notify.create({ type: 'positive', message: 'Identité enregistrée' })
    cancel(); await load(); identStore.reload()
  } catch (e) { Notify.create({ type: 'negative', message: (e.message || e) }) }
}
// Bloquer / réactiver SANS supprimer : départ = masqué des sélecteurs/roster, identité gardée pour l'historique.
async function toggleActive (i) {
  try {
    await upsertIdentity({ ...i, active: i.active === false })
    await load(); identStore.reload()
  } catch (e) { Notify.create({ type: 'negative', message: e.message || e }) }
}
async function remove (i) {
  Dialog.create({ title: 'Supprimer l\'identité', message: 'Retirer « ' + i.label + ' » ? (n\'affecte pas les comptes, seulement la carte d\'identité unifiée)', cancel: true }).onOk(async () => {
    try { await deleteIdentity(i.key); await load(); identStore.reload() } catch (e) { Notify.create({ type: 'negative', message: e.message || e }) }
  })
}
// Fusion : réconcilier deux entrées de la même personne (ex. user système + tech en double).
const mergeInto = ref(''); const mergeFrom = ref('')
async function doMerge () {
  if (!mergeInto.value || !mergeFrom.value || mergeInto.value === mergeFrom.value) { Notify.create({ type: 'warning', message: 'Choisis 2 identités distinctes' }); return }
  try {
    await mergeIdentity(mergeInto.value, mergeFrom.value)
    Notify.create({ type: 'positive', message: 'Identités fusionnées' })
    mergeInto.value = ''; mergeFrom.value = ''; await load(); identStore.reload()
  } catch (e) { Notify.create({ type: 'negative', message: e.message || e }) }
}
const idOptions = computed(() => list.value.map(i => ({ label: i.label + ' · ' + i.primary_email, value: i.key })))
</script>

<template>
  <div class="q-pa-sm">
    <div class="row items-center q-gutter-sm q-mb-sm">
      <div class="text-caption text-grey-7 col">Une personne = un nom complet + le courriel de login SSO + ses <b>alias courriel</b> + son lien <b>technicien</b>. Empêche les doublons d'assignation et affiche le nom complet partout.</div>
      <q-btn dense unelevated no-caps color="primary" icon="person_add" label="Nouvelle identité" @click="newIdentity" />
    </div>
    <q-input dense outlined v-model="search" placeholder="Chercher un nom / courriel…" clearable class="q-mb-sm"><template #prepend><q-icon name="search" /></template></q-input>

    <div v-if="loading" class="text-center q-pa-md"><q-spinner size="24px" color="primary" /></div>
    <q-list v-else bordered separator class="rounded-borders">
      <q-item v-for="i in filtered" :key="i.key" :class="{ 'idm-departed': i.active === false }">
        <q-item-section>
          <q-item-label class="text-weight-medium">
            {{ i.label }}
            <q-chip v-if="i.active === false" dense size="sm" color="grey-4" text-color="grey-8" icon="logout">parti(e)</q-chip>
            <q-chip v-if="i.kind === 'subcontractor'" dense size="sm" color="deep-purple-1" text-color="deep-purple-9" icon="handshake">sous-traitant</q-chip>
            <q-chip v-if="i.tech_id" dense size="sm" color="indigo-1" text-color="indigo-9" icon="engineering" class="q-ml-xs">{{ techNameOf(i.tech_id) }}</q-chip>
          </q-item-label>
          <q-item-label caption>
            <q-icon name="key" size="12px" /> {{ i.primary_email }}
            <span v-for="a in i.alias_emails" :key="a" class="q-ml-xs"><q-chip dense size="sm" color="grey-3" text-color="grey-8" icon="alternate_email">{{ a }}</q-chip></span>
          </q-item-label>
        </q-item-section>
        <q-item-section side class="row no-wrap">
          <q-btn flat dense round size="sm" :icon="i.active === false ? 'person_add' : 'block'" :color="i.active === false ? 'positive' : 'orange-7'" @click="toggleActive(i)"><q-tooltip>{{ i.active === false ? 'Réactiver' : 'Marquer parti(e) — bloque l\'assignation, garde l\'historique' }}</q-tooltip></q-btn>
          <q-btn flat dense round size="sm" icon="edit" color="primary" @click="edit(i)"><q-tooltip>Modifier</q-tooltip></q-btn>
          <q-btn flat dense round size="sm" icon="delete" color="grey-6" @click="remove(i)"><q-tooltip>Supprimer</q-tooltip></q-btn>
        </q-item-section>
      </q-item>
      <q-item v-if="!filtered.length"><q-item-section class="text-grey-6 text-caption">Aucune identité{{ search ? ' pour « ' + search + ' »' : '' }}.</q-item-section></q-item>
    </q-list>

    <!-- Fusion (réconcilier user système ↔ tech en double) -->
    <div class="q-mt-md q-pa-sm rounded-borders" style="border:1px dashed #cbd5e1">
      <div class="text-caption text-weight-medium text-grey-7 q-mb-xs"><q-icon name="merge" size="15px" /> Fusionner deux identités (même personne en double)</div>
      <div class="row items-center q-gutter-sm">
        <q-select class="col" dense outlined emit-value map-options v-model="mergeInto" :options="idOptions" label="Garder (cible)" />
        <q-icon name="arrow_back" color="grey-6" />
        <q-select class="col" dense outlined emit-value map-options v-model="mergeFrom" :options="idOptions" label="Fusionner (disparaît)" />
        <q-btn dense unelevated no-caps color="deep-orange-6" icon="merge" label="Fusionner" :disable="!mergeInto || !mergeFrom" @click="doMerge" />
      </div>
    </div>

    <!-- Éditeur -->
    <q-dialog :model-value="!!editing" @update:model-value="v => { if (!v) cancel() }">
      <q-card style="min-width:420px;max-width:96vw" v-if="editing">
        <q-card-section class="row items-center q-pb-none">
          <q-icon name="badge" color="primary" size="22px" class="q-mr-sm" />
          <div class="text-subtitle1 text-weight-bold">{{ editing._new ? 'Nouvelle identité' : 'Modifier l\'identité' }}</div>
          <q-space /><q-btn flat round dense icon="close" @click="cancel" />
        </q-card-section>
        <q-card-section class="q-gutter-sm">
          <q-input dense outlined v-model="editing.label" label="Nom complet (affiché partout)" placeholder="Louis-Paul Bourdon" autofocus />
          <q-input dense outlined v-model="editing.primary_email" label="Courriel principal (login SSO)" placeholder="louispaul@targointernet.com" :hint="editing._new ? '' : 'Modifier avec précaution — c\'est la clé'" />
          <div>
            <div class="text-caption text-grey-7 q-mb-xs">Alias courriel (tous connectent au même user)</div>
            <div class="row items-center q-gutter-xs q-mb-xs">
              <q-chip v-for="a in editing.alias_emails" :key="a" dense removable color="grey-3" text-color="grey-9" @remove="removeAlias(a)">{{ a }}</q-chip>
            </div>
            <div class="row items-center q-gutter-xs">
              <q-input class="col" dense outlined v-model="aliasInput" placeholder="autre@courriel.com" @keyup.enter="addAlias" />
              <q-btn dense flat round icon="add" color="primary" @click="addAlias" />
            </div>
          </div>
          <q-select dense outlined clearable emit-value map-options v-model="editing.tech_id" :options="techOptions" label="Lié au technicien (Dispatch)" use-input @filter="(v,u)=>u()" />
          <div class="row items-center q-gutter-md">
            <q-toggle v-model="editing.active" dense size="sm" color="positive" :label="editing.active ? 'Actif' : 'Parti(e) — bloqué'" />
            <q-option-group v-model="editing.kind" type="radio" inline dense size="sm" :options="[{label:'Employé',value:'employee'},{label:'Sous-traitant',value:'subcontractor'}]" />
          </div>
        </q-card-section>
        <q-card-actions align="right" class="q-px-md q-pb-md">
          <q-btn flat no-caps label="Annuler" color="grey-7" @click="cancel" />
          <q-btn unelevated no-caps color="primary" icon="save" label="Enregistrer" @click="saveEdit" />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </div>
</template>

<style scoped>
.idm-departed { opacity: .55; }
</style>
