---
import BaseLayout from '@/layouts/BaseLayout.astro';
import '@/styles/global.css';
---

<BaseLayout title="Ops — L'Electron Rare" description="Centre opérationnel IA-native.">
  <main class="ops" id="ops-main">

    <div class="ops-header">
      <div class="ops-header-left">
        <img src="/assets/brand/logo-mark.jpg" alt="" width="32" height="32" class="ops-logo" />
        <div>
          <h1 class="ops-title">Ops</h1>
          <p class="ops-sub">L'Electron Rare · <span id="task-count">—</span></p>
        </div>
      </div>
      <div class="ops-header-right">
        <div class="status-bar" id="status-bar">
          <span class="status-dot" id="status-dot"></span>
          <span class="status-text" id="status-text">...</span>
        </div>
      </div>
    </div>

    <nav class="tabs" id="tabs">
      <button class="tab tab--active" data-tab="tasks">Tâches</button>
      <button class="tab" data-tab="dashboard">Dashboard</button>
      <button class="tab" data-tab="services">Services</button>
    </nav>

    <!-- VUE 1: TÂCHES -->
    <section class="panel panel--active" id="panel-tasks">
      <div class="tasks-toolbar">
        <button class="btn btn--primary btn--sm" id="add-task-btn">+ Nouvelle tâche</button>
        <div class="tasks-filters">
          <select id="filter-cat" class="filter-select"><option value="">Toutes catégories</option></select>
          <select id="filter-status" class="filter-select">
            <option value="">Tous statuts</option>
            <option value="À faire" selected>À faire</option>
            <option value="En cours">En cours</option>
            <option value="Terminé">Terminé</option>
          </select>
          <input type="text" id="filter-search" class="filter-input" placeholder="Rechercher..." />
        </div>
        <button class="btn btn--outline btn--sm" id="refresh-tasks">↻</button>
      </div>

      <div id="add-task-form" style="display:none" class="card-form">
        <input type="text" id="new-task-title" class="form-input" placeholder="Titre de la tâche..." />
        <div class="form-row">
          <select id="new-task-category" class="form-select">
            <option value="urgent">Urgent</option>
            <option value="prospection">Prospection</option>
            <option value="linkedin">LinkedIn</option>
            <option value="technique">Technique</option>
            <option value="lancement">Lancement</option>
            <option value="formation">Formation</option>
            <option value="gie">GIE</option>
            <option value="marketing">Marketing</option>
            <option value="business">Business</option>
            <option value="crm">CRM</option>
          </select>
          <select id="new-task-priority" class="form-select">
            <option value="P0">P0</option>
            <option value="P1">P1</option>
            <option value="P2" selected>P2</option>
            <option value="P3">P3</option>
          </select>
          <input type="date" id="new-task-deadline" class="form-input" style="width:auto" />
          <select id="new-task-agent" class="form-select">
            <option value="">Sans IA</option>
            <option value="writer">writer</option>
            <option value="analyst">analyst</option>
            <option value="brainstorm">brainstorm</option>
            <option value="planner">planner</option>
            <option value="prospection">prospection</option>
            <option value="formation-designer">formation-designer</option>
          </select>
        </div>
        <textarea id="new-task-desc" class="form-textarea" rows="2" placeholder="Description (optionnel)..."></textarea>
        <div class="form-row">
          <button class="btn btn--primary" id="save-task-btn">Enregistrer</button>
          <button class="btn btn--outline" id="cancel-task-btn">Annuler</button>
        </div>
      </div>

      <div id="tasks-container"><div class="loading">Chargement...</div></div>
    </section>

    <!-- VUE 2: DASHBOARD -->
    <section class="panel" id="panel-dashboard">
      <div class="kpi-grid" id="kpi-grid">
        <div class="kpi-card"><div class="kpi-num" id="kpi-leads">—</div><div class="kpi-label">Leads</div></div>
        <div class="kpi-card"><div class="kpi-num" id="kpi-hot">—</div><div class="kpi-label">Chauds</div></div>
        <div class="kpi-card"><div class="kpi-num" id="kpi-score">—</div><div class="kpi-label">Score IA</div></div>
        <div class="kpi-card"><div class="kpi-num" id="kpi-tasks">—</div><div class="kpi-label">Tâches</div></div>
        <div class="kpi-card"><div class="kpi-num" id="kpi-done">—</div><div class="kpi-label">Terminées</div></div>
        <div class="kpi-card"><div class="kpi-num" id="kpi-agents">—</div><div class="kpi-label">Agents IA</div></div>
      </div>

      <h3 class="sub-title">Agents mascarade <button class="btn btn--outline btn--sm" id="add-agent-btn" style="margin-left:8px">+ Créer</button></h3>
      <div id="add-agent-form" style="display:none" class="card-form">
        <input type="text" id="new-agent-name" class="form-input" placeholder="Nom (ex: email-drafter)" />
        <input type="text" id="new-agent-desc" class="form-input" placeholder="Description" />
        <textarea id="new-agent-prompt" class="form-textarea" rows="3" placeholder="System prompt..."></textarea>
        <div class="form-row">
          <select id="new-agent-strategy" class="form-select"><option value="best">best</option><option value="cheapest">cheapest</option><option value="fastest">fastest</option></select>
          <select id="new-agent-provider" class="form-select"><option value="">Auto</option><option value="ollama">ollama</option><option value="claude">claude</option><option value="mistral">mistral</option></select>
          <button class="btn btn--primary" id="save-agent-btn">Créer</button>
          <button class="btn btn--outline" id="cancel-agent-btn">Annuler</button>
        </div>
      </div>
      <div class="agents-grid" id="agents-grid"></div>

      <h3 class="sub-title">Copilote rapide</h3>
      <div class="copilot-bar">
        <select id="chat-agent" class="form-select"></select>
        <input type="text" id="chat-input" class="form-input" placeholder="Demande à l'IA..." style="flex:1" />
        <button class="btn btn--primary" id="chat-send">→</button>
      </div>
      <div id="chat-output" class="chat-output"></div>

      <div class="quick-links">
        <a href="https://tower.saillant.cc/app/crm" target="_blank" class="btn btn--outline btn--sm">CRM</a>
        <a href="https://kpi.saillant.cc/dashboard/2" target="_blank" class="btn btn--outline btn--sm">Metabase</a>
        <a href="https://mail.saillant.cc" target="_blank" class="btn btn--outline btn--sm">Listmonk</a>
        <a href="https://rdv.saillant.cc" target="_blank" class="btn btn--outline btn--sm">Cal.com</a>
        <a href="https://n8n.saillant.cc" target="_blank" class="btn btn--outline btn--sm">n8n</a>
        <a href="https://tower.saillant.cc/lms/courses" target="_blank" class="btn btn--outline btn--sm">LMS</a>
      </div>
    </section>

    <!-- VUE 3: SERVICES -->
    <section class="panel" id="panel-services">
      <h3 class="sub-title">Status <span class="status-refresh" id="refresh-services">↻</span></h3>
      <div class="monitor-grid" id="monitor-grid"></div>

      <h3 class="sub-title">Business</h3>
      <div class="services-grid">
        <a href="https://tower.saillant.cc/app/crm" class="svc-card" target="_blank"><img src="/assets/icons/crm.png" width="36" height="36" /><span>CRM</span></a>
        <a href="https://tower.saillant.cc/lms/courses" class="svc-card" target="_blank"><img src="/assets/icons/lms.png" width="36" height="36" /><span>LMS</span></a>
        <a href="https://mail.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/newsletter.png" width="36" height="36" /><span>Listmonk</span></a>
        <a href="https://n8n.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/automation.png" width="36" height="36" /><span>n8n</span></a>
        <a href="https://kpi.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/analytics.png" width="36" height="36" /><span>Metabase</span></a>
        <a href="https://rdv.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/calendar.png" width="36" height="36" /><span>Cal.com</span></a>
      </div>

      <h3 class="sub-title">IA & Collaboratif</h3>
      <div class="services-grid">
        <a href="https://mascarade.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/ai-brain.png" width="36" height="36" /><span>mascarade</span></a>
        <a href="https://dify.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/workflow-ai.png" width="36" height="36" /><span>Dify</span></a>
        <a href="https://langfuse.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/analytics.png" width="36" height="36" /><span>Langfuse</span></a>
        <a href="https://memos.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/notes.png" width="36" height="36" /><span>Memos</span></a>
        <a href="https://docs.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/documents.png" width="36" height="36" /><span>Paperless</span></a>
        <a href="https://karakeep.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/bookmarks.png" width="36" height="36" /><span>Karakeep</span></a>
        <a href="https://draw.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/eye.png" width="36" height="36" /><span>Excalidraw</span></a>
        <a href="https://paste.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/logs.png" width="36" height="36" /><span>PrivateBin</span></a>
      </div>

      <h3 class="sub-title">Monitoring</h3>
      <div class="services-grid">
        <a href="https://grafana.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/chart.png" width="36" height="36" /><span>Grafana</span></a>
        <a href="https://logs.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/logs.png" width="36" height="36" /><span>Dozzle</span></a>
        <a href="https://ntfy.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/bell.png" width="36" height="36" /><span>ntfy</span></a>
        <a href="https://checks.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/health.png" width="36" height="36" /><span>Healthchecks</span></a>
        <a href="https://watch.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/eye.png" width="36" height="36" /><span>Changedetection</span></a>
        <a href="https://feeds.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/rss.png" width="36" height="36" /><span>Miniflux</span></a>
        <a href="https://auth.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/auth.png" width="36" height="36" /><span>Authentik</span></a>
        <a href="https://browser.saillant.cc" class="svc-card" target="_blank"><img src="/assets/icons/eye.png" width="36" height="36" /><span>browser-use</span></a>
      </div>
    </section>

  </main>
</BaseLayout>

<script>
  // API Contracts:
  // GET  /health         → { ok, agents, providers }
  // GET  /api/ai         → { agents: [...] }
  // POST /api/ai         → create agent
  // POST /api/ai/:name/run → { messages: [{role, content}] }
  // GET  /api/ops/tasks  → { data: [...] }
  // POST /api/ops/tasks  → create task
  // PUT  /api/ops/tasks/:id → update task
  // POST /api/ops/execute/:id → AI execute

  const API = 'https://api.lelectronrare.fr';
  const OPS = API + '/api/ops';
  const AI = API + '/api/ai';

  // Auth token for API calls — populate via data-token attribute on #ops-main
  // or a <meta name="api-token"> tag. Empty string keeps unauthenticated flow working.
  const AUTH_TOKEN = document.getElementById('ops-main')?.dataset?.token
    || document.querySelector('meta[name="api-token"]')?.content
    || '';

  const catLabels = {urgent:'Urgent',prospection:'Prospection',linkedin:'LinkedIn',technique:'Technique',lancement:'Lancement',formation:'Formation',gie:'GIE',marketing:'Marketing',business:'Business',crm:'CRM'};
  const catColors = {urgent:'red',prospection:'amber',linkedin:'blue',technique:'cyan',lancement:'green',formation:'amber',gie:'amber',crm:'cyan',marketing:'blue',business:'green'};
  const prioColors = {P0:'red',P1:'amber',P2:'cyan',P3:'green'};

  // --- Tabs ---
  document.querySelectorAll('.tab').forEach(tab => {
    tab.addEventListener('click', () => {
      document.querySelectorAll('.tab').forEach(t => t.classList.remove('tab--active'));
      document.querySelectorAll('.panel').forEach(p => p.classList.remove('panel--active'));
      tab.classList.add('tab--active');
      document.getElementById('panel-' + tab.dataset.tab)?.classList.add('panel--active');
    });
  });

  // --- TASKS ---
  let allTasks = [];

  async function loadTasks() {
    try {
      const res = await fetch(OPS + '/tasks', {headers:{'Content-Type':'application/json'}});
      allTasks = (await res.json()).data || [];
      renderTasks();
    } catch(e) { document.getElementById('tasks-container').innerHTML = '<p class="err">Erreur: '+e.message+'</p>'; }
  }

  function renderTasks() {
    const cat = document.getElementById('filter-cat')?.value || '';
    const status = document.getElementById('filter-status')?.value || '';
    const search = (document.getElementById('filter-search')?.value || '').toLowerCase();

    let filtered = allTasks;
    if (cat) filtered = filtered.filter(t => t.category === cat);
    if (status) filtered = filtered.filter(t => t.status === status);
    if (search) filtered = filtered.filter(t => (t.task_title||'').toLowerCase().includes(search) || (t.description||'').toLowerCase().includes(search));

    const groups = {};
    const done = [];
    filtered.forEach(t => {
      if (t.status === 'Terminé') { done.push(t); return; }
      const c = t.category || 'technique';
      if (!groups[c]) groups[c] = [];
      groups[c].push(t);
    });

    let html = '';
    for (const [c, tasks] of Object.entries(groups)) {
      html += `<div class="task-group"><div class="group-label group-label--${catColors[c]||'cyan'}">${catLabels[c]||c} (${tasks.length})</div><div class="task-list">${tasks.map(t => taskCard(t)).join('')}</div></div>`;
    }
    if (done.length) {
      html += `<details class="task-group"><summary class="group-label group-done">Terminé (${done.length})</summary><div class="task-list">${done.map(t => taskCard(t,true)).join('')}</div></details>`;
    }

    const total = allTasks.length;
    const doneCount = allTasks.filter(t => t.status === 'Terminé').length;
    document.getElementById('task-count').textContent = `${doneCount}/${total} tâches`;
    document.getElementById('tasks-container').innerHTML = html || '<p class="hint">Aucune tâche</p>';
    bindTasks();

    // Populate category filter
    const catSelect = document.getElementById('filter-cat');
    if (catSelect && catSelect.options.length <= 1) {
      const cats = [...new Set(allTasks.map(t => t.category).filter(Boolean))].sort();
      cats.forEach(c => { const o = document.createElement('option'); o.value = c; o.textContent = catLabels[c]||c; catSelect.appendChild(o); });
    }
  }

  function taskCard(t, isDone) {
    const overdue = t.deadline && new Date(t.deadline) < new Date() && !isDone;
    const isLinkedin = t.category === 'linkedin';
    const lines = isLinkedin && t.description ? t.description.split('\\n').map(l => l ? '<p class="li-line">'+l+'</p>' : '<div class="li-spacer"></div>').join('') : '';

    return `<div class="task ${overdue?'task--overdue':''} ${isDone?'task--done':''}" data-id="${t.name}">
      <div class="task-header">
        <span class="task-status">${t.status==='Terminé'?'●':t.status==='En cours'?'◐':'○'}</span>
        <span class="task-title">${t.task_title||''}</span>
        ${t.priority?`<span class="badge badge--${prioColors[t.priority]||'cyan'}">${t.priority}</span>`:''}
        ${t.deadline?`<span class="badge badge--${overdue?'red':'blue'}">${t.deadline}</span>`:''}
        ${t.ai_agent?`<span class="badge badge--cyan">IA</span>`:''}
      </div>
      <div class="task-body">
        ${t.description?`<div class="task-desc">${isLinkedin?'<div class="li-preview"><div class="li-header"><div class="li-avatar">CS</div><div><b>Clément Saillant</b><br><small>Ingénieur électronique · L\'Electron Rare</small></div></div>'+lines+'</div>':'<p>'+t.description+'</p>'}</div>`:''}
        ${t.ai_result?`<details class="ai-saved"><summary>Résultat IA</summary><pre>${(t.ai_result||'').substring(0,500)}</pre></details>`:''}
        <div class="task-actions">
          <select class="action-status" data-id="${t.name}">${['À faire','En cours','Terminé','Reporté'].map(s=>`<option${s===t.status?' selected':''}>${s}</option>`).join('')}</select>
          <input type="text" class="action-note" data-id="${t.name}" placeholder="Note..." value="${(t.notes||'').replace(/"/g,'&quot;')}" />
          <button class="btn btn--primary btn--sm save-btn" data-id="${t.name}">Save</button>
          ${t.ai_agent?`<button class="btn btn--outline btn--sm exec-btn" data-id="${t.name}">IA: ${t.ai_agent}</button>`:''}
          ${isLinkedin?`<button class="btn btn--outline btn--sm copy-btn" data-text="${encodeURIComponent(t.description||'')}">Copier</button><a href="https://linkedin.com/feed/" target="_blank" class="btn btn--outline btn--sm">LinkedIn</a>`:''}
        </div>
        <div class="ai-out" id="ai-${t.name}"></div>
      </div>
    </div>`;
  }

  function bindTasks() {
    document.querySelectorAll('#tasks-container .task-header').forEach(h => h.addEventListener('click', () => h.closest('.task')?.classList.toggle('task--open')));
    document.querySelectorAll('.save-btn').forEach(b => b.addEventListener('click', async e => {
      e.stopPropagation(); const id=b.dataset.id, task=b.closest('.task');
      b.textContent='...';
      await fetch(OPS+'/tasks/'+id,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify({status:task.querySelector('.action-status')?.value,notes:task.querySelector('.action-note')?.value})});
      b.textContent='✓'; setTimeout(loadTasks,500);
    }));
    document.querySelectorAll('.exec-btn').forEach(b => b.addEventListener('click', async e => {
      e.stopPropagation(); const id=b.dataset.id, out=document.getElementById('ai-'+id);
      if(out){out.innerHTML='<div class="loading">IA...</div>';out.style.display='block';}
      b.textContent='...';
      try{const r=await fetch(OPS+'/execute/'+id,{method:'POST',headers:{'Content-Type':'application/json'}});const d=await r.json();
      if(out)out.innerHTML='<pre>'+(d.result||d.error||'').substring(0,500).replace(/</g,'&lt;')+'</pre>';
      }catch(err){if(out)out.innerHTML='<p class="err">'+err.message+'</p>';}
      b.textContent='IA'; loadTasks();
    }));
    document.querySelectorAll('.copy-btn').forEach(b => b.addEventListener('click', e => {
      e.stopPropagation(); navigator.clipboard.writeText(decodeURIComponent(b.dataset.text)); b.textContent='✓'; setTimeout(()=>b.textContent='Copier',2000);
    }));
  }

  // Filters
  ['filter-cat','filter-status'].forEach(id => document.getElementById(id)?.addEventListener('change', renderTasks));
  document.getElementById('filter-search')?.addEventListener('input', renderTasks);
  document.getElementById('refresh-tasks')?.addEventListener('click', loadTasks);

  // Add task
  document.getElementById('add-task-btn')?.addEventListener('click', () => { const f=document.getElementById('add-task-form'); f.style.display=f.style.display==='none'?'block':'none'; });
  document.getElementById('cancel-task-btn')?.addEventListener('click', () => document.getElementById('add-task-form').style.display='none');
  document.getElementById('save-task-btn')?.addEventListener('click', async () => {
    const title=document.getElementById('new-task-title')?.value?.trim(); if(!title)return;
    await fetch(OPS+'/tasks',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({
      task_title:title, category:document.getElementById('new-task-category')?.value||'technique',
      priority:document.getElementById('new-task-priority')?.value||'P2',
      deadline:document.getElementById('new-task-deadline')?.value||null,
      ai_agent:document.getElementById('new-task-agent')?.value||null,
      description:document.getElementById('new-task-desc')?.value||'',
      status:'À faire', assigned_to:'clement@lelectronrare.fr'
    })});
    document.getElementById('new-task-title').value=''; document.getElementById('add-task-form').style.display='none'; loadTasks();
  });

  loadTasks();

  // --- DASHBOARD ---
  let allAgents = [];

  async function loadDashboard() {
    // KPIs
    try {
      document.getElementById('kpi-tasks').textContent = allTasks.length;
      document.getElementById('kpi-done').textContent = allTasks.filter(t=>t.status==='Terminé').length;
    } catch {}
    // Agents
    try {
      const agentHeaders = {'Content-Type':'application/json'};
      if (AUTH_TOKEN) agentHeaders['Authorization'] = 'Bearer ' + AUTH_TOKEN;
      const r = await fetch(AI, {headers: agentHeaders});
      const d = await r.json();
      allAgents = d.agents || (Array.isArray(d) ? d : []);
      // kpi-agents is set from /health below; fallback to allAgents.length
      if (!document.getElementById('kpi-agents').dataset.fromHealth) {
        document.getElementById('kpi-agents').textContent = allAgents.length;
      }
      const grid = document.getElementById('agents-grid');
      grid.innerHTML = allAgents.map(a => `<div class="agent-card" data-name="${a.name}"><b>${a.name}</b><span class="badge badge--${a.strategy==='best'?'cyan':a.strategy==='cheapest'?'green':'blue'}">${a.strategy}</span><p>${(a.description||'').substring(0,60)}</p></div>`).join('');
      grid.querySelectorAll('.agent-card').forEach(c => c.addEventListener('click', () => {
        const sel = document.getElementById('chat-agent'); if(sel) sel.value = c.dataset.name;
        document.getElementById('chat-input')?.focus();
      }));
      // Populate chat selector
      const sel = document.getElementById('chat-agent');
      if (sel) sel.innerHTML = allAgents.map(a=>`<option value="${a.name}">${a.name}</option>`).join('');
    } catch {}
    // API health — parse { ok, agents, providers }
    try {
      const h = await fetch(API+'/health'); const hd = await h.json();
      document.getElementById('status-dot').className = 'status-dot status-dot--ok';
      const parts = ['API OK'];
      if (typeof hd.agents === 'number') parts.push(hd.agents + ' agents');
      if (Array.isArray(hd.providers) && hd.providers.length) parts.push(hd.providers.join(', '));
      document.getElementById('status-text').textContent = parts.join(' \u00b7 ');
      // Update kpi-agents from health (authoritative count)
      if (typeof hd.agents === 'number') {
        document.getElementById('kpi-agents').textContent = hd.agents;
        document.getElementById('kpi-agents').dataset.fromHealth = '1';
      }
    } catch {
      document.getElementById('status-dot').className = 'status-dot status-dot--err';
      document.getElementById('status-text').textContent = 'API down';
    }
  }

  // Agent CRUD
  document.getElementById('add-agent-btn')?.addEventListener('click', () => { const f=document.getElementById('add-agent-form'); f.style.display=f.style.display==='none'?'block':'none'; });
  document.getElementById('cancel-agent-btn')?.addEventListener('click', () => document.getElementById('add-agent-form').style.display='none');
  document.getElementById('save-agent-btn')?.addEventListener('click', async () => {
    const name=document.getElementById('new-agent-name')?.value?.trim(); if(!name)return;
    await fetch(AI,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({
      name, description:document.getElementById('new-agent-desc')?.value||'',
      system_prompt:document.getElementById('new-agent-prompt')?.value||'',
      strategy:document.getElementById('new-agent-strategy')?.value||'best',
      preferred_provider:document.getElementById('new-agent-provider')?.value||null,
      temperature:0.5, max_tokens:4096
    })});
    document.getElementById('add-agent-form').style.display='none'; loadDashboard();
  });

  // Copilot quick
  document.getElementById('chat-send')?.addEventListener('click', sendChat);
  document.getElementById('chat-input')?.addEventListener('keydown', e => { if(e.key==='Enter') sendChat(); });
  async function sendChat() {
    const input = document.getElementById('chat-input');
    const msg = input?.value?.trim(); if(!msg) return; input.value = '';
    const agent = document.getElementById('chat-agent')?.value || 'agent-zero';
    const out = document.getElementById('chat-output');
    out.innerHTML = '<div class="loading">'+agent+' réfléchit...</div>';
    try {
      const r = await fetch(AI+'/'+agent+'/run',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({messages:[{role:'user',content:msg}]})});
      const d = await r.json();
      out.innerHTML = '<pre>'+(d.content||d.response||JSON.stringify(d)).replace(/</g,'&lt;')+'</pre><button class="btn btn--outline btn--sm copy-chat">Copier</button>';
      out.querySelector('.copy-chat')?.addEventListener('click', function(){navigator.clipboard.writeText(d.content||d.response||'');this.textContent='✓';});
    } catch(e) { out.innerHTML = '<p class="err">Erreur: '+e.message+'</p>'; }
  }

  loadDashboard();

  // --- SERVICES MONITORING ---
  async function loadServices() {
    const services = [
      {name:'Site',url:'https://www.lelectronrare.fr/'},{name:'API',url:API+'/health'},
      {name:'CRM',url:'https://tower.saillant.cc/'},{name:'Listmonk',url:'https://mail.saillant.cc/'},
      {name:'n8n',url:'https://n8n.saillant.cc/'},{name:'Cal.com',url:'https://rdv.saillant.cc/'},
      {name:'Metabase',url:'https://kpi.saillant.cc/'},{name:'Authentik',url:'https://auth.saillant.cc/'},
      {name:'Memos',url:'https://memos.saillant.cc/'},{name:'Excalidraw',url:'https://draw.saillant.cc/'},
      {name:'Paperless',url:'https://docs.saillant.cc/'},{name:'ntfy',url:'https://ntfy.saillant.cc/'},
    ];
    const grid = document.getElementById('monitor-grid');
    grid.innerHTML = services.map(s => `<div class="mon-card" id="mon-${s.name}"><span class="mon-dot"></span><span class="mon-name">${s.name}</span><span class="mon-ms"></span></div>`).join('');
    for (const s of services) {
      const card = document.getElementById('mon-'+s.name); if(!card) continue;
      const t0 = Date.now();
      try { await fetch(s.url,{mode:'no-cors',signal:AbortSignal.timeout(5000)}); card.querySelector('.mon-dot').classList.add('mon-ok'); card.querySelector('.mon-ms').textContent=(Date.now()-t0)+'ms'; }
      catch { card.querySelector('.mon-dot').classList.add('mon-err'); card.querySelector('.mon-ms').textContent='timeout'; }
    }
  }
  document.getElementById('refresh-services')?.addEventListener('click', loadServices);
  loadServices();
</script>

<style>
  /* ═══ Apple SOTA 2026 — Ops Dashboard ═══ */
  .ops {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem clamp(1rem, 4vw, 2rem);
    min-height: 100vh;
    background: #ffffff;
    color: #1d1d1f;
    font-family: Manrope, -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Helvetica Neue, sans-serif;
    font-size: 0.875rem;
    letter-spacing: -0.01em;
    -webkit-font-smoothing: antialiased;
  }

  /* Header */
  .ops-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1.5rem;
    padding-bottom: 1rem;
    border-bottom: 0.5px solid rgba(0, 0, 0, 0.08);
  }
  .ops-header-left { display: flex; align-items: center; gap: 0.75rem; }
  .ops-header-right { display: flex; align-items: center; gap: 0.5rem; }
  .ops-logo { border-radius: 0.5rem; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
  .ops-title {
    font-family: Manrope, -apple-system, "SF Pro Display", sans-serif;
    font-size: 1.5rem;
    font-weight: 700;
    margin: 0;
    line-height: 1.15;
    letter-spacing: -0.025em;
  }
  .ops-sub { font-size: 0.75rem; color: #86868b; margin: 0.15rem 0 0; font-weight: 500; }

  /* Status bar */
  .status-bar {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.75rem;
    background: #f5f5f7;
    border-radius: 999px;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
  }
  .status-dot { width: 8px; height: 8px; border-radius: 50%; background: #d2d2d7; transition: background 0.3s; }
  .status-dot--ok { background: #30d158; }
  .status-dot--err { background: #ff3b30; }
  .status-text { font-size: 0.7rem; color: #86868b; font-weight: 500; }

  /* Tabs — segmented control Apple-style */
  .tabs {
    display: flex;
    gap: 0;
    margin-bottom: 1.5rem;
    background: #f5f5f7;
    border-radius: 0.75rem;
    padding: 0.2rem;
  }
  .tab {
    flex: 1;
    font-size: 0.85rem;
    padding: 0.55rem 1rem;
    background: none;
    border: none;
    color: #86868b;
    cursor: pointer;
    border-radius: 0.6rem;
    transition: all 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
    font-weight: 600;
    text-align: center;
  }
  .tab:hover { color: #1d1d1f; }
  .tab--active {
    color: #1d1d1f;
    background: #ffffff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08), 0 0.5px 1px rgba(0, 0, 0, 0.04);
  }

  /* Panels */
  .panel { display: none; animation: fadeIn 0.25s cubic-bezier(0.25, 0.1, 0.25, 1); }
  .panel--active { display: block; }
  @keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

  /* Tasks toolbar */
  .tasks-toolbar { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap; }
  .tasks-filters { display: flex; gap: 0.35rem; flex: 1; flex-wrap: wrap; }

  /* Form controls */
  .filter-select, .form-select {
    font-size: 0.8rem;
    padding: 0.4rem 0.65rem;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.5rem;
    background: #ffffff;
    color: #1d1d1f;
    font-family: inherit;
    transition: border-color 0.2s, box-shadow 0.2s;
  }
  .filter-input, .form-input {
    font-size: 0.85rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.625rem;
    background: #ffffff;
    color: #1d1d1f;
    font-family: inherit;
    transition: border-color 0.2s, box-shadow 0.2s;
  }
  .filter-input:focus, .form-input:focus, .form-textarea:focus, .filter-select:focus, .form-select:focus {
    outline: none;
    border-color: #0071e3;
    box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.12);
  }
  .form-textarea {
    width: 100%;
    font-size: 0.85rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.625rem;
    background: #ffffff;
    resize: vertical;
    box-sizing: border-box;
    margin-bottom: 0.5rem;
    font-family: inherit;
    line-height: 1.5;
  }
  .form-row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
  .card-form {
    background: #ffffff;
    border: 0.5px solid rgba(0, 0, 0, 0.08);
    border-radius: 1rem;
    padding: 1rem;
    margin-bottom: 1rem;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
  }

  /* Task groups */
  .task-group { margin-bottom: 1.25rem; }
  .group-label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    display: inline-block;
    font-weight: 700;
    margin-bottom: 0.5rem;
  }
  .group-label--red { color: #ff3b30; background: rgba(255, 59, 48, 0.08); }
  .group-label--amber { color: #ff9f0a; background: rgba(255, 159, 10, 0.08); }
  .group-label--blue { color: #0071e3; background: rgba(0, 113, 227, 0.06); }
  .group-label--green { color: #30d158; background: rgba(48, 209, 88, 0.08); }
  .group-label--cyan { color: #0071e3; background: rgba(0, 113, 227, 0.06); }
  .group-done { color: #86868b; background: #f5f5f7; cursor: pointer; list-style: none; border-radius: 999px; }
  .group-done::-webkit-details-marker { display: none; }
  .group-done::before { content: '+ '; font-weight: 700; }
  details[open] > .group-done::before { content: '- '; }

  /* Task cards */
  .task-list { display: flex; flex-direction: column; gap: 0.5rem; }
  .task {
    background: #ffffff;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 0.875rem;
    overflow: hidden;
    transition: all 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
  }
  .task:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06); transform: translateY(-1px); }
  .task--overdue { border-left: 3px solid #ff3b30; }
  .task--done { opacity: 0.35; }
  .task--done .task-title { text-decoration: line-through; }
  .task--open .task-body { display: block; }

  .task-header { display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1rem; cursor: pointer; }
  .task-status { font-size: 0.9rem; color: #86868b; width: 1.25rem; text-align: center; }
  .task-title { flex: 1; font-size: 0.875rem; color: #1d1d1f; font-weight: 500; }

  /* Badges */
  .badge {
    font-size: 0.65rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-weight: 700;
    border: none;
  }
  .badge--red { background: rgba(255, 59, 48, 0.08); color: #ff3b30; }
  .badge--amber { background: rgba(255, 159, 10, 0.08); color: #c77d00; }
  .badge--cyan { background: rgba(0, 113, 227, 0.06); color: #0071e3; }
  .badge--blue { background: rgba(0, 113, 227, 0.06); color: #0071e3; }
  .badge--green { background: rgba(48, 209, 88, 0.08); color: #1a9d4a; }

  /* Task body */
  .task-body { display: none; padding: 0 1rem 1rem; font-size: 0.85rem; color: #6e6e73; line-height: 1.55; }
  .task-desc p { margin: 0.25rem 0; }
  .task-actions { display: flex; gap: 0.35rem; margin-top: 0.5rem; flex-wrap: wrap; align-items: center; }
  .action-status {
    font-size: 0.8rem;
    padding: 0.35rem 0.5rem;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.5rem;
    font-family: inherit;
    background: #ffffff;
  }
  .action-note {
    flex: 1;
    min-width: 100px;
    font-size: 0.8rem;
    padding: 0.35rem 0.6rem;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 0.5rem;
    font-family: inherit;
  }
  .ai-out { margin-top: 0.5rem; }
  .ai-out pre {
    font-size: 0.8rem;
    white-space: pre-wrap;
    word-break: break-word;
    background: #f5f5f7;
    padding: 0.75rem;
    border-radius: 0.75rem;
    max-height: 200px;
    overflow-y: auto;
    line-height: 1.5;
  }
  .ai-saved summary { font-size: 0.75rem; color: #0071e3; cursor: pointer; font-weight: 600; }
  .ai-saved pre {
    font-size: 0.75rem;
    white-space: pre-wrap;
    background: rgba(0, 113, 227, 0.04);
    padding: 0.6rem;
    border-radius: 0.625rem;
    margin-top: 0.25rem;
    max-height: 150px;
    overflow-y: auto;
  }

  /* LinkedIn preview */
  .li-preview { background: #f5f5f7; border: 0.5px solid rgba(0, 0, 0, 0.06); border-radius: 0.75rem; padding: 0.85rem; margin-bottom: 0.5rem; }
  .li-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.6rem; }
  .li-avatar {
    width: 2rem; height: 2rem; border-radius: 50%;
    background: #0071e3; color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-size: 0.75rem; font-weight: 700;
  }
  .li-line { margin: 0 0 0.15rem; font-size: 0.8rem; color: #1d1d1f; }
  .li-spacer { height: 0.5rem; }

  /* Buttons */
  .btn {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.45rem 0.85rem;
    font-size: 0.8rem;
    font-weight: 600;
    border-radius: 999px;
    text-decoration: none;
    cursor: pointer;
    border: none;
    transition: all 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
    font-family: inherit;
  }
  .btn--primary {
    background: #0071e3;
    color: #ffffff;
    box-shadow: 0 2px 8px rgba(0, 113, 227, 0.2);
  }
  .btn--primary:hover {
    filter: brightness(1.08);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 113, 227, 0.25);
  }
  .btn--outline {
    background: #ffffff;
    border: 0.5px solid rgba(0, 0, 0, 0.1);
    color: #6e6e73;
  }
  .btn--outline:hover { color: #0071e3; border-color: rgba(0, 113, 227, 0.2); background: rgba(0, 113, 227, 0.04); }
  .btn--sm { padding: 0.3rem 0.6rem; font-size: 0.7rem; }

  /* Dashboard KPIs */
  .kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 0.75rem;
    margin-bottom: 1.5rem;
  }
  .kpi-card {
    background: #ffffff;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 1rem;
    padding: 1.25rem 1rem;
    text-align: center;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
    transition: transform 0.2s, box-shadow 0.2s;
  }
  .kpi-card:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06); }
  .kpi-num {
    font-size: 2rem;
    font-weight: 700;
    color: #1d1d1f;
    letter-spacing: -0.02em;
  }
  .kpi-label {
    font-size: 0.7rem;
    color: #86868b;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 0.15rem;
    font-weight: 600;
  }

  .sub-title {
    font-family: Manrope, -apple-system, "SF Pro Display", sans-serif;
    font-size: 1.1rem;
    font-weight: 700;
    color: #1d1d1f;
    margin: 1.5rem 0 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    letter-spacing: -0.015em;
  }

  /* Agents grid */
  .agents-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 0.65rem;
    margin-bottom: 1.25rem;
  }
  .agent-card {
    background: #ffffff;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 0.875rem;
    padding: 0.85rem;
    cursor: pointer;
    transition: all 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
  }
  .agent-card:hover {
    border-color: rgba(0, 113, 227, 0.15);
    box-shadow: 0 4px 16px rgba(0, 113, 227, 0.08);
    transform: translateY(-2px);
  }
  .agent-card b { font-size: 0.85rem; color: #0071e3; display: block; margin-bottom: 0.25rem; }
  .agent-card p { font-size: 0.75rem; color: #86868b; margin: 0.25rem 0 0; line-height: 1.4; }

  /* Copilot */
  .copilot-bar { display: flex; gap: 0.5rem; margin-bottom: 0.5rem; }
  .chat-output { min-height: 1.25rem; }
  .chat-output pre {
    font-size: 0.85rem;
    white-space: pre-wrap;
    word-break: break-word;
    background: #f5f5f7;
    border: 0.5px solid rgba(0, 0, 0, 0.04);
    padding: 1rem;
    border-radius: 0.875rem;
    max-height: 300px;
    overflow-y: auto;
    line-height: 1.55;
  }

  .quick-links { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1.25rem; }

  /* Services monitoring */
  .monitor-grid { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.25rem; }
  .mon-card {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    background: #ffffff;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 999px;
    padding: 0.4rem 0.75rem;
    font-size: 0.8rem;
    transition: box-shadow 0.2s;
  }
  .mon-card:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); }
  .mon-dot { width: 8px; height: 8px; border-radius: 50%; background: #d2d2d7; transition: background 0.3s; }
  .mon-ok { background: #30d158; }
  .mon-err { background: #ff3b30; }
  .mon-name { color: #1d1d1f; font-weight: 500; }
  .mon-ms { color: #86868b; font-size: 0.65rem; }

  /* Services cards */
  .services-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    gap: 0.65rem;
    margin-bottom: 1.25rem;
  }
  .svc-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 1rem 0.6rem;
    background: #ffffff;
    border: 0.5px solid rgba(0, 0, 0, 0.06);
    border-radius: 1rem;
    text-decoration: none;
    transition: all 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
  }
  .svc-card:hover {
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
    transform: translateY(-3px);
  }
  .svc-card img { border-radius: 0.625rem; }
  .svc-card span { font-size: 0.75rem; color: #6e6e73; text-align: center; font-weight: 500; }
  .status-refresh { font-size: 1rem; cursor: pointer; color: #0071e3; font-weight: 500; }
  .status-refresh:hover { opacity: 0.7; }

  /* Utilities */
  .loading { text-align: center; padding: 2rem; color: #0071e3; animation: pulse 1.5s infinite; font-weight: 500; }
  @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
  .err { color: #ff3b30; font-size: 0.85rem; }
  .hint { color: #86868b; font-size: 0.85rem; }

  /* Responsive */
  @media (max-width: 640px) {
    .ops { padding: 1rem 0.75rem; }
    .ops-title { font-size: 1.25rem; }
    .tasks-toolbar { flex-direction: column; align-items: stretch; }
    .tasks-filters { flex-direction: column; }
    .task-actions { flex-direction: column; }
    .btn { width: 100%; justify-content: center; }
    .kpi-grid { grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
    .kpi-card { padding: 0.85rem 0.5rem; }
    .kpi-num { font-size: 1.5rem; }
    .services-grid { grid-template-columns: repeat(3, 1fr); }
    .agents-grid { grid-template-columns: repeat(2, 1fr); }
    .copilot-bar { flex-direction: column; }
    .tab { padding: 0.45rem 0.6rem; font-size: 0.8rem; }
  }
</style>
