Nessun oggetto della modifica
Nessun oggetto della modifica
Riga 205: Riga 205:
   refreshProjects();
   refreshProjects();
});
});
/* ===================== MPAI – CHAT APP (no inline script) ===================== */
/** Mostra la UI AI e nasconde i box legacy */
window.showMpAI = function(){
  ['api-settings','project-status','chatgpt-plus','test-tools','activity-log']
    .forEach(id => { const el=document.getElementById(id); if(el) el.style.display='none'; });
  const ai = document.getElementById('mpAI');
  if (ai){ ai.style.display='block'; ai.scrollIntoView({behavior:'smooth'}); }
};
/** Stato locale della chat */
const mpaiState = {
  currentProject: null,  // “progetto reale” (opzionale)
  sessionId: null,        // id bozza locale
  sessionMeta: null,      // {title, updated}
  history: [],
  attachments: []
};
/** Shortcuts */
const $mp = (s)=>document.querySelector(s);
/** UI helpers */
function mpaiAppendMsg(role, content){
  const chatEl = $mp('#mpai-chat');
  if (!chatEl) return;
  const div = document.createElement('div');
  div.className = 'mpai-msg ' + (role === 'user' ? 'user' : (role === 'assistant' ? 'assistant' : 'error'));
  div.innerHTML = `
    <div class="role">${role==='user'?'Tu':role==='assistant'?'GPT':'Errore'}</div>
    <div class="content" style="white-space:pre-wrap">${content}</div>`;
  chatEl.appendChild(div);
  chatEl.scrollTop = chatEl.scrollHeight;
}
function mpaiRenderFiles(){
  const fileListEl = $mp('#mpai-file-list');
  if (!fileListEl) return;
  fileListEl.innerHTML = '';
  mpaiState.attachments.forEach((a,i)=>{
    const pill = document.createElement('span');
    pill.className = 'mpai-filepill';
    pill.innerHTML = `<span title="Allegato">${a.name}</span><button title="Rimuovi">✕</button>`;
    pill.querySelector('button').onclick = ()=>{ mpaiState.attachments.splice(i,1); mpaiRenderFiles(); };
    fileListEl.appendChild(pill);
  });
}
/** Persistenza “per progetto” (cronologia locale) */
function mpaiSaveLocal(){
  if (!mpaiState.currentProject) return;
  localStorage.setItem('mpai.hist.'+mpaiState.currentProject, JSON.stringify(mpaiState.history.slice(-200)));
}
function mpaiLoadLocal(project){
  const chatEl = $mp('#mpai-chat');
  if (!chatEl) return;
  const raw = localStorage.getItem('mpai.hist.'+project);
  mpaiState.history = raw ? JSON.parse(raw) : [];
  chatEl.innerHTML = '';
  if (!mpaiState.history.length){
    mpaiAppendMsg('assistant', 'Pronto! Dimmi cosa vuoi fare su "'+project+'". Allegami anche file sanificati se servono.');
  } else {
    mpaiState.history.forEach(m => mpaiAppendMsg(m.role, m.content));
  }
}
/** Bozze locali (se non c’è progetto) */
function mpaiEnsureSession(){
  if (!mpaiState.sessionId){
    mpaiState.sessionId = 'sess-' + Date.now();
    mpaiState.sessionMeta = { title: 'Nuova conversazione', updated: Date.now() };
    localStorage.setItem('mpai.session.meta.'+mpaiState.sessionId, JSON.stringify(mpaiState.sessionMeta));
  }
}
function mpaiSaveSession(){
  if (!mpaiState.sessionId) return;
  const key = 'mpai.session.hist.' + mpaiState.sessionId;
  localStorage.setItem(key, JSON.stringify(mpaiState.history.slice(-200)));
  mpaiState.sessionMeta.updated = Date.now();
  localStorage.setItem('mpai.session.meta.'+mpaiState.sessionId, JSON.stringify(mpaiState.sessionMeta));
}
function mpaiLoadSession(id){
  const chatEl = $mp('#mpai-chat');
  if (!chatEl) return;
  mpaiState.sessionId = id;
  const key = 'mpai.session.hist.' + id;
  const raw = localStorage.getItem(key);
  mpaiState.history = raw ? JSON.parse(raw) : [];
  const metaRaw = localStorage.getItem('mpai.session.meta.'+id);
  mpaiState.sessionMeta = metaRaw ? JSON.parse(metaRaw) : {title:'Nuova conversazione', updated:Date.now()};
  chatEl.innerHTML = '';
  if (!mpaiState.history.length){
    mpaiAppendMsg('assistant', 'Pronto! Dimmi cosa vuoi fare. Puoi allegare file sanificati.');
  } else {
    mpaiState.history.forEach(m => mpaiAppendMsg(m.role, m.content));
  }
}
/** Lista progetti (sidebar AI) – opzionale ma comoda */
async function mpaiLoadProjects(){
  const box = $mp('#mpai-project-list');
  if (!box) return; // se non c’è la UI AI, non fare nulla
  box.innerHTML = '<em class="muted">Carico progetti…</em>';
  try{
    const r = await fetch('/dashboard/api/project_list.php', {cache:'no-store', credentials:'include'});
    const j = await r.json();
    const arr = Array.isArray(j) ? j : (Array.isArray(j.projects) ? j.projects : []);
    if (!arr.length){ box.innerHTML='<em class="muted">Nessun progetto</em>'; return; }
    box.innerHTML='';
    arr.forEach(item=>{
      const name = (typeof item === 'string') ? item : (item.name || item);
      const row = document.createElement('div');
      row.className = 'row';
      row.innerHTML = `<span class="title">${name}</span>
                      <span><button class="mpai-btn" data-open="${name}">Apri</button></span>`;
      row.querySelector('[data-open]').onclick = ()=>{
        mpaiState.currentProject = name;
        mpaiLoadLocal(name);
      };
      box.appendChild(row);
    });
    if (!mpaiState.currentProject){
      const first = (typeof arr[0]==='string')?arr[0]:(arr[0].name||arr[0]);
      mpaiState.currentProject = first;
      mpaiLoadLocal(first);
    }
  }catch(e){
    box.innerHTML = '<span class="muted">Errore caricamento: '+e.message+'</span>';
  }
}
async function mpaiCreateProject(){
  const inp = $mp('#mpai-project-name');
  const name = (inp?.value||'').trim();
  if (!name){ alert('Inserisci un nome progetto'); return; }
  try{
    const r = await fetch('/dashboard/api/project_create.php', {
      method:'POST',
      headers:{'Content-Type':'application/json'},
      credentials:'include',
      body: JSON.stringify({name})
    });
    const txt = await r.text(); let j; try{ j=JSON.parse(txt) }catch{ j={ok:false,raw:txt}; }
    if (j.ok!==false){ await mpaiLoadProjects(); mpaiState.currentProject=name; mpaiState.history=[]; mpaiLoadLocal(name); inp.value=''; }
    else { alert('Errore creazione: '+(j.error||'')); }
  }catch(e){ alert('Errore rete: '+e.message); }
}
/** INVIO PROMPT → OpenAI proxy */
window.sendPrompt = async function(){
  const ta = $mp('#mpai-input');
  if (!ta) return;
  const model = ($mp('#mpai-model')?.value || 'gpt-4o-2024-05-13').trim();
  const temp  = parseFloat($mp('#mpai-temp')?.value || '0.7') || 0.7;
  const sanitizedOnly = !!($mp('#mpai-sanitized-only')?.checked);
  const content = (ta.value || '').trim();
  if (!content){ ta.focus(); return; }
  // Se non c'è progetto, attiva bozza locale
  if (!mpaiState.currentProject && !mpaiState.sessionId){
    mpaiEnsureSession();
    mpaiLoadSession(mpaiState.sessionId);
  }
  // Mostra subito il messaggio utente
  mpaiState.history.push({role:'user', content});
  mpaiAppendMsg('user', content);
  ta.value = '';
  // Contesto
  const contextName = mpaiState.currentProject
    ? `Progetto: ${mpaiState.currentProject}`
    : `Sessione: ${mpaiState.sessionMeta?.title || 'Nuova conversazione'}`;
  const fileNames = mpaiState.attachments.map(a => a.name).join(', ');
  const preface = `${contextName}
File allegati${sanitizedOnly ? ' (sanificati)' : ''}: ${fileNames || 'nessuno'}
Istruzioni: rispondi in ITALIANO, struttura chiara (titoli, punti elenco), sii operativo. Temperatura: ${temp}.
---
Utente:
${content}`;
  // Placeholder “Elaboro…”
  const pending = document.createElement('div');
  pending.className = 'mpai-msg';
  pending.innerHTML = '<em class="muted">Elaboro…</em>';
  const chatEl = $mp('#mpai-chat');
  chatEl && chatEl.appendChild(pending);
  try{
    const r = await fetch('/dashboard/api/openai_project_gpt.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include',
      mode: 'same-origin',
      cache: 'no-store',
      body: JSON.stringify({ model, prompt: preface })
    });
    const raw = await r.text();
    pending.remove?.();
    if (!r.ok){
      console.error('GPT proxy error', r.status, r.statusText, raw);
      mpaiAppendMsg('error', `HTTP ${r.status} ${r.statusText}\n\n${raw || '(nessun body)'}`);
      mpaiSaveLocal(); return;
    }
    let j;
    try { j = JSON.parse(raw); }
    catch(parseErr){
      console.error('JSON parse error', parseErr, raw);
      mpaiAppendMsg('error', `Risposta non in JSON:\n\n${raw.slice(0,1500)}`);
      mpaiSaveLocal(); return;
    }
    if (j.status === 'ok' && j.result){
      // Se è bozza, rinomina titolo alla prima risposta
      if (!mpaiState.currentProject && mpaiState.sessionMeta && mpaiState.sessionMeta.title === 'Nuova conversazione'){
        mpaiState.sessionMeta.title = (content.slice(0,48) || 'Nuova conversazione');
        mpaiSaveSession();
      }
      mpaiState.history.push({role:'assistant', content: j.result});
      mpaiAppendMsg('assistant', j.result);
      mpaiSaveLocal();
    } else {
      const err = j.error || 'Errore sconosciuto';
      mpaiAppendMsg('error', `API error: ${err}\n\nRAW:\n${(j.raw||'').slice(0,1500)}`);
      mpaiSaveLocal();
    }
  } catch(e){
    pending.remove?.();
    console.error('Network/JS error', e);
    mpaiAppendMsg('error', `Errore di rete/JS: ${e.message}`);
    mpaiSaveLocal();
  }
};
/** Bind UI quando la pagina è pronta (solo se la UI AI esiste) */
document.addEventListener('DOMContentLoaded', ()=>{
  if (!$mp('#mpAI')) return; // non siamo nella dashboard AI
  // Upload locale (solo elenco)
  const dz = $mp('#mpai-dropzone');
  const fi = $mp('#mpai-file-input');
  dz && dz.addEventListener('dragover', e => { e.preventDefault(); dz.style.opacity = .85; });
  dz && dz.addEventListener('dragleave', () => { dz.style.opacity = 1; });
  dz && dz.addEventListener('drop', e => {
    e.preventDefault(); dz.style.opacity = 1;
    Array.from(e.dataTransfer.files||[]).forEach(f=> mpaiState.attachments.push({file:f,name:f.name}));
    mpaiRenderFiles();
  });
  fi && fi.addEventListener('change', () => {
    Array.from(fi.files||[]).forEach(f=> mpaiState.attachments.push({file:f,name:f.name}));
    fi.value=''; mpaiRenderFiles();
  });
  // Bottoni
  $mp('#mpai-send')?.addEventListener('click', window.sendPrompt);
  $mp('#mpai-project-create')?.addEventListener('click', mpaiCreateProject);
  $mp('#mpai-new-chat')?.addEventListener('click', ()=>{
    mpaiState.history=[]; mpaiState.attachments=[]; mpaiRenderFiles();
    const chatEl = $mp('#mpai-chat'); if (chatEl){ chatEl.innerHTML=''; }
    if (mpaiState.currentProject){ mpaiAppendMsg('assistant','Nuova chat per "'+mpaiState.currentProject+'".'); mpaiSaveLocal(); }
    else { mpaiState.sessionId=null; mpaiState.sessionMeta=null; mpaiEnsureSession(); mpaiAppendMsg('assistant','Nuova conversazione.'); mpaiSaveSession(); }
  });
  $mp('#mpai-clear')?.addEventListener('click', ()=>{
    if (!mpaiState.currentProject){ alert('Crea o seleziona un progetto'); return; }
    if (!confirm('Svuotare la conversazione locale?')) return;
    mpaiState.history=[]; mpaiState.attachments=[]; mpaiRenderFiles();
    const chatEl = $mp('#mpai-chat'); if (chatEl){ chatEl.innerHTML=''; }
    mpaiAppendMsg('assistant','Conversazione pulita.'); mpaiSaveLocal();
  });
  // Invio con Cmd/Ctrl+Enter nella textarea
  document.addEventListener('keydown', (e)=>{
    if ((e.metaKey||e.ctrlKey) && e.key==='Enter'){ const ta=$mp('#mpai-input'); if (ta && ta===document.activeElement){ e.preventDefault(); window.sendPrompt(); } }
  });
  // Boot
  mpaiLoadProjects();
});
/* ===================== /MPAI – CHAT APP ===================== */

Versione delle 08:24, 28 set 2025

/* dashboard.js — Masticationpedia (colla UI) */
// ---------- Utilità ----------
const $ = sel => document.querySelector(sel);
const $$ = sel => Array.from(document.querySelectorAll(sel));

function logActivity(msg) {
  const box = $('#activityLogContent');
  if (!box) return;
  const now = new Date();
  const hh = now.toTimeString().slice(0,8);
  const line = `[${hh}] ${msg}`;
  const pre = document.createElement('div');
  pre.textContent = line;
  box.prepend(pre);
}

async function postJSON(url, body) {
  const r = await fetch(url, {
    method: 'POST',
    headers: {'Content-Type':'application/json'},
    body: JSON.stringify(body || {})
  });
  // alcuni endpoint tornano text; gestisco entrambe
  const txt = await r.text();
  try { return JSON.parse(txt); } catch { return {ok:false, raw:txt}; }
}

// ---------- Toggle sezioni ----------
window.toggleDashboardBox = function(id){
  // chiudi tutte
  ['api-settings','project-status','chatgpt-plus','test-tools','activity-log'].forEach(i=>{
    const el = document.getElementById(i);
    if (el) el.style.display = 'none';
  });
  // apri quella scelta
  const box = document.getElementById(id);
  if (box) box.style.display = 'block';
};

// ---------- Clear log server ----------
window.clearServerLog = async function(){
  try {
    const r = await fetch('/dashboard/api/log_clear.php', {cache:'no-store'});
    const j = await r.json();
    if (j.ok) {
      alert('Log svuotato ✅');
      logActivity('🧹 Log server svuotato');
    } else {
      alert('Errore svuota log: ' + (j.error||''));
      logActivity('❌ Errore svuota log');
    }
  } catch(e) {
    alert('Errore rete: ' + e.message);
  }
};

// ---------- Test API OpenAI ----------
window.testAPIConnection = async function(){
  const model  = ($('#model-select')?.value || 'gpt-4o-2024-05-13').trim();
  const prompt = ($('#test-prompt')?.value || 'Dimmi una curiosità sulla mandibola').trim();

  logActivity(`🚀 Test API via proxy — Modello: ${model}`);
  const res = await postJSON('/dashboard/api/openai_project_gpt.php', {model, prompt});
  if (res.status === 'ok' && res.result) {
    logActivity(`✅ Proxy OK — Modello: ${model}`);
    const out = $('#gptResponse');
    if (out) out.textContent = res.result;
  } else {
    logActivity(`❌ Proxy errore: ${(res.error||res.raw||'sconosciuto')}`);
    alert('Errore API: ' + (res.error||res.raw||''));
  }
};

// ---------- Analizza progetto (Stato Progetti) ----------
function buildPromptForGPT(){
  const goal        = ($('#p_goal')?.value||'').trim();
  const audience    = ($('#p_audience')?.value||'').trim();
  const deliverable = ($('#p_deliverable')?.value||'').trim();
  const constraints = ($('#p_constraints')?.value||'').trim();

  const parts = [];
  parts.push('Sei un project manager ed editor senior. Rispondi in ITALIANO. Fornisci un piano chiaro e operativo.');
  if (goal)        parts.push('\n# Obiettivo\n' + goal);
  if (audience)    parts.push('\n# Pubblico\n' + audience);
  if (deliverable) parts.push('\n# Output atteso\n' + deliverable);
  if (constraints) parts.push('\n# Vincoli\n' + constraints);
  parts.push(`
# Formato output richiesto
- Sommario introduttivo
- Punti di forza e rischi
- Piano step-by-step (milestones)
- File/Config necessari dal server (ELENCO puntuale dei file da leggere)
- Risorse & Budget hint
- Metriche di successo`);

  return parts.join('\n');
}

window.runProjectAnalysis = async function(){
  const btn = $('#btnAnalyze');
  if (!btn) return;
  btn.disabled = true; btn.textContent = 'Analizzo…';
  try {
    const prompt = buildPromptForGPT();
    const model  = ($('#model-select')?.value || 'gpt-4o-2024-05-13').trim();
    const res = await postJSON('/dashboard/api/openai_project_gpt.php', {model, prompt});
    if (res.status === 'ok' && res.result) {
      const out = $('#gptResponse');
      if (out) out.textContent = res.result;
      logActivity('🧠 Analisi GPT completata');
    } else {
      const msg = res.error || res.raw || 'Errore sconosciuto';
      logActivity('❌ Analisi GPT fallita: ' + msg);
      alert('Errore analisi: ' + msg);
    }
  } catch(e){
    alert('Errore rete: ' + e.message);
  } finally {
    btn.disabled = false; btn.textContent = 'Analizza con GPT';
  }
};

// ---------- Progetti (crea + lista) ----------
async function refreshProjects(){
  const list = $('#projectsList');
  if (!list) return;
  list.innerHTML = '<em>Carico…</em>';
  try {
    const r = await fetch('/dashboard/api/project_list.php', {cache:'no-store'});
    const j = await r.json();
    if (!j.ok || !Array.isArray(j.projects)) { list.textContent = 'Nessun progetto.'; return; }
    if (!j.projects.length) { list.textContent = 'Nessun progetto.'; return; }
    list.innerHTML = j.projects.map(name => `
      <li style="display:flex;gap:8px;align-items:center;margin:4px 0;">
        <code>${name}</code>
        <button data-open="${name}">Apri</button>
        <button data-zip="${name}">ZIP</button>
        <button data-del="${name}" title="Sposta nel cestino">🗑️</button>
      </li>
    `).join('');
    list.querySelectorAll('[data-open]').forEach(b=>{
      b.addEventListener('click', ()=>selectProject(b.getAttribute('data-open')));
    });
    list.querySelectorAll('[data-zip]').forEach(b=>{
      b.addEventListener('click', ()=>zipProject(b.getAttribute('data-zip')));
    });
    list.querySelectorAll('[data-del]').forEach(b=>{
      b.addEventListener('click', ()=>deleteProject(b.getAttribute('data-del')));
    });
  } catch(e) {
    list.textContent = 'Errore lista: ' + e.message;
  }
}

async function selectProject(name){
  // eventuale endpoint select (se esiste). Per ora solo log.
  logActivity('📂 Project selezionato: ' + name);
}

async function zipProject(name){
  try {
    const j = await postJSON('/dashboard/api/project_backup.php', { name });
    if (j.ok) { alert('ZIP creato: ' + (j.zip||'')); logActivity('🗜️ Backup creato: ' + (j.zip||'')); }
    else { alert('Errore ZIP: ' + (j.error||'')); }
  } catch(e){ alert('Errore: ' + e.message); }
}

async function deleteProject(name){
  if (!confirm('Spostare nel cestino "'+name+'"?')) return;
  try {
    const j = await postJSON('/dashboard/api/project_delete.php', { name });
    if (j.ok) { logActivity('🗑️ Progetto spostato nel cestino'); refreshProjects(); }
    else { alert('Errore delete: ' + (j.error||'')); }
  } catch(e){ alert('Errore: ' + e.message); }
}

async function createProject(){
  const inp = $('#newProjectName');
  const name = (inp?.value||'').trim();
  if (!name) { alert('Inserisci un nome progetto'); return; }
  try {
    const j = await postJSON('/dashboard/api/project_create.php', { name });
    if (j.ok) {
      logActivity('✅ Progetto creato: ' + name);
      inp.value = '';
      refreshProjects();
    } else {
      alert('Errore creazione: ' + (j.error||''));
    }
  } catch(e) {
    alert('Errore rete: ' + e.message);
  }
}

// ---------- Carica in OpenAI (stub clic pulsante in alto) ----------
window.uploadToOpenAI = function(){
  alert('Funzione "Carica in OpenAI" in preparazione.');
};

// ---------- Bind all ----------
document.addEventListener('DOMContentLoaded', ()=>{
  // bottoni/azioni principali già definiti in HTML
  $('#btnAnalyze') && $('#btnAnalyze').addEventListener('click', window.runProjectAnalysis);
  $('#btnCreateProject') && $('#btnCreateProject').addEventListener('click', createProject);
  refreshProjects();
});



/* ===================== MPAI – CHAT APP (no inline script) ===================== */

/** Mostra la UI AI e nasconde i box legacy */
window.showMpAI = function(){
  ['api-settings','project-status','chatgpt-plus','test-tools','activity-log']
    .forEach(id => { const el=document.getElementById(id); if(el) el.style.display='none'; });
  const ai = document.getElementById('mpAI');
  if (ai){ ai.style.display='block'; ai.scrollIntoView({behavior:'smooth'}); }
};

/** Stato locale della chat */
const mpaiState = {
  currentProject: null,   // “progetto reale” (opzionale)
  sessionId: null,        // id bozza locale
  sessionMeta: null,      // {title, updated}
  history: [],
  attachments: []
};

/** Shortcuts */
const $mp = (s)=>document.querySelector(s);

/** UI helpers */
function mpaiAppendMsg(role, content){
  const chatEl = $mp('#mpai-chat');
  if (!chatEl) return;
  const div = document.createElement('div');
  div.className = 'mpai-msg ' + (role === 'user' ? 'user' : (role === 'assistant' ? 'assistant' : 'error'));
  div.innerHTML = `
    <div class="role">${role==='user'?'Tu':role==='assistant'?'GPT':'Errore'}</div>
    <div class="content" style="white-space:pre-wrap">${content}</div>`;
  chatEl.appendChild(div);
  chatEl.scrollTop = chatEl.scrollHeight;
}

function mpaiRenderFiles(){
  const fileListEl = $mp('#mpai-file-list');
  if (!fileListEl) return;
  fileListEl.innerHTML = '';
  mpaiState.attachments.forEach((a,i)=>{
    const pill = document.createElement('span');
    pill.className = 'mpai-filepill';
    pill.innerHTML = `<span title="Allegato">${a.name}</span><button title="Rimuovi">✕</button>`;
    pill.querySelector('button').onclick = ()=>{ mpaiState.attachments.splice(i,1); mpaiRenderFiles(); };
    fileListEl.appendChild(pill);
  });
}

/** Persistenza “per progetto” (cronologia locale) */
function mpaiSaveLocal(){
  if (!mpaiState.currentProject) return;
  localStorage.setItem('mpai.hist.'+mpaiState.currentProject, JSON.stringify(mpaiState.history.slice(-200)));
}
function mpaiLoadLocal(project){
  const chatEl = $mp('#mpai-chat');
  if (!chatEl) return;
  const raw = localStorage.getItem('mpai.hist.'+project);
  mpaiState.history = raw ? JSON.parse(raw) : [];
  chatEl.innerHTML = '';
  if (!mpaiState.history.length){
    mpaiAppendMsg('assistant', 'Pronto! Dimmi cosa vuoi fare su "'+project+'". Allegami anche file sanificati se servono.');
  } else {
    mpaiState.history.forEach(m => mpaiAppendMsg(m.role, m.content));
  }
}

/** Bozze locali (se non c’è progetto) */
function mpaiEnsureSession(){
  if (!mpaiState.sessionId){
    mpaiState.sessionId = 'sess-' + Date.now();
    mpaiState.sessionMeta = { title: 'Nuova conversazione', updated: Date.now() };
    localStorage.setItem('mpai.session.meta.'+mpaiState.sessionId, JSON.stringify(mpaiState.sessionMeta));
  }
}
function mpaiSaveSession(){
  if (!mpaiState.sessionId) return;
  const key = 'mpai.session.hist.' + mpaiState.sessionId;
  localStorage.setItem(key, JSON.stringify(mpaiState.history.slice(-200)));
  mpaiState.sessionMeta.updated = Date.now();
  localStorage.setItem('mpai.session.meta.'+mpaiState.sessionId, JSON.stringify(mpaiState.sessionMeta));
}
function mpaiLoadSession(id){
  const chatEl = $mp('#mpai-chat');
  if (!chatEl) return;
  mpaiState.sessionId = id;
  const key = 'mpai.session.hist.' + id;
  const raw = localStorage.getItem(key);
  mpaiState.history = raw ? JSON.parse(raw) : [];
  const metaRaw = localStorage.getItem('mpai.session.meta.'+id);
  mpaiState.sessionMeta = metaRaw ? JSON.parse(metaRaw) : {title:'Nuova conversazione', updated:Date.now()};
  chatEl.innerHTML = '';
  if (!mpaiState.history.length){
    mpaiAppendMsg('assistant', 'Pronto! Dimmi cosa vuoi fare. Puoi allegare file sanificati.');
  } else {
    mpaiState.history.forEach(m => mpaiAppendMsg(m.role, m.content));
  }
}

/** Lista progetti (sidebar AI) – opzionale ma comoda */
async function mpaiLoadProjects(){
  const box = $mp('#mpai-project-list');
  if (!box) return; // se non c’è la UI AI, non fare nulla
  box.innerHTML = '<em class="muted">Carico progetti…</em>';
  try{
    const r = await fetch('/dashboard/api/project_list.php', {cache:'no-store', credentials:'include'});
    const j = await r.json();
    const arr = Array.isArray(j) ? j : (Array.isArray(j.projects) ? j.projects : []);
    if (!arr.length){ box.innerHTML='<em class="muted">Nessun progetto</em>'; return; }
    box.innerHTML='';
    arr.forEach(item=>{
      const name = (typeof item === 'string') ? item : (item.name || item);
      const row = document.createElement('div');
      row.className = 'row';
      row.innerHTML = `<span class="title">${name}</span>
                       <span><button class="mpai-btn" data-open="${name}">Apri</button></span>`;
      row.querySelector('[data-open]').onclick = ()=>{ 
        mpaiState.currentProject = name; 
        mpaiLoadLocal(name); 
      };
      box.appendChild(row);
    });
    if (!mpaiState.currentProject){
      const first = (typeof arr[0]==='string')?arr[0]:(arr[0].name||arr[0]);
      mpaiState.currentProject = first;
      mpaiLoadLocal(first);
    }
  }catch(e){
    box.innerHTML = '<span class="muted">Errore caricamento: '+e.message+'</span>';
  }
}
async function mpaiCreateProject(){
  const inp = $mp('#mpai-project-name');
  const name = (inp?.value||'').trim();
  if (!name){ alert('Inserisci un nome progetto'); return; }
  try{
    const r = await fetch('/dashboard/api/project_create.php', {
      method:'POST',
      headers:{'Content-Type':'application/json'},
      credentials:'include',
      body: JSON.stringify({name})
    });
    const txt = await r.text(); let j; try{ j=JSON.parse(txt) }catch{ j={ok:false,raw:txt}; }
    if (j.ok!==false){ await mpaiLoadProjects(); mpaiState.currentProject=name; mpaiState.history=[]; mpaiLoadLocal(name); inp.value=''; }
    else { alert('Errore creazione: '+(j.error||'')); }
  }catch(e){ alert('Errore rete: '+e.message); }
}

/** INVIO PROMPT → OpenAI proxy */
window.sendPrompt = async function(){
  const ta = $mp('#mpai-input');
  if (!ta) return;
  const model = ($mp('#mpai-model')?.value || 'gpt-4o-2024-05-13').trim();
  const temp  = parseFloat($mp('#mpai-temp')?.value || '0.7') || 0.7;
  const sanitizedOnly = !!($mp('#mpai-sanitized-only')?.checked);

  const content = (ta.value || '').trim();
  if (!content){ ta.focus(); return; }

  // Se non c'è progetto, attiva bozza locale
  if (!mpaiState.currentProject && !mpaiState.sessionId){ 
    mpaiEnsureSession();
    mpaiLoadSession(mpaiState.sessionId);
  }

  // Mostra subito il messaggio utente
  mpaiState.history.push({role:'user', content});
  mpaiAppendMsg('user', content);
  ta.value = '';

  // Contesto
  const contextName = mpaiState.currentProject
    ? `Progetto: ${mpaiState.currentProject}`
    : `Sessione: ${mpaiState.sessionMeta?.title || 'Nuova conversazione'}`;

  const fileNames = mpaiState.attachments.map(a => a.name).join(', ');
  const preface = `${contextName}
File allegati${sanitizedOnly ? ' (sanificati)' : ''}: ${fileNames || 'nessuno'}

Istruzioni: rispondi in ITALIANO, struttura chiara (titoli, punti elenco), sii operativo. Temperatura: ${temp}.
---
Utente:
${content}`;

  // Placeholder “Elaboro…”
  const pending = document.createElement('div');
  pending.className = 'mpai-msg';
  pending.innerHTML = '<em class="muted">Elaboro…</em>';
  const chatEl = $mp('#mpai-chat');
  chatEl && chatEl.appendChild(pending);

  try{
    const r = await fetch('/dashboard/api/openai_project_gpt.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include',
      mode: 'same-origin',
      cache: 'no-store',
      body: JSON.stringify({ model, prompt: preface })
    });

    const raw = await r.text();
    pending.remove?.();

    if (!r.ok){
      console.error('GPT proxy error', r.status, r.statusText, raw);
      mpaiAppendMsg('error', `HTTP ${r.status} ${r.statusText}\n\n${raw || '(nessun body)'}`);
      mpaiSaveLocal(); return;
    }

    let j;
    try { j = JSON.parse(raw); }
    catch(parseErr){
      console.error('JSON parse error', parseErr, raw);
      mpaiAppendMsg('error', `Risposta non in JSON:\n\n${raw.slice(0,1500)}`);
      mpaiSaveLocal(); return;
    }

    if (j.status === 'ok' && j.result){
      // Se è bozza, rinomina titolo alla prima risposta
      if (!mpaiState.currentProject && mpaiState.sessionMeta && mpaiState.sessionMeta.title === 'Nuova conversazione'){
        mpaiState.sessionMeta.title = (content.slice(0,48) || 'Nuova conversazione');
        mpaiSaveSession();
      }
      mpaiState.history.push({role:'assistant', content: j.result});
      mpaiAppendMsg('assistant', j.result);
      mpaiSaveLocal();
    } else {
      const err = j.error || 'Errore sconosciuto';
      mpaiAppendMsg('error', `API error: ${err}\n\nRAW:\n${(j.raw||'').slice(0,1500)}`);
      mpaiSaveLocal();
    }
  } catch(e){
    pending.remove?.();
    console.error('Network/JS error', e);
    mpaiAppendMsg('error', `Errore di rete/JS: ${e.message}`);
    mpaiSaveLocal();
  }
};

/** Bind UI quando la pagina è pronta (solo se la UI AI esiste) */
document.addEventListener('DOMContentLoaded', ()=>{
  if (!$mp('#mpAI')) return; // non siamo nella dashboard AI

  // Upload locale (solo elenco)
  const dz = $mp('#mpai-dropzone');
  const fi = $mp('#mpai-file-input');
  dz && dz.addEventListener('dragover', e => { e.preventDefault(); dz.style.opacity = .85; });
  dz && dz.addEventListener('dragleave', () => { dz.style.opacity = 1; });
  dz && dz.addEventListener('drop', e => {
    e.preventDefault(); dz.style.opacity = 1;
    Array.from(e.dataTransfer.files||[]).forEach(f=> mpaiState.attachments.push({file:f,name:f.name}));
    mpaiRenderFiles();
  });
  fi && fi.addEventListener('change', () => {
    Array.from(fi.files||[]).forEach(f=> mpaiState.attachments.push({file:f,name:f.name}));
    fi.value=''; mpaiRenderFiles();
  });

  // Bottoni
  $mp('#mpai-send')?.addEventListener('click', window.sendPrompt);
  $mp('#mpai-project-create')?.addEventListener('click', mpaiCreateProject);
  $mp('#mpai-new-chat')?.addEventListener('click', ()=>{
    mpaiState.history=[]; mpaiState.attachments=[]; mpaiRenderFiles();
    const chatEl = $mp('#mpai-chat'); if (chatEl){ chatEl.innerHTML=''; }
    if (mpaiState.currentProject){ mpaiAppendMsg('assistant','Nuova chat per "'+mpaiState.currentProject+'".'); mpaiSaveLocal(); }
    else { mpaiState.sessionId=null; mpaiState.sessionMeta=null; mpaiEnsureSession(); mpaiAppendMsg('assistant','Nuova conversazione.'); mpaiSaveSession(); }
  });
  $mp('#mpai-clear')?.addEventListener('click', ()=>{
    if (!mpaiState.currentProject){ alert('Crea o seleziona un progetto'); return; }
    if (!confirm('Svuotare la conversazione locale?')) return;
    mpaiState.history=[]; mpaiState.attachments=[]; mpaiRenderFiles();
    const chatEl = $mp('#mpai-chat'); if (chatEl){ chatEl.innerHTML=''; }
    mpaiAppendMsg('assistant','Conversazione pulita.'); mpaiSaveLocal();
  });

  // Invio con Cmd/Ctrl+Enter nella textarea
  document.addEventListener('keydown', (e)=>{
    if ((e.metaKey||e.ctrlKey) && e.key==='Enter'){ const ta=$mp('#mpai-input'); if (ta && ta===document.activeElement){ e.preventDefault(); window.sendPrompt(); } }
  });

  // Boot
  mpaiLoadProjects();
});
/* ===================== /MPAI – CHAT APP ===================== */