import { ref } from 'vue'
import { Notify } from 'quasar'
import { HUB_URL } from 'src/config/hub'
import { useAuthStore } from 'src/stores/auth'

// ── Centre de notifications (cloche) — PAR UTILISATEUR, feeds activables ──────
// Écoute SSE 'outbox' (évaluations) + 'conversations' (messages ENTRANTS client).
// Chaque feed (SMS / clavardage / appels / Messenger / courriel / évaluations) est
// activable/désactivable PAR utilisateur — prefs stockées côté hub (clé = courriel
// agent), donc elles suivent l'usager. État SINGLETON (module-level) partagé par la
// cloche montée dans MainLayout. /sse est PUBLIC (EventSource sans en-tête).

export const FEEDS = [
  { key: 'sms', label: 'Textos (SMS)', icon: 'sms', color: 'teal-7' },
  { key: 'webchat', label: 'Clavardage web', icon: 'chat', color: 'primary' },
  { key: '3cx', label: 'Appels (3CX)', icon: 'call', color: 'blue-7' },
  { key: 'call', label: 'Appels entrants (ligne principale)', icon: 'phone_in_talk', color: 'green-7' },
  { key: 'facebook', label: 'Messenger', icon: 'facebook', color: 'blue-9' },
  { key: 'email', label: 'Courriels', icon: 'mail', color: 'deep-purple-6' },
  { key: 'ratings', label: 'Évaluations', icon: 'star', color: 'amber-7' },
]
// Défaut : canaux TEMPS RÉEL + appels entrants + évaluations ON ; courriel OFF (asynchrone, fort volume → l'Inbox suffit).
const DEFAULTS = { sms: true, webchat: true, '3cx': true, call: true, facebook: true, email: false, ratings: true }

const notifications = ref([])   // { id, type, feed, title, caption, ts, customer, conv, icon, stars, low }
const unread = ref(0)
const prefs = ref({ ...DEFAULTS })
const myQueues = ref({ queues: [], mine: [], notify: {}, labels: {} })   // abonnement PAR AGENT aux files + notif par file
let es = null
let _seq = 0

function headers () {
  try { const email = useAuthStore().user; if (email && email !== 'authenticated') return { 'Content-Type': 'application/json', 'X-Authentik-Email': email } } catch {}
  return { 'Content-Type': 'application/json' }
}
function add (n) {
  notifications.value.unshift({ id: 'n' + (++_seq), ts: new Date().toISOString(), ...n })
  if (notifications.value.length > 60) notifications.value.length = 60
  unread.value++
}
function toast (opts) { try { Notify.create(opts) } catch (e) { /* */ } }
function nav (path) { window.location.hash = '#' + path }
function go (n) {
  markAllRead()
  if (n && (n.type === 'rating' || n.type === 'comment')) return nav('/evaluations')
  if (n && n.type === 'call' && n.customer) return nav('/clients/' + encodeURIComponent(n.customer))
  if (n && n.conv) return nav('/communications/c/' + encodeURIComponent(n.conv))
  nav('/communications')
}

async function loadPrefs () {
  try { const r = await fetch(`${HUB_URL}/conversations/notif-prefs`, { headers: headers() }); if (r.ok) { const d = await r.json(); prefs.value = { ...DEFAULTS, ...(d.prefs || {}) } } } catch { /* défauts conservés */ }
}
async function savePrefs () {
  try { await fetch(`${HUB_URL}/conversations/notif-prefs`, { method: 'PUT', headers: headers(), body: JSON.stringify({ prefs: prefs.value }) }) } catch { /* */ }
}
// Files (self-service) : mes abonnements + notif par file.
async function loadMyQueues () {
  try { const r = await fetch(`${HUB_URL}/conversations/my-queues`, { headers: headers() }); if (r.ok) myQueues.value = await r.json() } catch { /* */ }
}
async function setQueueSub (queue, subscribe) {
  try { await fetch(`${HUB_URL}/conversations/my-queues`, { method: 'POST', headers: headers(), body: JSON.stringify({ queue, subscribe }) }); await loadMyQueues() } catch { /* */ }
}
async function setQueueNotify (queue, notify) {
  try { await fetch(`${HUB_URL}/conversations/my-queues`, { method: 'POST', headers: headers(), body: JSON.stringify({ queue, notify }) }); await loadMyQueues() } catch { /* */ }
}

function onRating (d) {
  if (!prefs.value.ratings) return
  const name = d.name || d.customer || 'Client'
  add({ type: 'rating', feed: 'ratings', stars: d.stars, low: !!d.low, customer: d.customer || '', conv: d.conv || '', title: `${'★'.repeat(d.stars || 0)} ${name}`, caption: d.low ? 'Évaluation à traiter' : 'Nouvel avis' })
  toast({ message: `${d.stars}★ — ${name}`, caption: d.low ? 'Évaluation basse à traiter' : 'Nouvel avis', color: d.low ? 'orange-9' : 'green-7', textColor: 'white', icon: 'star', position: 'top-right', timeout: 6000, actions: [{ label: 'Voir', color: 'white', handler: () => go({ type: 'rating' }) }] })
}
function onComment (d) {
  if (!prefs.value.ratings) return
  const name = d.name || d.customer || 'Client'
  add({ type: 'comment', feed: 'ratings', stars: d.stars, low: d.stars != null && d.stars < 5, customer: d.customer || '', conv: d.conv || '', title: `💬 ${name}`, caption: (d.comment || '').slice(0, 90) })
  toast({ message: `Commentaire — ${name}`, caption: (d.comment || '').slice(0, 90), color: 'green-8', textColor: 'white', icon: 'rate_review', position: 'top-right', timeout: 7000, actions: [{ label: 'Voir', color: 'white', handler: () => go({ type: 'comment' }) }] })
}
const CH_META = { sms: { icon: 'sms', label: 'SMS', color: 'teal-8' }, webchat: { icon: 'chat', label: 'Clavardage', color: 'green-8' }, '3cx': { icon: 'call', label: 'Appel', color: 'blue-8' }, facebook: { icon: 'facebook', label: 'Messenger', color: 'blue-9' } }
function onConvMessage (d) {
  if (!d || !d.message || d.message.from !== 'customer') return   // UNIQUEMENT les messages entrants client (pas nos réponses)
  const feed = d.channel                                          // sms / webchat / 3cx / facebook (email géré par conv-email)
  if (!CH_META[feed] || !prefs.value[feed]) return
  const name = d.customerName || d.customer || 'Client'
  const meta = CH_META[feed]
  const body = (d.message.text || '').trim() || (d.message.media ? '[image]' : '…')
  add({ type: 'conv', feed, conv: d.token || '', customer: d.customer || '', title: name, caption: `${meta.label} · ${body.slice(0, 80)}`, icon: meta.icon })
  toast({ message: `${meta.label} — ${name}`, caption: body.slice(0, 80), color: meta.color, textColor: 'white', icon: meta.icon, position: 'top-right', timeout: 6000, actions: [{ label: 'Voir', color: 'white', handler: () => go({ type: 'conv', conv: d.token }) }] })
}
function onConvEmail (d) {
  if (!prefs.value.email || !d) return
  const who = d.email || 'Courriel'
  add({ type: 'conv', feed: 'email', conv: d.token || '', title: who, caption: 'Nouveau courriel entrant', icon: 'mail' })
  toast({ message: `Courriel — ${who}`, caption: 'Nouveau courriel entrant', color: 'deep-purple-7', textColor: 'white', icon: 'mail', position: 'top-right', timeout: 6000, actions: [{ label: 'Voir', color: 'white', handler: () => go({ type: 'conv', conv: d.token }) }] })
}
// Appel entrant (ligne principale Twilio) → screen-pop coin haut-droit : nom du compte lié + numéro + « Ouvrir la fiche ».
function onCallIncoming (d) {
  if (!prefs.value.call || !d) return
  // Par FILE : si l'appel cible une file, ne notifier que les agents abonnés à cette file avec notif ON.
  if (d.queue) { const mq = myQueues.value; if (!(mq.mine || []).includes(d.queue) || (mq.notify || {})[d.queue] === false) return }
  const known = !!d.customerId
  const name = d.customerName || (known ? 'Client' : 'Appelant inconnu')
  const sub = (d.from || '') + (d.territory ? ' · ' + d.territory : '')
  add({ type: 'call', feed: 'call', customer: d.customerId || '', title: '📞 ' + name, caption: 'Appel entrant · ' + sub, icon: 'phone_in_talk' })
  toast({ message: 'Appel entrant — ' + name, caption: sub + (known ? '' : ' · numéro non reconnu'), color: known ? 'green-8' : 'blue-grey-8', textColor: 'white', icon: 'phone_in_talk', position: 'top-right', timeout: 15000, actions: known ? [{ label: 'Ouvrir la fiche', color: 'white', handler: () => nav('/clients/' + encodeURIComponent(d.customerId)) }] : [] })
}

function initNotifications () {
  loadPrefs(); loadMyQueues()
  if (es) return
  connectNotifSSE()
}
function connectNotifSSE () {
  try {
    es = new EventSource(`${HUB_URL}/sse?topics=outbox,conversations`)
    es.addEventListener('rating', e => { try { onRating(JSON.parse(e.data)) } catch {} })
    es.addEventListener('rating-comment', e => { try { onComment(JSON.parse(e.data)) } catch {} })
    es.addEventListener('conv-message', e => { try { onConvMessage(JSON.parse(e.data)) } catch {} })
    es.addEventListener('conv-email', e => { try { onConvEmail(JSON.parse(e.data)) } catch {} })
    es.addEventListener('call-incoming', e => { try { onCallIncoming(JSON.parse(e.data)) } catch {} })
    // Survit aux redéploiements du hub : si le flux meurt DÉFINITIVEMENT (502 pendant le restart → EventSource CLOSED,
    // plus de reconnexion native), on relance après 3 s (sinon la cloche reste muette jusqu'au prochain rechargement).
    es.onerror = () => { if (es && es.readyState === EventSource.CLOSED) { es = null; setTimeout(connectNotifSSE, 3000) } }
  } catch (e) { /* SSE indisponible */ }
}
function markAllRead () { unread.value = 0 }

export function useNotifications () { return { notifications, unread, prefs, FEEDS, myQueues, loadMyQueues, setQueueSub, setQueueNotify, initNotifications, markAllRead, savePrefs, loadPrefs, go } }
