// Assistant IA clinique — analyse réelle des transcriptions via window.claude.complete

const { useState: useStateA, useRef: useRefA, useEffect: useEffectA } = React;

// minimal markdown: **bold**, line breaks, • bullets
function renderRich(text) {
  const lines = text.split('\n');
  return lines.map((line, li) => {
    const parts = line.split(/(\*\*[^*]+\*\*)/g).filter(Boolean).map((seg, si) => {
      if (seg.startsWith('**') && seg.endsWith('**')) return <strong key={si}>{seg.slice(2, -2)}</strong>;
      return <React.Fragment key={si}>{seg}</React.Fragment>;
    });
    return <React.Fragment key={li}>{parts}{li < lines.length - 1 ? <br /> : null}</React.Fragment>;
  });
}

function detectResident(text) {
  const t = text.toLowerCase();
  return window.RESIDENTS.find((r) =>
    t.includes(r.lastName.toLowerCase()) || t.includes(r.firstName.toLowerCase())
  );
}

// Troncature : les N derniers appels en transcription intégrale, les
// suivants en résumé seul (l'historique Firebase peut compter 100+ appels).
const CTX_FULL_CALLS = 10;   // transcriptions complètes
const CTX_SUMMARY_CALLS = 40; // résumés supplémentaires

function buildResidentContext(r, { fullCalls = CTX_FULL_CALLS, summaryCalls = CTX_SUMMARY_CALLS } = {}) {
  if (!r) return '';
  const calls = r.calls.slice(0, fullCalls + summaryCalls).map((c, i) => {
    const head = `[Appel ${i + 1}] ${c.when} · ${c.duration} · humeur ${window.moodOf(c.moodStart).label} → ${window.moodOf(c.moodEnd).label}\nRésumé: ${c.summary}`;
    if (i >= fullCalls || !c.transcript || !c.transcript.length) return head;
    const tr = c.transcript.map((b) => `${b.speaker === 'livana' ? 'Livana' : r.lastName}: ${b.text}`).join('\n');
    return `${head}\nTranscription:\n${tr}`;
  }).join('\n\n');
  const omitted = Math.max(0, r.calls.length - fullCalls - summaryCalls);
  const mood = r.moodTimeline.slice(-30).map((m) => `${m.date}: ${window.moodOf(m.mood).label}`).join(' · ');
  return `RÉSIDENT: ${r.firstName} ${r.lastName}${r.age != null ? `, ${r.age} ans` : ''}, chambre ${r.room}.
État clinique: ${r.condition || 'non renseigné'}.
Histoire de vie: ${r.story || 'non renseignée'}
Sujets apaisants identifiés: ${r.calming.length ? r.calming.join(', ') : 'non renseignés'}.
Déclencheurs identifiés: ${r.triggers.length ? r.triggers.join(', ') : 'non renseignés'}.
Évolution de l'humeur (récente): ${mood || 'aucune donnée'}.
Statistiques: ${r.kpi.calls} appels, durée moyenne ${r.kpi.avgDuration}.
Note clinique de la psychologue: ${r.note || 'aucune'}

HISTORIQUE DES APPELS (du plus récent au plus ancien — les ${Math.min(fullCalls, r.calls.length)} plus récents avec transcription intégrale, les suivants en résumé${omitted ? ` ; ${omitted} appels plus anciens non inclus` : ''}):
${calls || 'Aucun appel enregistré.'}`;
}

// Contexte global : TOUS les résidents de l'établissement (pour le grand
// chatbot quand aucun résident précis n'est nommé ou sélectionné).
function buildGlobalContext() {
  const blocs = window.RESIDENTS.map((r) =>
    buildResidentContext(r, { fullCalls: 2, summaryCalls: 10 })
  ).join('\n\n────────────────\n\n');
  return `ÉTABLISSEMENT: ${window.ESTABLISHMENT} — ${window.RESIDENTS.length} résidents suivis par Livana.

DOSSIERS DES RÉSIDENTS (pour chacun : fiche + appels récents, transcription intégrale pour les 2 derniers) :

${blocs}`;
}

// Construit à chaque question (l'établissement n'est connu qu'après connexion)
const SYSTEM_PROMPT_RULES = `Règles :
- Réponds en français, de manière concise (3 à 6 phrases max sauf demande de synthèse), professionnelle, bienveillante et nuancée.
- Appuie-toi UNIQUEMENT sur les données fournies. Si l'information manque, dis-le clairement plutôt que d'inventer.
- Mets en **gras** les éléments cliniques clés (humeur, déclencheurs, sujets apaisants, citations marquantes).
- Tu peux citer brièvement les propos du résident pour étayer.
- Tu n'es pas médecin : pas de diagnostic définitif ni de prescription. Tu proposes des pistes de suivi, jamais des certitudes.
- Reste centré sur le ou les résidents dont les données sont fournies.`;
const systemPrompt = () => `Tu es l'assistant clinique de Livana, une IA d'aide au suivi destinée à la psychologue d'un EHPAD (${window.ESTABLISHMENT}). Ton rôle : analyser les transcriptions et données d'appels des résidents pour aider la psychologue à personnaliser le suivi.

${SYSTEM_PROMPT_RULES}`;

// Mémoire des conversations (en mémoire de session, par contexte) : les échanges
// survivent aux changements d'onglet/page tant qu'on ne recharge pas ni ne se
// déconnecte. Une conversation par résident + une pour le grand chatbot.
window.CHAT_STORE = window.CHAT_STORE || {};

function Assistant({ mode = 'page', fixedResident = null, asstStyle = 'card', onOpenProfile, locked = false, onUnlockRequest, pageStyle = 'default', topBanner = null, suggestions = null, initialPrompt = null, onPromptConsumed, compactHead = false }) {
  const storeKey = fixedResident ? 'resident:' + fixedResident.id : 'global';
  const saved = window.CHAT_STORE[storeKey] || {};
  const [ctx, setCtx] = useStateA(fixedResident || saved.ctx || null);
  const [pickerOpen, setPickerOpen] = useStateA(false);
  const [search, setSearch] = useStateA('');
  const [messages, setMessages] = useStateA(saved.messages || []);
  const [input, setInput] = useStateA('');
  const [loading, setLoading] = useStateA(false);
  const [expanded, setExpanded] = useStateA(false);
  const [showAllSuggest, setShowAllSuggest] = useStateA(false);
  const threadRef = useRefA(null);
  const taRef = useRefA(null);

  useEffectA(() => { if (fixedResident) setCtx(fixedResident); }, [fixedResident]);
  // Sauvegarde de la conversation à chaque échange
  useEffectA(() => {
    window.CHAT_STORE[storeKey] = { messages: messages, ctx: fixedResident ? null : ctx };
  }, [messages, ctx, storeKey]);
  // Changement de contexte (autre fiche résident) : recharge la conversation correspondante
  useEffectA(() => {
    const s = window.CHAT_STORE[storeKey] || {};
    setMessages(s.messages || []);
    if (!fixedResident) setCtx(s.ctx || null);
  }, [storeKey]);
  useEffectA(() => {
    if (!expanded) return;
    const h = (e) => { if (e.key === 'Escape') setExpanded(false); };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [expanded]);
  useEffectA(() => {
    if (threadRef.current) threadRef.current.scrollTop = threadRef.current.scrollHeight;
  }, [messages, loading]);

  const SUGGEST = suggestions && suggestions.length ? suggestions : [
    "Comment évolue l'humeur ces dernières semaines ?",
    "Quels ont été les retours aux questions ciblées de Livana ?",
    "Quels sujets semblent l'apaiser ?",
    "Y a-t-il des signes récurrents d'anxiété ?",
    "Qu'est-ce qui ressort des dernières transcriptions ?",
    "Pourquoi était-il/elle en difficulté lors du dernier appel ?",
  ];

  async function send(text) {
    const q = (text != null ? text : input).trim();
    if (!q || loading) return;

    // resolve context (mention by name on home)
    let active = ctx;
    if (!fixedResident) {
      const detected = detectResident(q);
      if (detected) { active = detected; setCtx(detected); }
    }

    const userMsg = { role: 'user', text: q };
    const historique = messages; // état avant cette question
    setMessages((m) => [...m, userMsg]);
    setInput('');
    if (taRef.current) taRef.current.style.height = 'auto';

    setLoading(true);
    try {
      // Fiche résident ciblée si un résident est sélectionné/détecté,
      // sinon (grand chatbot) contexte global : tous les résidents.
      const context = active ? buildResidentContext(active) : buildGlobalContext();
      const cadre = active
        ? `Les questions portent sur ${active.firstName} ${active.lastName}.`
        : `Aucun résident précis n'est sélectionné : la question peut porter sur un ou plusieurs résidents de l'établissement, ou être transversale (comparaisons, signaux d'alerte…).`;
      // Affichage au fil de l'eau. On repère la bulle en cours d'écriture par
      // son marqueur `streaming` dans l'état lui-même : un drapeau de closure
      // serait lu au moment où React applique la mise à jour (donc trop tard),
      // et le premier fragment écraserait la question de l'utilisatrice.
      const majBulle = (texte, enCours) => setMessages((m) => {
        const dernier = m[m.length - 1];
        const bulle = { role: 'assistant', text: texte };
        if (enCours) bulle.streaming = true;
        if (dernier && dernier.role === 'assistant' && dernier.streaming) {
          const copie = m.slice();
          copie[copie.length - 1] = bulle;
          return copie;
        }
        return [...m, bulle];
      });

      const reply = await window.LivanaAPI.aiComplete({
        system: `${systemPrompt()}\n\n${cadre}\n\n=== DONNÉES À ANALYSER ===\n${context}`,
        messages: historique.slice(-8).map((m) => ({ role: m.role === 'assistant' ? 'assistant' : 'user', content: m.text }))
          .concat([{ role: 'user', content: q }]),
        onToken: (partiel) => {
          majBulle(partiel, true);
          setLoading(false); // le texte remplace l'indicateur de frappe
        },
      });
      // Fige la bulle une fois la réponse terminée (retire le curseur)
      majBulle((reply || '').trim() || "Je n'ai pas pu produire de réponse. Réessayez.", false);
    } catch (e) {
      console.warn('aiComplete (assistant) indisponible :', e && e.message);
      setMessages((m) => [...m, { role: 'assistant', text: "Le service d'analyse est momentanément indisponible. Réessayez dans un instant." }]);
    } finally {
      setLoading(false);
    }
  }

  const promptHandledRef = useRefA(null);
  useEffectA(() => {
    if (!initialPrompt || promptHandledRef.current === initialPrompt) return;
    promptHandledRef.current = initialPrompt;
    const prefillOnly = initialPrompt.startsWith('[PREFILL]');
    const text = prefillOnly ? initialPrompt.slice(9).trim() : initialPrompt;
    if (locked || prefillOnly) { setInput(text); }
    else { send(text); }
    if (onPromptConsumed) onPromptConsumed();
  }, [initialPrompt, locked]);

  const onKey = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); }
  };
  const pickSuggestion = (s) => {
    setInput(s);
    if (taRef.current) {
      taRef.current.focus();
      taRef.current.style.height = 'auto';
      taRef.current.style.height = Math.min(taRef.current.scrollHeight, 120) + 'px';
    }
  };
  const autoGrow = (e) => {
    setInput(e.target.value);
    e.target.style.height = 'auto';
    e.target.style.height = Math.min(e.target.scrollHeight, 120) + 'px';
  };

  const filtered = window.RESIDENTS.filter((r) =>
    `${r.firstName} ${r.lastName}`.toLowerCase().includes(search.toLowerCase()));

  const resetChat = () => {
    setMessages([]);
    if (!fixedResident) setCtx(null);
    delete window.CHAT_STORE[storeKey];
  };

  const headEl = (
    <div className="chat-head">
      <div className={`chat-orb-spark ${loading ? 'pulsing' : ''}`}><Icon name="sparkles" size={34} stroke="var(--accent)" /></div>
      <div>
        <div className="chat-head-title">Livana Copilot</div>
        <div className="chat-head-sub"><span className="online-dot"></span>{fixedResident ? 'Analyse le dossier complet' : 'Analyse les dossiers complets'}</div>
      </div>
      {messages.length > 0 && (
        <button className="chat-head-expand" style={{ marginLeft: 'auto' }} onClick={resetChat} title="Nouvelle conversation">
          <Icon name="plus" size={15} />
        </button>
      )}
      {mode === 'embed' && (
        <button className="chat-head-expand" style={{ marginLeft: messages.length > 0 ? 8 : 'auto' }} onClick={() => setExpanded((e) => !e)} title={expanded ? 'Réduire' : 'Afficher en grand'}>
          <Icon name={expanded ? 'x' : 'expand'} size={15} />
        </button>
      )}
    </div>
  );

  const threadEl = messages.length === 0 ? (
    <div className="chat-thread" ref={threadRef}>
      <div className="chat-empty">
        <div className="chat-orb-spark"><Icon name="sparkles" size={52} stroke="var(--accent)" /></div>
        <div className="chat-empty-title">
          {ctx ? `Interrogez le dossier de ${ctx.firstName}` : 'Posez une question sur un résident'}
        </div>
        <div className="chat-empty-sub">
          {ctx
            ? "Je m'appuie sur ses transcriptions, son humeur et ses résumés pour vous répondre."
            : "Nommez un résident pour cibler son dossier, ou posez une question générale — j'ai accès aux appels de tous les résidents."}
        </div>
      </div>
    </div>
  ) : (
    <div className="chat-thread" ref={threadRef}>
      {messages.map((m, i) => (
        <div key={i} className={`chat-msg ${m.role}`}>
          <span className="chat-msg-av">{m.role === 'assistant' ? '' : window.PSY.initials}</span>
          <div className="chat-bubble">
            {renderRich(m.text)}
            {m.streaming && <span className="chat-caret" aria-hidden="true"></span>}
          </div>
        </div>
      ))}
      {loading && (
        <div className="chat-msg assistant">
          <span className="chat-msg-av"></span>
          <div className="chat-bubble"><div className="typing"><i></i><i></i><i></i></div></div>
        </div>
      )}
    </div>
  );

  // Sur mobile et tablette (≤ 1024 px), le CSS ne laisse visible que la
  // première suggestion tant que `chat-suggest-open` est absent — le bouton
  // « Afficher plus (n) » (masqué sur bureau) déplie les autres.
  const tactile = window.matchMedia && window.matchMedia('(max-width: 1024px)').matches;
  const visiblesEmbed = tactile ? 1 : 3; // le CSS ne laisse qu'une puce sur tactile
  const suggestEl = messages.length === 0 ? (
    <div className={`chat-suggest ${showAllSuggest ? 'chat-suggest-open' : ''}`}>
      {mode === 'embed' ? (
        <React.Fragment>
          {(showAllSuggest ? SUGGEST : SUGGEST.slice(0, 3)).map((s, i) => (
            <button key={i} className="suggest-chip" onClick={() => pickSuggestion(s)}>{s}</button>
          ))}
          {SUGGEST.length > visiblesEmbed && (
            <button className="suggest-more" onClick={() => setShowAllSuggest((v) => !v)}>
              {showAllSuggest ? 'Moins de suggestions' : `Afficher plus de suggestions (${SUGGEST.length - visiblesEmbed})`}
            </button>
          )}
        </React.Fragment>
      ) : (
        <React.Fragment>
          <div className="chat-suggest-h">Questions suggérées</div>
          {SUGGEST.map((s, i) => (
            <button key={i} className="suggest-chip" onClick={() => pickSuggestion(s)}>{s}</button>
          ))}
          <button className="suggest-more suggest-more-tactile" onClick={() => setShowAllSuggest((v) => !v)}>
            {showAllSuggest ? 'Moins de suggestions' : `Afficher plus de suggestions (${SUGGEST.length - 1})`}
          </button>
        </React.Fragment>
      )}
    </div>
  ) : null;

  const composerEl = (
    <div className="chat-composer">
      <div className="chat-composer-inner">
        <textarea
          ref={taRef}
          className="chat-input"
          rows={1}
          placeholder={tactile
            ? (ctx ? `Question sur ${ctx.firstName}…` : 'Votre question…')
            : (ctx ? `Question sur ${ctx.firstName} ${ctx.lastName}…` : 'Votre question — un résident précis ou tous…')}
          value={input}
          onChange={autoGrow}
          onKeyDown={onKey}
        />
        <button className="chat-send" disabled={!input.trim() || loading} onClick={() => send()}>
          <Icon name="send" size={17} />
        </button>
      </div>
      <div className="chat-foot"><Icon name="lock" size={11} /> Conversation confidentielle · à ne pas montrer à n'importe qui</div>
    </div>
  );

  const wrapExpand = (shellEl) => expanded
    ? ReactDOM.createPortal(
        <div className="chat-fs-layer">
          <div className="chat-fs-backdrop" onClick={() => setExpanded(false)}></div>
          {shellEl}
        </div>,
        document.body
      )
    : shellEl;

  const lockEl = locked ? (
    <div className="chat-lock">
      <div className="chat-lock-ic"><Icon name="lock" size={26} /></div>
      <div className="chat-lock-title">Agent verrouillé</div>
      <div className="chat-lock-sub">L'agent analyse des transcriptions couvertes par le secret médical. Déverrouillez-le avec votre code à 4&nbsp;chiffres.</div>
      <button className="btn btn-accent" onClick={onUnlockRequest}><Icon name="lock" size={15} /> Déverrouiller l'agent</button>
    </div>
  ) : null;

  // ── ChatGPT-style layout (assistant page) ──
  if (pageStyle === 'chatgpt') {
    const shellEl = (
      <div className={`chat-shell chat-gpt asst-${asstStyle} ${locked ? 'is-locked' : ''} ${expanded ? 'chat-fullscreen' : ''}`} style={{ height: '100%' }}>
        {lockEl}
        {topBanner}
        {compactHead
          ? <button className="chat-float-expand" onClick={() => setExpanded((e) => !e)} title={expanded ? 'Réduire' : 'Afficher en grand'}><Icon name={expanded ? 'x' : 'expand'} size={15} /></button>
          : headEl}
        {messages.length === 0 ? (
          <div className="gpt-center">
            <div className="gpt-center-inner">
              <div className={`chat-orb-spark ${loading ? 'pulsing' : ''}`} style={{ marginBottom: 4 }}><Icon name="sparkles" size={48} stroke="var(--accent)" /></div>
              <h2 className="gpt-title">
                {ctx ? `Interrogez le dossier de ${ctx.firstName}` : 'Comment puis-je vous aider ?'}
              </h2>
              <div className="gpt-sub">
                {ctx
                  ? "Je m'appuie sur ses transcriptions, son humeur et ses résumés pour vous répondre."
                  : "Posez votre question — sur un résident précis ou sur l'ensemble de l'établissement."}
              </div>
              {composerEl}
              {suggestEl}
            </div>
          </div>
        ) : (
          <React.Fragment>
            {threadEl}
            {composerEl}
          </React.Fragment>
        )}
      </div>
    );
    return wrapExpand(shellEl);
  }

  const shellEl = (
    <div className={`chat-shell asst-${asstStyle} ${mode === 'embed' ? 'chat-embed' : ''} ${locked ? 'is-locked' : ''} ${expanded ? 'chat-fullscreen' : ''}`} style={mode === 'page' ? { height: '100%' } : null}>
      {lockEl}
      {headEl}
      {threadEl}
      {suggestEl}
      {composerEl}
    </div>
  );
  return wrapExpand(shellEl);
}

window.Assistant = Assistant;
