<template>
  <q-page class="hist-page">
    <div class="hist-head">
      <div class="text-h6">Historique &amp; classements</div>
      <div class="hist-sub">Retracer la journée de chaque technicien (tous statuts) et reconnaître l'effort de l'équipe.</div>
    </div>

    <q-tabs v-model="tab" no-caps dense align="left" class="hist-tabs" active-color="primary" indicator-color="primary">
      <q-tab name="tournees" icon="route" label="Tournées par technicien" />
      <q-tab name="techs" icon="emoji_events" label="Classement techniciens" />
      <q-tab name="inbox" icon="forum" label="Classement Inbox" />
    </q-tabs>
    <q-separator />

    <q-tab-panels v-model="tab" animated class="hist-panels">
      <!-- ─────────── Tournées par technicien (tous statuts) ─────────── -->
      <q-tab-panel name="tournees" class="q-pa-none">
        <div class="hist-toolbar">
          <q-btn flat dense round icon="chevron_left" @click="shiftDay(-1)" />
          <q-btn flat dense no-caps class="hist-datebtn" :label="prettyDate(histDate)" icon-right="event">
            <q-popup-proxy cover transition-show="scale" transition-hide="scale">
              <q-date v-model="histDate" mask="YYYY-MM-DD" today-btn minimal @update:model-value="() => { loadHistory() }" />
            </q-popup-proxy>
          </q-btn>
          <q-btn flat dense round icon="chevron_right" :disable="histDate >= today" @click="shiftDay(1)" />
          <q-btn flat dense no-caps label="Aujourd'hui" class="q-ml-sm" :disable="histDate === today" @click="histDate = today; loadHistory()" />
          <q-space />
          <div v-if="!histLoading && hist" class="hist-summary">
            <b>{{ hist.count }}</b> tâche{{ hist.count > 1 ? 's' : '' }} · <b>{{ (hist.techs || []).length }}</b> technicien{{ (hist.techs || []).length > 1 ? 's' : '' }}
            <span v-for="s in histStatusSummary" :key="s.key" class="hist-sumchip" :style="{ color: s.color }">● {{ s.n }} {{ s.label }}</span>
          </div>
        </div>

        <div v-if="histLoading" class="hist-loading"><q-spinner-dots size="32px" color="primary" /></div>
        <div v-else-if="!hist || !(hist.techs || []).length" class="hist-empty">
          <q-icon name="event_busy" size="32px" class="q-mb-sm" />
          <div>Aucune tâche planifiée le {{ prettyDate(histDate) }}.</div>
        </div>
        <div v-else class="hist-techs">
          <q-card v-for="t in hist.techs" :key="t.tech" flat bordered class="hist-techcard">
            <div class="hist-techhead">
              <q-avatar size="28px" color="blue-grey-1" text-color="blue-grey-8" class="q-mr-sm">{{ initials(t.tech_name) }}</q-avatar>
              <div class="hist-techname">{{ t.tech_name }}</div>
              <q-space />
              <span class="hist-techcount">{{ t.jobs.length }} tâche{{ t.jobs.length > 1 ? 's' : '' }}</span>
            </div>
            <q-separator />
            <div v-for="j in t.jobs" :key="j.name" class="hist-job" :class="{ 'hist-job--cancel': j.status === 'Cancelled' }">
              <q-chip dense square :style="{ background: statusMeta(j.status).bg, color: statusMeta(j.status).fg }" class="hist-statuschip">{{ statusMeta(j.status).label }}</q-chip>
              <span class="hist-jobtime">{{ jobTime(j) }}</span>
              <span class="hist-jobsubj">{{ j.subject || j.job_type || j.name }}</span>
              <q-space />
              <span v-if="j.duration_h" class="hist-jobdur">{{ j.duration_h }} h</span>
            </div>
          </q-card>
        </div>
      </q-tab-panel>

      <!-- ─────────── Classement techniciens (jobs complétés) ─────────── -->
      <q-tab-panel name="techs" class="q-pa-none">
        <div class="hist-toolbar">
          <q-btn-toggle v-model="rangeDays" no-caps dense unelevated toggle-color="primary" color="grey-2" text-color="grey-8"
            :options="[{ label: '7 jours', value: 7 }, { label: '30 jours', value: 30 }, { label: '90 jours', value: 90 }]"
            @update:model-value="loadTechBoard" />
          <q-space />
          <div class="hist-summary">Jobs <b>complétés</b> · {{ prettyDate(rangeFrom) }} → {{ prettyDate(today) }}</div>
        </div>
        <div v-if="techLoading" class="hist-loading"><q-spinner-dots size="32px" color="primary" /></div>
        <div v-else-if="!techBoard.length" class="hist-empty"><q-icon name="emoji_events" size="32px" class="q-mb-sm" /><div>Aucun job complété sur la période.</div></div>
        <div v-else class="hist-board">
          <div v-for="(b, i) in techBoard" :key="b.tech" class="hist-rank">
            <div class="hist-medal" :class="'hist-medal--' + (i < 3 ? i + 1 : 0)">{{ i < 3 ? ['🥇', '🥈', '🥉'][i] : (i + 1) }}</div>
            <q-avatar size="30px" color="blue-grey-1" text-color="blue-grey-8" class="q-mr-sm">{{ initials(b.tech_name) }}</q-avatar>
            <div class="hist-rankname">{{ b.tech_name }}</div>
            <div class="hist-bar"><div class="hist-bar-fill" :style="{ width: barPct(b.completed, techMax) + '%' }"></div></div>
            <div class="hist-rankval">{{ b.completed }}</div>
          </div>
        </div>
      </q-tab-panel>

      <!-- ─────────── Classement Inbox (réponses par agent) ─────────── -->
      <q-tab-panel name="inbox" class="q-pa-none">
        <div class="hist-toolbar">
          <q-btn-toggle v-model="rangeDays" no-caps dense unelevated toggle-color="primary" color="grey-2" text-color="grey-8"
            :options="[{ label: '7 jours', value: 7 }, { label: '30 jours', value: 30 }, { label: '90 jours', value: 90 }]"
            @update:model-value="loadInboxBoard" />
          <q-space />
          <div class="hist-summary">Réponses &amp; conversations prises · {{ prettyDate(rangeFrom) }} → {{ prettyDate(today) }}</div>
        </div>
        <div v-if="inboxLoading" class="hist-loading"><q-spinner-dots size="32px" color="primary" /></div>
        <template v-else>
          <div v-if="!inboxBoard.length" class="hist-empty">
            <q-icon name="forum" size="32px" class="q-mb-sm" />
            <div>Les statistiques par agent s'accumulent à partir de maintenant.</div>
            <div class="hist-empty-sub">Chaque réponse envoyée est désormais attribuée à son auteur·rice.<br>{{ inboxUnattributed }} réponse{{ inboxUnattributed > 1 ? 's' : '' }} antérieure{{ inboxUnattributed > 1 ? 's' : '' }} (avant suivi) ne sont pas attribuées.</div>
          </div>
          <div v-else class="hist-board">
            <div v-for="(b, i) in inboxBoard" :key="b.agent" class="hist-rank">
              <div class="hist-medal" :class="'hist-medal--' + (i < 3 ? i + 1 : 0)">{{ i < 3 ? ['🥇', '🥈', '🥉'][i] : (i + 1) }}</div>
              <q-avatar size="30px" color="teal-1" text-color="teal-8" class="q-mr-sm">{{ initials(agentName(b.agent)) }}</q-avatar>
              <div class="hist-rankname">{{ agentName(b.agent) }}</div>
              <div class="hist-bar"><div class="hist-bar-fill hist-bar-fill--teal" :style="{ width: barPct(b.replies, inboxMax) + '%' }"></div></div>
              <div class="hist-rankval">{{ b.replies }}<span class="hist-rankval-sub">rép.</span></div>
              <div class="hist-rankval2" v-if="b.handled">{{ b.handled }}<span class="hist-rankval-sub">pris</span></div>
            </div>
            <div v-if="inboxUnattributed" class="hist-note">+ {{ inboxUnattributed }} réponse{{ inboxUnattributed > 1 ? 's' : '' }} antérieure{{ inboxUnattributed > 1 ? 's' : '' }} non attribuée{{ inboxUnattributed > 1 ? 's' : '' }} (avant le suivi par auteur).</div>
          </div>
        </template>
      </q-tab-panel>
    </q-tab-panels>
  </q-page>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { Notify } from 'quasar'
import { HUB_URL } from 'src/config/hub'

const tab = ref('tournees')

function localDateStr (d = new Date()) {
  // Date locale (QC = ET) en YYYY-MM-DD, sans décalage UTC
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}
const today = localDateStr()

async function hubGet (path) {
  const res = await fetch(HUB_URL + path, { headers: { 'Content-Type': 'application/json' } })
  if (!res.ok) throw new Error('HTTP ' + res.status)
  return res.json()
}

// ── Affichage commun ──
function initials (name) {
  const parts = String(name || '?').trim().split(/\s+/).filter(Boolean)
  return ((parts[0]?.[0] || '') + (parts.length > 1 ? parts[parts.length - 1][0] : '')).toUpperCase() || '?'
}
function prettyDate (iso) {
  if (!iso) return ''
  const [y, m, d] = iso.split('-').map(Number)
  return new Date(y, m - 1, d).toLocaleDateString('fr-CA', { weekday: 'short', day: 'numeric', month: 'short' })
}
function barPct (v, max) { return max > 0 ? Math.max(4, Math.round((v / max) * 100)) : 0 }

const STATUS_META = {
  Completed: { label: 'Complété', bg: '#dcfce7', fg: '#15803d' },
  assigned: { label: 'Assigné', bg: '#dbeafe', fg: '#1d4ed8' },
  in_progress: { label: 'En cours', bg: '#fef3c7', fg: '#b45309' },
  open: { label: 'Ouvert', bg: '#e2e8f0', fg: '#475569' },
  'On Hold': { label: 'En attente', bg: '#ffedd5', fg: '#c2410c' },
  Cancelled: { label: 'Annulé', bg: '#f1f5f9', fg: '#94a3b8' },
}
function statusMeta (s) { return STATUS_META[s] || { label: s || '—', bg: '#e2e8f0', fg: '#475569' } }
function jobTime (j) {
  const t = j.start_time ? String(j.start_time).slice(11, 16) : ''
  return t || '—'
}

// ── Tab 1 : tournées par technicien ──
const histDate = ref(today)
const hist = ref(null)
const histLoading = ref(false)
function shiftDay (delta) {
  const [y, m, d] = histDate.value.split('-').map(Number)
  const nd = new Date(y, m - 1, d + delta)
  const next = localDateStr(nd)
  if (next > today) return
  histDate.value = next
  loadHistory()
}
async function loadHistory () {
  histLoading.value = true
  try { hist.value = await hubGet(`/dispatch/history?date=${histDate.value}`) }
  catch (e) { hist.value = null; Notify.create({ type: 'negative', message: 'Chargement de l\'historique : ' + e.message }) }
  finally { histLoading.value = false }
}
const histStatusSummary = computed(() => {
  if (!hist.value) return []
  const counts = {}
  for (const t of (hist.value.techs || [])) for (const j of t.jobs) counts[j.status] = (counts[j.status] || 0) + 1
  return Object.keys(counts).sort((a, b) => counts[b] - counts[a]).map(k => ({ key: k, n: counts[k], label: statusMeta(k).label.toLowerCase(), color: statusMeta(k).fg }))
})

// ── Périodes (tabs 2 & 3) ──
const rangeDays = ref(30)
const rangeFrom = computed(() => {
  const d = new Date(); d.setDate(d.getDate() - (rangeDays.value - 1))
  return localDateStr(d)
})

// ── Tab 2 : classement techniciens ──
const techBoard = ref([])
const techLoading = ref(false)
const techMax = computed(() => techBoard.value.reduce((m, b) => Math.max(m, b.completed), 0))
async function loadTechBoard () {
  techLoading.value = true
  try { const r = await hubGet(`/dispatch/leaderboard?from=${rangeFrom.value}&to=${today}`); techBoard.value = r.board || [] }
  catch (e) { techBoard.value = []; Notify.create({ type: 'negative', message: 'Classement techniciens : ' + e.message }) }
  finally { techLoading.value = false }
}

// ── Tab 3 : classement Inbox ──
const inboxBoard = ref([])
const inboxUnattributed = ref(0)
const inboxLoading = ref(false)
const inboxMax = computed(() => inboxBoard.value.reduce((m, b) => Math.max(m, b.replies), 0))
function agentName (email) {
  if (!email) return '—'
  const local = String(email).split('@')[0]
  return local.split(/[.\-_]/).filter(Boolean).map(p => p[0].toUpperCase() + p.slice(1)).join(' ') || email
}
async function loadInboxBoard () {
  inboxLoading.value = true
  try {
    const r = await hubGet(`/conversations/leaderboard?from=${rangeFrom.value}&to=${today}`)
    inboxBoard.value = (r.board || []).filter(b => b.replies > 0 || b.handled > 0)
    inboxUnattributed.value = r.unattributed || 0
  } catch (e) { inboxBoard.value = []; Notify.create({ type: 'negative', message: 'Classement Inbox : ' + e.message }) }
  finally { inboxLoading.value = false }
}

onMounted(() => { loadHistory(); loadTechBoard(); loadInboxBoard() })
</script>

<style scoped>
.hist-page { padding: 16px 20px; background: var(--ops-bg, #f8fafc); min-height: 100%; }
.hist-head { margin-bottom: 10px; }
.hist-sub { color: var(--ops-text-muted, #64748b); font-size: 13px; margin-top: 2px; }
.hist-tabs { color: var(--ops-text, #1e293b); }
.hist-panels { background: transparent; }

.hist-toolbar { display: flex; align-items: center; gap: 2px; padding: 12px 2px; flex-wrap: wrap; }
.hist-datebtn { font-weight: 600; text-transform: capitalize; }
.hist-summary { font-size: 13px; color: var(--ops-text-muted, #64748b); }
.hist-summary b { color: var(--ops-text, #1e293b); }
.hist-sumchip { margin-left: 10px; font-size: 12px; white-space: nowrap; }

.hist-loading, .hist-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 48px 16px; color: var(--ops-text-muted, #94a3b8); text-align: center; }
.hist-empty-sub { font-size: 12px; margin-top: 6px; line-height: 1.5; }

/* Tournées */
.hist-techs { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 12px; }
.hist-techcard { border-radius: 10px; background: var(--ops-surface, #fff); overflow: hidden; }
.hist-techhead { display: flex; align-items: center; padding: 10px 12px; }
.hist-techname { font-weight: 600; color: var(--ops-text, #1e293b); }
.hist-techcount { font-size: 12px; color: var(--ops-text-muted, #64748b); }
.hist-job { display: flex; align-items: center; gap: 8px; padding: 7px 12px; border-top: 1px solid var(--ops-border, #f1f5f9); font-size: 13px; }
.hist-job:first-of-type { border-top: none; }
.hist-job--cancel { opacity: 0.55; }
.hist-job--cancel .hist-jobsubj { text-decoration: line-through; }
.hist-statuschip { font-size: 11px; font-weight: 600; height: 20px; }
.hist-jobtime { font-variant-numeric: tabular-nums; color: var(--ops-text-muted, #64748b); width: 42px; flex-shrink: 0; }
.hist-jobsubj { color: var(--ops-text, #1e293b); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hist-jobdur { font-size: 12px; color: var(--ops-text-muted, #94a3b8); flex-shrink: 0; }

/* Classements */
.hist-board { max-width: 760px; }
.hist-rank { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-bottom: 1px solid var(--ops-border, #eef2f6); }
.hist-medal { width: 30px; text-align: center; font-weight: 700; font-size: 16px; color: var(--ops-text-muted, #94a3b8); flex-shrink: 0; }
.hist-medal--1, .hist-medal--2, .hist-medal--3 { font-size: 18px; }
.hist-rankname { font-weight: 600; color: var(--ops-text, #1e293b); width: 200px; max-width: 32%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hist-bar { flex: 1; height: 10px; background: var(--ops-border, #eef2f6); border-radius: 6px; overflow: hidden; margin: 0 4px; }
.hist-bar-fill { height: 100%; background: #3b82f6; border-radius: 6px; transition: width .3s; }
.hist-bar-fill--teal { background: #14b8a6; }
.hist-rankval { font-weight: 700; color: var(--ops-text, #1e293b); min-width: 38px; text-align: right; font-variant-numeric: tabular-nums; }
.hist-rankval2 { min-width: 42px; text-align: right; color: var(--ops-text-muted, #64748b); font-variant-numeric: tabular-nums; }
.hist-rankval-sub { font-size: 10px; font-weight: 400; color: var(--ops-text-muted, #94a3b8); margin-left: 2px; }
.hist-note { font-size: 12px; color: var(--ops-text-muted, #94a3b8); padding: 10px; }
</style>
