// ============================================================
// ai.jsx — wrapper FE per /api/ai/complete (Copilot live)
// ============================================================
//
// FASE 2b.AI.2: la simulazione vive ora server-side in
// `apps/web/src/lib/ai-simulated.ts`. Questo modulo è un thin wrapper
// che chiama `POST /api/ai/complete` con i messaggi e il system prompt;
// il server decide secondo `ai_credentials.mode` (simulated/hybrid/live)
// e usa la chiave salvata in DB cifrata per i provider reali.
//
// La response include `source` (`simulated`, `claude`, `gemini`) e
// `model`/`latencyMs` quando è una chiamata live; `fallback:true` quando
// l'hybrid ha fallback al simulato.

// FASE 11 — /api/ai/invoke con provenance ledger (ai_invocation row + audit-safe).
// /api/ai/complete continua a funzionare (back-compat) ma il copilot punta al
// nuovo endpoint per ricevere `invocationId` e poter linkare la conversazione
// all'event log.
async function aiAsk({ messages, system, context, agentCode } = {}) {
  const userId = readUserId();
  const res = await fetch('/api/ai/invoke', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Actor-Persona-Id': userId || '',
    },
    credentials: 'same-origin',
    body: JSON.stringify({
      messages: (messages || []).map((m) => ({ role: m.role, content: m.content })),
      system,
      ...(context ? { context } : {}),
      ...(agentCode ? { agentCode } : {}),
    }),
  });
  const json = await res.json().catch(() => null);
  if (!res.ok) {
    const detail = json?.detail || json?.error || `HTTP ${res.status}`;
    throw new Error(detail);
  }
  const d = json.data || {};
  return {
    text: d.text,
    source: d.source,
    provider: d.provider,
    model: d.model,
    latencyMs: d.latencyMs,
    finishReason: d.finishReason,
    fallback: !!d.fallback,
    fallbackReason: d.fallbackReason || null,
    matchedRule: d.matchedRule || null,
    invocationId: d.invocationId || null,
    promptHash: d.promptHash || null,
    agentCode: d.agentCode || null,
  };
}

// FASE 11.B — streaming via /api/ai/stream (SSE).
// Eventi server: meta, delta, usage, done, error.
// onMeta(meta), onChunk(text), onUsage({inputTokens, outputTokens}), onDone({finishReason, latencyMs, source, fallback, fallbackReason, inputTokens, outputTokens, success})
// onError(msg). signal opzionale per cancel.
//
// Su 429 quota_exceeded → throw con error.code = 'quota_exceeded' + dettagli.
async function aiAskStream({ messages, system, signal, onMeta, onChunk, onUsage, onToolCall, onDone, onError } = {}) {
  const userId = readUserId();
  const res = await fetch('/api/ai/stream', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Actor-Persona-Id': userId || '',
      Accept: 'text/event-stream',
    },
    credentials: 'same-origin',
    signal,
    body: JSON.stringify({
      messages: (messages || []).map((m) => ({ role: m.role, content: m.content })),
      system,
    }),
  });

  if (res.status === 429) {
    const body = await res.json().catch(() => ({}));
    const err = new Error('quota_exceeded: ' + (body.reason || 'unknown'));
    err.code = 'quota_exceeded';
    err.body = body;
    throw err;
  }
  if (!res.ok || !res.body) {
    const txt = await res.text().catch(() => '');
    throw new Error(txt || ('HTTP ' + res.status));
  }

  const reader = res.body.getReader();
  const decoder = new TextDecoder();
  let buf = '';
  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) break;
      buf += decoder.decode(value, { stream: true });
      let sepIdx;
      while ((sepIdx = buf.indexOf('\n\n')) !== -1) {
        const record = buf.slice(0, sepIdx);
        buf = buf.slice(sepIdx + 2);
        if (!record.trim()) continue;
        let event = '';
        let dataRaw = '';
        for (const line of record.split('\n')) {
          if (line.startsWith('event:')) event = line.slice(6).trim();
          else if (line.startsWith('data:')) dataRaw += line.slice(5).trim();
        }
        if (!dataRaw) continue;
        let data;
        try { data = JSON.parse(dataRaw); } catch { continue; }
        if (event === 'meta') onMeta && onMeta(data);
        else if (event === 'delta') onChunk && onChunk(data.text || '');
        else if (event === 'usage') onUsage && onUsage(data);
        else if (event === 'tool_call') onToolCall && onToolCall(data);
        else if (event === 'done') onDone && onDone(data);
        else if (event === 'error') onError && onError(data.error || 'unknown');
      }
    }
  } finally {
    try { reader.releaseLock(); } catch (_) {}
  }
}

function readUserId() {
  try {
    const raw = localStorage.getItem('lgs.user');
    if (!raw) return '';
    const u = JSON.parse(raw);
    return u?.id || '';
  } catch {
    return '';
  }
}

function aiSuggestions(route) {
  const base = {
    dashboard: [
      'Riassumi i rischi critici di questa settimana',
      'Quali progetti sono in ritardo ≥ 15 giorni?',
      'Mostra i top 5 vendor per on-time',
    ],
    projects: [
      'Quale progetto è più a rischio?',
      'Confronta forecast vs baseline su tutto il portfolio',
      'Genera status report esecutivo',
    ],
    archive: [
      'Trova offerte Siemens simili a linea EFA',
      'Cerca specifiche banco test avionica',
      'Capitolati OT segmentation passati',
    ],
    rda: [
      'Crea bozza RdA per cobot rivettatura',
      'Controlla completezza checklist RDA-0142',
      'Estrai allegati mancanti per tutte le RdA in draft',
    ],
    benchmark: [
      'Confronta offerta corrente con 5 storiche',
      'Trend prezzi automazione 2019–2025',
      'Scarto % offerta vs mediana',
    ],
    communications: [
      'Riassumi mail settimana su P-2026-005',
      'Action item scaduti in tutti i MoM',
      'Classifica email per rischio ritardo',
    ],
    alerts: [
      'Perché è stato generato l\'alert a02?',
      'Trend severità ultimi 30 giorni',
      'Silenzia falsi positivi ricorrenti',
    ],
  };
  return base[route] || ['Come posso aiutarti?', 'Mostra panoramica portfolio', 'Cerca nell\'archivio'];
}

Object.assign(window, { aiAsk, aiAskStream, aiSuggestions });
