// Chatbot screen — sub-routes: persona, chat, prompt, handoff
function ScreenChatbot({ route, onMarkDirty, onSaved, onAction }) {
  const sub = route.split(":")[1] || "persona";
  const toast = useToast();

  // Persona state (lives in this component)
  const [persona, setPersona] = useState({
    voiceTone: "consultivo",
    temperature: 0.5,
    ttsProvider: "piper",
    ttsVoice: "piper-faber",
    ttsSpeed: 0.95,
    ttsPitch: 1,
    ttsExpressivity: 0.78,
  });

  const updatePersona = (k, v) => {
    setPersona((p) => ({ ...p, [k]: v }));
    onMarkDirty();
  };

  // Chat appearance
  const [chat, setChat] = useState({
    welcomeBg: "#ffffff",
    chatBg: "#fff8f3",
    fontFamily: "Sora",
    fontSize: 14,
    fontWeight: "400",
    lineHeight: 1.5,
    bubbleUserBg: "#224187",
    bubbleUserText: "#ffda01",
    bubbleBotBg: "#ffda01",
    bubbleBotText: "#224187",
    messageAvatarsEnabled: true,
    userAvatarPath: "",
    botMessageAvatarPath: "",
    // Mídias do widget (mascote do header + 4 vídeos por estado do bot).
    mascotPath: "",
    welcomeVideo: "",
    idleVideo: "",
    searchVideo: "",
    talkVideo: "",
    // Texto narrado pelo TTS quando o vídeo de saudação abre (vídeo silencioso
    // ganha "voz" via síntese). Vazio = sem áudio extra.
    welcomeIntroText: "",
    greeting: "Olá! Sou o Ramalhinho — o assistente do SINTRACON-SP. Como posso ajudar você hoje?",
    fallback: "Não encontrei essa informação na minha base. Posso te conectar com um atendente humano pelo WhatsApp?",
  });
  const updateChat = (k, v) => { setChat((c) => ({ ...c, [k]: v })); onMarkDirty(); };

  const [systemPrompt, setSystemPrompt] = useState(`Você é o Ramalhinho, assistente virtual oficial do SINTRACON-SP (Sindicato dos Trabalhadores da Construção Civil de São Paulo).

REGRAS DE COMPORTAMENTO:
- Use linguagem clara, próxima e respeitosa. O público inclui trabalhadores da construção civil.
- Responda SEMPRE em português brasileiro.
- Se a pergunta for sobre direitos trabalhistas, recomende falar com a Assessoria Jurídica.
- NUNCA invente informação. Se não souber, diga "Não tenho essa informação na minha base" e ofereça contato humano.

FONTES PERMITIDAS:
- Contextos diretos cadastrados no painel.
- Arquivos indexados (PDFs, cartilhas, estatuto).
- Páginas do site sintracon.org.br.

TOM DE VOZ ATIVO: {{voice_tone}}
DATA: {{current_date}}`);

  // Load real persona once on mount
  useEffect(() => {
    let alive = true;
    api('/api/admin/persona').then((p) => {
      if (!alive || !p) return;
      setPersona((cur) => ({
        ...cur,
        voiceTone: p.voice_tone || cur.voiceTone,
        // Postgres devolve colunas NUMERIC como STRING ("0.7"). Usamos Number()
        // com guarda de NaN — antes o typeof==='number' rejeitava a string e
        // caía no default (bug: temperatura voltava pra 0.5 ao recarregar/salvar).
        temperature: (p.temperature != null && !isNaN(Number(p.temperature))) ? Number(p.temperature) : cur.temperature,
        ttsProvider: p.tts_provider || cur.ttsProvider,
        ttsVoice: p.tts_voice || cur.ttsVoice,
        ttsSpeed: (p.tts_speed != null && !isNaN(Number(p.tts_speed))) ? Number(p.tts_speed) : cur.ttsSpeed,
        ttsPitch: (p.tts_pitch != null && !isNaN(Number(p.tts_pitch))) ? Number(p.tts_pitch) : cur.ttsPitch,
        ttsExpressivity: (p.tts_expressivity != null && !isNaN(Number(p.tts_expressivity))) ? Number(p.tts_expressivity) : cur.ttsExpressivity,
      }));
      setChat((cur) => ({
        ...cur,
        welcomeBg: p.welcome_bg_color || cur.welcomeBg,
        chatBg: p.chat_bg_color || cur.chatBg,
        fontFamily: (p.chat_font_family || cur.fontFamily).replace(/['"]/g, '').split(',')[0].trim(),
        fontSize: p.chat_font_size || cur.fontSize,
        fontWeight: p.chat_font_weight || cur.fontWeight,
        lineHeight: p.chat_line_height || cur.lineHeight,
        bubbleUserBg: p.chat_bubble_user_bg || cur.bubbleUserBg,
        bubbleUserText: p.chat_bubble_user_text || cur.bubbleUserText,
        bubbleBotBg: p.chat_bubble_bot_bg || cur.bubbleBotBg,
        bubbleBotText: p.chat_bubble_bot_text || cur.bubbleBotText,
        messageAvatarsEnabled: typeof p.message_avatars_enabled === 'boolean' ? p.message_avatars_enabled : cur.messageAvatarsEnabled,
        userAvatarPath: p.user_avatar_path || cur.userAvatarPath,
        botMessageAvatarPath: p.bot_message_avatar_path || cur.botMessageAvatarPath,
        mascotPath: p.mascot_path || cur.mascotPath,
        welcomeVideo: p.avatar_video_welcome || cur.welcomeVideo,
        idleVideo: p.avatar_video_idle || cur.idleVideo,
        searchVideo: p.avatar_video_search || cur.searchVideo,
        talkVideo: p.avatar_video_talk || cur.talkVideo,
        welcomeIntroText: typeof p.welcome_intro_text === 'string' ? p.welcome_intro_text : cur.welcomeIntroText,
        greeting: p.greeting_message || cur.greeting,
        fallback: p.fallback_message || cur.fallback,
      }));
      if (p.system_prompt) setSystemPrompt(p.system_prompt);
    }).catch(() => {});
    return () => { alive = false; };
  }, []);

  const savePersona = () => {
    const payload = {
      voice_tone: persona.voiceTone,
      temperature: persona.temperature,
      tts_provider: persona.ttsProvider,
      tts_voice: persona.ttsVoice,
      tts_speed: persona.ttsSpeed,
      tts_pitch: persona.ttsPitch,
      tts_expressivity: persona.ttsExpressivity,
      welcome_bg_color: chat.welcomeBg,
      chat_bg_color: chat.chatBg,
      chat_font_family: "'" + chat.fontFamily + "', sans-serif",
      chat_font_size: chat.fontSize,
      chat_font_weight: chat.fontWeight,
      chat_line_height: chat.lineHeight,
      chat_bubble_user_bg: chat.bubbleUserBg,
      chat_bubble_user_text: chat.bubbleUserText,
      chat_bubble_bot_bg: chat.bubbleBotBg,
      chat_bubble_bot_text: chat.bubbleBotText,
      message_avatars_enabled: chat.messageAvatarsEnabled,
      user_avatar_path: chat.userAvatarPath,
      bot_message_avatar_path: chat.botMessageAvatarPath,
      mascot_path: chat.mascotPath,
      avatar_video_welcome: chat.welcomeVideo,
      avatar_video_idle: chat.idleVideo,
      avatar_video_search: chat.searchVideo,
      avatar_video_talk: chat.talkVideo,
      welcome_intro_text: chat.welcomeIntroText,
      greeting_message: chat.greeting,
      fallback_message: chat.fallback,
      system_prompt: systemPrompt,
    };
    api('/api/admin/persona', { method: 'POST', body: payload })
      .then(() => { onSaved(); toast({ title: "Configuração salva", msg: "Aplicada ao chatbot em produção.", kind: "success" }); })
      .catch((e) => toast({ title: "Falha ao salvar", msg: e.message, kind: "error" }));
  };

  // ---- Sub-tabs router ----
  const tabs = [
    { id: "persona", label: "Persona & Voz", icon: "fa-user-cog" },
    { id: "chat", label: "Aparência", icon: "fa-palette" },
    { id: "prompt", label: "System Prompt", icon: "fa-terminal" },
    { id: "handoff", label: "Atendimento humano", icon: "fa-headset" },
  ];

  return (
    <div className="page" data-screen-label={"Chatbot · " + (tabs.find((t) => t.id === sub) || {}).label}>
      <div className="page-header">
        <div>
          <h1>
            <span className="h1-icon"><i className="fas fa-robot"></i></span>
            Configuração do Chatbot
          </h1>
          <p className="sub">Define personalidade, voz e visual do widget que aparece no site.</p>
        </div>
        <div className="page-header-actions">
          <button className="btn btn-ghost" onClick={() => onAction && onAction("open-preview")}>
            <i className="fas fa-eye"></i> Testar agora
          </button>
          <button className="btn btn-primary" onClick={savePersona}>
            <i className="fas fa-save"></i> Salvar
          </button>
        </div>
      </div>

      <div className="subtabs">
        {tabs.map((t) => (
          <button key={t.id} className={"tab" + (sub === t.id ? " active" : "")} onClick={() => onAction("nav:chatbot:" + t.id)}>
            <i className={"fas " + t.icon}></i> {t.label}
          </button>
        ))}
      </div>

      {sub === "persona" && <PersonaPane persona={persona} update={updatePersona} />}
      {sub === "chat" && <AppearancePane chat={chat} update={updateChat} />}
      {sub === "prompt" && <PromptPane value={systemPrompt} onChange={(v) => { setSystemPrompt(v); onMarkDirty(); }} />}
      {sub === "handoff" && <HandoffPane onAction={onAction} />}
    </div>
  );
}

// ---------- Persona pane ----------
// Mapa de capacidades dos providers TTS — define quais sliders cada provider
// realmente honra na chamada de síntese. Quando o slider não se aplica, a UI
// fica esmaecida com um aviso pra evitar que o usuário ache que está
// configurando algo que não tem efeito.
const TTS_CAPS = {
  piper:            { speed: true,  pitch: true,  expressivity: true,  speedRange: [0.5, 2.0] },
  google_cloud:     { speed: true,  pitch: true,  expressivity: false, speedRange: [0.25, 4.0] },
  openai_tts:       { speed: true,  pitch: false, expressivity: false, speedRange: [0.25, 4.0] },
  elevenlabs:       { speed: true,  pitch: false, expressivity: false, speedRange: [0.7, 1.2] },
  google_translate: { speed: false, pitch: false, expressivity: false, speedRange: [1.0, 1.0] },
};
function getTtsCaps(providerId) {
  return TTS_CAPS[providerId] || TTS_CAPS.piper;
}

function PersonaPane({ persona, update }) {
  const tones = [
    { id: "amigavel", label: "Amigável", emoji: "🤗", desc: "Caloroso, acolhe o usuário" },
    { id: "animado",  label: "Animado", emoji: "✨", desc: "Energético, exclamativo" },
    { id: "formal",   label: "Formal", emoji: "👔", desc: "Tratamento Sr./Sra., neutro" },
    { id: "tecnico",  label: "Técnico", emoji: "🔧", desc: "Direto, foco no fato" },
    { id: "consultivo", label: "Consultivo", emoji: "💼", desc: "Orienta passo-a-passo" },
  ];

  // Provider TTS ativo, pra calcular capabilities (dim de sliders nao suportados)
  // e tambem alimentar o seletor inline do ActiveTtsBanner. Compartilhado com
  // o banner via prop — quando o user troca provider/voz no banner, o reload
  // atualiza este state e os sliders recalculam capabilities automaticamente.
  const [activeTts, setActiveTts] = useState(null);
  const reloadTts = () => api('/api/admin/tts/providers')
    .then((d) => setActiveTts(d))
    .catch(() => {});
  useEffect(() => { reloadTts(); }, []);
  const activeProviderId = activeTts && activeTts.active && activeTts.active.provider;
  const activeProvLabel  = activeProviderId
    ? ((activeTts.providers.find((p) => p.id === activeProviderId) || {}).label || activeProviderId)
    : 'provider ativo';
  const caps = getTtsCaps(activeProviderId);

  return (
    <>
      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-comment-dots"></i> Tom de voz</h3>
          <span className="meta">Aplicado ao texto e ao pitch da voz TTS</span>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", gap: 10 }}>
          {tones.map((t) => (
            <div
              key={t.id}
              onClick={() => update("voiceTone", t.id)}
              style={{
                padding: "14px 16px",
                background: persona.voiceTone === t.id ? "var(--og)" : "var(--bg1)",
                border: persona.voiceTone === t.id ? "1px solid var(--og2)" : "1px solid var(--b1)",
                borderRadius: "var(--r-input)",
                cursor: "pointer",
                transition: "all .15s",
              }}
            >
              <div style={{ fontSize: 20, marginBottom: 6 }}>{t.emoji}</div>
              <div style={{ fontSize: 13, fontWeight: 600, color: persona.voiceTone === t.id ? "var(--or)" : "var(--t1)" }}>{t.label}</div>
              <div style={{ fontSize: 11, color: "var(--t3)", marginTop: 2 }}>{t.desc}</div>
            </div>
          ))}
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-volume-up"></i> Síntese de voz (TTS)</h3>
        </div>

        <ActiveTtsBanner info={activeTts} onReload={reloadTts} />

        <div className="form-row" style={{ marginTop: 16 }}>
          <div className="field">
            <label><i className="fas fa-thermometer-half"></i> Criatividade do texto <code style={{ color: "var(--or)" }}>{persona.temperature.toFixed(1)}</code></label>
            <Range min={0} max={1} step={0.1} value={persona.temperature} onChange={(v) => update("temperature", v)} format={(v) => v.toFixed(1)} />
            <span className="hint">0 = sempre igual · 1 = mais variação criativa. (afeta a resposta do LLM, não a voz)</span>
          </div>
          <SliderField
            icon="fa-tachometer-alt"
            label="Velocidade da voz"
            value={persona.ttsSpeed}
            display={persona.ttsSpeed.toFixed(2) + "x"}
            min={0.5} max={2} step={0.05}
            onChange={(v) => update("ttsSpeed", v)}
            format={(v) => v.toFixed(1) + "x"}
            supported={caps.speed}
            providerLabel={activeProvLabel}
            hint={
              caps.speed
                ? `Ritmo da fala. Faixa aplicada: ${caps.speedRange[0]}x–${caps.speedRange[1]}x (limites do provider).`
                : "Ritmo da fala. 0.9–1.1 soa mais natural."
            }
          />
        </div>

        <div className="form-row" style={{ marginTop: 16 }}>
          <SliderField
            icon="fa-music"
            label="Tonalidade"
            value={persona.ttsPitch}
            display={(persona.ttsPitch > 0 ? "+" : "") + persona.ttsPitch}
            min={-6} max={6} step={1}
            onChange={(v) => update("ttsPitch", v)}
            supported={caps.pitch}
            providerLabel={activeProvLabel}
            hint="Em semitons. 0 = voz original · negativo = grave · positivo = aguda."
          />
          <SliderField
            icon="fa-wave-square"
            label="Expressividade"
            value={persona.ttsExpressivity}
            display={persona.ttsExpressivity.toFixed(2)}
            min={0.3} max={1} step={0.02}
            onChange={(v) => update("ttsExpressivity", v)}
            format={(v) => v.toFixed(2)}
            supported={caps.expressivity}
            providerLabel={activeProvLabel}
            hint='Mais alto = voz mais "viva". Valores baixos soam monótonos.'
          />
        </div>
      </div>
    </>
  );
}

// Campo de slider com feedback visual quando o provider TTS ativo não honra
// o parâmetro — fica esmaecido e mostra aviso "não aplicado por <provider>".
function SliderField({ icon, label, value, display, min, max, step, onChange, format, supported, providerLabel, hint }) {
  const dimStyle = supported ? null : { opacity: 0.55 };
  return (
    <div className="field" style={dimStyle}>
      <label>
        <i className={"fas " + icon}></i> {label}{" "}
        <code style={{ color: "var(--or)" }}>{display}</code>
        {!supported && (
          <span style={{
            marginLeft: 8, fontSize: 10, fontWeight: 600,
            padding: "2px 8px", borderRadius: 10,
            background: "var(--bg1)", border: "1px solid var(--b1)",
            color: "var(--t3)", letterSpacing: ".02em",
          }}>
            <i className="fas fa-info-circle"></i> não aplicado por {providerLabel}
          </span>
        )}
      </label>
      <Range min={min} max={max} step={step} value={value} onChange={onChange} format={format} />
      <span className="hint">
        {!supported
          ? `O provider ${providerLabel} ignora este parâmetro — troque para um provider que o suporte (ex.: Piper).`
          : hint}
      </span>
    </div>
  );
}

// Seletor inline de provider/modelo/voz TTS. Permite trocar tudo sem sair da
// tela. Configuração avançada (API keys, ping, cache) continua em Sistema.
// info e onReload vem do PersonaPane (compartilha state pra capabilities
// dos sliders recalcularem automaticamente quando troca de provider aqui).
function ActiveTtsBanner({ info, onReload }) {
  const toast = useToast();
  const [previewBusy, setPreviewBusy] = useState(false);
  const [switching, setSwitching] = useState(false);
  const load = () => (onReload ? onReload() : Promise.resolve());

  const goToSystem = () => {
    if (window.appNavigate) window.appNavigate('system:config');
    else window.location.hash = '#system:config';
  };

  const selectProvider = async (providerId) => {
    const p = info.providers.find((x) => x.id === providerId);
    if (!p) return;
    if (!p.keyConfigured) {
      toast({
        title: 'API key necessária',
        msg: `Configure a chave do ${p.label} em Sistema → Provider de TTS antes de ativar.`,
        kind: 'error',
      });
      return;
    }
    setSwitching(true);
    try {
      await api('/api/admin/tts/select', {
        method: 'POST',
        body: { provider: p.id, model: p.selectedModel, voice: p.selectedVoice },
      });
      toast({ title: 'Provider de voz ativo', msg: p.label, kind: 'success' });
      await load();
    } catch (e) { toast({ title: 'Falha ao trocar provider', msg: e.message, kind: 'error' }); }
    finally { setSwitching(false); }
  };

  const selectVoice = async (voiceId) => {
    if (!info || !info.active) return;
    setSwitching(true);
    try {
      await api('/api/admin/tts/select', {
        method: 'POST',
        body: { provider: info.active.provider, model: info.active.model, voice: voiceId },
      });
      await load();
    } catch (e) { toast({ title: 'Falha ao trocar voz', msg: e.message, kind: 'error' }); }
    finally { setSwitching(false); }
  };

  const selectModel = async (modelId) => {
    if (!info || !info.active) return;
    setSwitching(true);
    try {
      await api('/api/admin/tts/select', {
        method: 'POST',
        body: { provider: info.active.provider, model: modelId, voice: info.active.voice },
      });
      await load();
    } catch (e) { toast({ title: 'Falha ao trocar modelo', msg: e.message, kind: 'error' }); }
    finally { setSwitching(false); }
  };

  const preview = async () => {
    setPreviewBusy(true);
    try {
      const r = await fetch('/api/admin/tts/preview', {
        method: 'POST',
        headers: { 'Authorization': 'Bearer ' + Auth.token, 'Content-Type': 'application/json' },
        body: JSON.stringify({}),
      });
      if (!r.ok) throw new Error('HTTP ' + r.status);
      const blob = await r.blob();
      const url = URL.createObjectURL(blob);
      const audio = new Audio(url);
      audio.onended = () => URL.revokeObjectURL(url);
      await audio.play();
    } catch (e) { toast({ title: 'Falha no preview', msg: e.message, kind: 'error' }); }
    finally { setPreviewBusy(false); }
  };

  if (!info) {
    return (
      <div style={{ padding: '12px 14px', background: 'var(--bg1)', border: '1px solid var(--b1)', borderRadius: 'var(--r-input)', fontSize: 12, color: 'var(--t3)' }}>
        <i className="fas fa-circle-notch fa-spin"></i> Carregando providers de voz…
      </div>
    );
  }

  const active = info.providers.find((p) => p.id === info.active.provider) || info.providers[0];
  const hasModels = (active.models || []).length > 1;
  const usdBrl = 5.20;

  return (
    <div style={{
      display: 'flex', flexDirection: 'column', gap: 12,
      padding: '14px 16px',
      background: 'linear-gradient(90deg, var(--og), var(--bg1) 70%)',
      border: '1px solid var(--og2)',
      borderRadius: 'var(--r-input)',
    }}>
      {/* Header com mark + nome + preço + preview */}
      <div style={{ display: 'flex', gap: 14, alignItems: 'center' }}>
        <div className="prov-active-mark" data-mark={active.id} style={{ width: 38, height: 38, fontSize: 16 }}>{active.mark}</div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--t1)', display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            {active.label}
            <span className={"badge b-" + active.tierColor} style={{ fontSize: 10 }}>{active.tier}</span>
            {!active.keyConfigured && active.requiresKey && (
              <span className="badge b-rd" style={{ fontSize: 10 }}>sem API key</span>
            )}
          </div>
          <div style={{ fontSize: 11.5, color: 'var(--t3)', fontFamily: 'var(--ff-mono)', marginTop: 2 }}>
            {active.pricePer1M === 0 ? 'grátis · ilimitado' : `R$ ${(active.pricePer1M * usdBrl).toFixed(2)} / 1M characters`}
          </div>
        </div>
        <button type="button" className="btn btn-soft btn-sm" onClick={preview} disabled={previewBusy}>
          {previewBusy ? <><i className="fas fa-circle-notch fa-spin"></i> tocando…</> : <><i className="fas fa-play"></i> ouvir preview</>}
        </button>
        <button type="button" className="btn btn-ghost btn-sm" onClick={goToSystem} title="API keys, ping, cache de áudio">
          <i className="fas fa-sliders-h"></i> configuração avançada
        </button>
      </div>

      {/* Selects: provider · modelo · voz */}
      <div style={{ display: 'grid', gridTemplateColumns: hasModels ? '1fr 1fr 1fr' : '1fr 1fr', gap: 10 }}>
        <div className="field" style={{ margin: 0 }}>
          <label style={{ fontSize: 11, color: 'var(--t3)', marginBottom: 4 }}>
            <i className="fas fa-server"></i> Provider
          </label>
          <select
            className="input"
            value={active.id}
            disabled={switching}
            onChange={(e) => selectProvider(e.target.value)}
          >
            {info.providers.map((p) => {
              const blocked = p.requiresKey && !p.keyConfigured;
              const labelTxt = p.label + (p.free ? ' · grátis' : '') + (blocked ? ' · sem API key' : '');
              return <option key={p.id} value={p.id}>{labelTxt}</option>;
            })}
          </select>
        </div>

        {hasModels && (
          <div className="field" style={{ margin: 0 }}>
            <label style={{ fontSize: 11, color: 'var(--t3)', marginBottom: 4 }}>
              <i className="fas fa-microchip"></i> Modelo
            </label>
            <select
              className="input"
              value={info.active.model || (active.models[0] || {}).id}
              disabled={switching}
              onChange={(e) => selectModel(e.target.value)}
            >
              {(active.models || []).map((m) => <option key={m.id} value={m.id}>{m.label || m.id}</option>)}
            </select>
          </div>
        )}

        <div className="field" style={{ margin: 0 }}>
          <label style={{ fontSize: 11, color: 'var(--t3)', marginBottom: 4 }}>
            <i className="fas fa-microphone"></i> Voz
          </label>
          <select
            className="input"
            value={info.active.voice || (active.voices[0] || {}).id || ''}
            disabled={switching || !(active.voices || []).length}
            onChange={(e) => selectVoice(e.target.value)}
          >
            {(active.voices || []).length === 0 && <option value="">(provider sem vozes selecionáveis)</option>}
            {(active.voices || []).map((v) => {
              const desc = v.desc ? ` — ${v.desc}` : '';
              const gender = v.gender ? ` (${v.gender === 'F' ? 'feminina' : v.gender === 'M' ? 'masculina' : v.gender})` : '';
              return <option key={v.id} value={v.id}>{(v.label || v.name || v.id) + gender + desc}</option>;
            })}
          </select>
        </div>
      </div>
    </div>
  );
}

// ---------- Appearance pane ----------
function AppearancePane({ chat, update }) {
  return (
    <>
      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-palette"></i> Cores e fundos</h3>
          <span className="meta">Cores aplicadas atrás do mascote/vídeo no widget.</span>
        </div>
        <div className="form-row">
          <div className="field">
            <label>Fundo: vídeo de saudação</label>
            <div className="color-row">
              <input type="color" value={chat.welcomeBg} onChange={(e) => update("welcomeBg", e.target.value)} />
              <span className="hex">{chat.welcomeBg.toUpperCase()}</span>
              <span className="hint" style={{ marginLeft: "auto" }}>tela inicial</span>
            </div>
          </div>
          <div className="field">
            <label>Fundo: avatar (chat)</label>
            <div className="color-row">
              <input type="color" value={chat.chatBg} onChange={(e) => update("chatBg", e.target.value)} />
              <span className="hex">{chat.chatBg.toUpperCase()}</span>
              <span className="hint" style={{ marginLeft: "auto" }}>durante conversa</span>
            </div>
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-comments"></i> Cores das mensagens</h3>
          <span className="meta">Balões de pergunta (usuário) e resposta (bot) — fundo e texto.</span>
        </div>
        <div className="form-row">
          <div className="field">
            <label>Fundo: balão de pergunta</label>
            <div className="color-row">
              <input type="color" value={chat.bubbleUserBg} onChange={(e) => update("bubbleUserBg", e.target.value)} />
              <span className="hex">{chat.bubbleUserBg.toUpperCase()}</span>
              <span className="hint" style={{ marginLeft: "auto" }}>usuário</span>
            </div>
          </div>
          <div className="field">
            <label>Texto: balão de pergunta</label>
            <div className="color-row">
              <input type="color" value={chat.bubbleUserText} onChange={(e) => update("bubbleUserText", e.target.value)} />
              <span className="hex">{chat.bubbleUserText.toUpperCase()}</span>
              <span className="hint" style={{ marginLeft: "auto" }}>usuário</span>
            </div>
          </div>
        </div>
        <div className="form-row">
          <div className="field">
            <label>Fundo: balão de resposta</label>
            <div className="color-row">
              <input type="color" value={chat.bubbleBotBg} onChange={(e) => update("bubbleBotBg", e.target.value)} />
              <span className="hex">{chat.bubbleBotBg.toUpperCase()}</span>
              <span className="hint" style={{ marginLeft: "auto" }}>bot</span>
            </div>
          </div>
          <div className="field">
            <label>Texto: balão de resposta</label>
            <div className="color-row">
              <input type="color" value={chat.bubbleBotText} onChange={(e) => update("bubbleBotText", e.target.value)} />
              <span className="hex">{chat.bubbleBotText.toUpperCase()}</span>
              <span className="hint" style={{ marginLeft: "auto" }}>bot</span>
            </div>
          </div>
        </div>
        {/* Mini-preview ao vivo: mostra os 2 balões com as cores configuradas
            antes de salvar. Mesmo padrão do "Preview ao vivo" da tipografia.
            Útil pra calibrar contraste (evita fundo+texto na mesma cor). */}
        <div className="form-row" style={{ marginTop: 12 }}>
          <div className="field" style={{ flex: 1 }}>
            <label>Preview ao vivo</label>
            <div style={{
              padding: "12px",
              background: "var(--bg1)",
              border: "1px solid var(--b1)",
              borderRadius: "var(--r-input)",
              display: "flex",
              flexDirection: "column",
              gap: 8,
            }}>
              <div style={{
                alignSelf: "flex-end",
                background: chat.bubbleUserBg,
                color: chat.bubbleUserText,
                padding: "8px 14px",
                borderRadius: "14px",
                borderTopRightRadius: 2,
                fontWeight: 700,
                fontSize: 13,
                maxWidth: "70%",
              }}>Quais são meus direitos?</div>
              <div style={{
                alignSelf: "flex-start",
                background: chat.bubbleBotBg,
                color: chat.bubbleBotText,
                padding: "8px 14px",
                borderRadius: "14px",
                borderTopLeftRadius: 2,
                fontWeight: 700,
                fontSize: 13,
                maxWidth: "70%",
              }}>Posso te ajudar com os direitos da categoria.</div>
            </div>
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-user-circle"></i> Avatares nas mensagens</h3>
          <span className="meta">Imagem circular ao lado de cada balão (usuário/bot). Toggle global + 2 imagens configuráveis.</span>
        </div>
        <div style={{
          display: "flex", alignItems: "center", justifyContent: "space-between",
          gap: 12, padding: "10px 12px", background: "var(--bg1)",
          border: "1px solid var(--b1)", borderRadius: "var(--r-input)", marginBottom: 14,
        }}>
          <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
            <span style={{ fontSize: 13, fontWeight: 600 }}>Mostrar avatares ao lado das mensagens</span>
            <span style={{ fontSize: 11, color: "var(--t3)" }}>
              {chat.messageAvatarsEnabled
                ? "Avatares visíveis em cada balão."
                : "Avatares ocultos — balões aparecem sozinhos (comportamento legado)."}
            </span>
          </div>
          <Switch on={chat.messageAvatarsEnabled} onChange={(v) => update("messageAvatarsEnabled", v)} />
        </div>
        <div className="form-row">
          <AvatarUploadField
            label="Avatar do usuário (quem pergunta)"
            hint="PNG/JPG quadrada. Fica à direita do balão de pergunta. Vazio → ícone genérico."
            value={chat.userAvatarPath}
            onChange={(v) => update("userAvatarPath", v)}
            fallback={null}
          />
          <AvatarUploadField
            label="Avatar do bot (quem responde)"
            hint="PNG/JPG quadrada. Fica à esquerda do balão de resposta. Vazio → usa o mascote do header."
            value={chat.botMessageAvatarPath}
            onChange={(v) => update("botMessageAvatarPath", v)}
            fallback={chat.mascotPath}
          />
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-video"></i> Mídia e avatar</h3>
          <span className="meta">Mascote (imagem) + 4 vídeos para cada estado do bot. Clique em "Trocar" pra enviar um arquivo.</span>
        </div>

        <div className="media-grid">
          <MediaCard
            label="Mascote (ícone)"
            hint="PNG/JPG quadrada, fundo transparente. Aparece no header do widget."
            value={chat.mascotPath}
            onChange={(v) => update("mascotPath", v)}
            kind="image"
          />
          <MediaCard
            label="Vídeo de saudação"
            hint="MP4 mostrado na tela inicial antes do usuário clicar em INICIAR."
            value={chat.welcomeVideo}
            onChange={(v) => update("welcomeVideo", v)}
            kind="video"
          />
          <MediaCard
            label="Avatar: repouso"
            hint="Loop enquanto aguarda o usuário digitar."
            value={chat.idleVideo}
            onChange={(v) => update("idleVideo", v)}
            kind="video"
          />
          <MediaCard
            label="Avatar: pensando"
            hint="Toca enquanto a IA monta a resposta."
            value={chat.searchVideo}
            onChange={(v) => update("searchVideo", v)}
            kind="video"
          />
          <MediaCard
            label="Avatar: falando"
            hint="Toca enquanto a IA fala (TTS)."
            value={chat.talkVideo}
            onChange={(v) => update("talkVideo", v)}
            kind="video"
          />
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-microphone-lines" style={{ color: "var(--or)" }}></i> Introdução de voz (TTS)</h3>
          <span className="meta">
            Texto narrado pela voz configurada em <strong>Persona &amp; Voz</strong> quando a tela de saudação abre.
            Útil quando o vídeo de saudação é silencioso.
          </span>
        </div>
        <div className="field" style={{ flex: 1 }}>
          <label>Texto a ser lido (sincroniza com o vídeo de saudação)</label>
          <textarea
            className="input"
            rows="3"
            value={chat.welcomeIntroText}
            onChange={(e) => update("welcomeIntroText", e.target.value)}
            placeholder="Ex: Olá! Eu sou o Ramalhinho, do SINTRACON-SP. Clique em INICIAR pra conversar comigo."
          ></textarea>
          <span className="hint">
            Vazio → nenhum áudio extra. Quando o usuário clica em <strong>INICIAR</strong>, o vídeo e a narração param na hora.
          </span>
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-font"></i> Tipografia do chat</h3>
          <span className="meta">Carregada automaticamente do Google Fonts.</span>
        </div>

        <div className="form-row">
          <div className="field">
            <label>Fonte principal</label>
            <select className="input" value={chat.fontFamily} onChange={(e) => update("fontFamily", e.target.value)}>
              {Data.fonts.map((f) => <option key={f} value={f}>{f}</option>)}
            </select>
          </div>
          <div className="field">
            <label>Preview ao vivo</label>
            <div style={{
              padding: "12px 14px",
              background: "var(--bg1)",
              border: "1px solid var(--b1)",
              borderRadius: "var(--r-input)",
              fontFamily: chat.fontFamily,
              fontSize: chat.fontSize + "px",
              fontWeight: chat.fontWeight,
              lineHeight: chat.lineHeight,
              color: "var(--t1)",
            }}>
              Olá! Sou o Ramalhinho — assistente do SINTRACON.
            </div>
          </div>
        </div>

        <div className="form-row-3" style={{ marginTop: 16 }}>
          <div className="field">
            <label>Tamanho (px)</label>
            <input type="number" className="input" value={chat.fontSize} onChange={(e) => update("fontSize", parseInt(e.target.value))} min="8" max="32" />
          </div>
          <div className="field">
            <label>Peso</label>
            <select className="input" value={chat.fontWeight} onChange={(e) => update("fontWeight", e.target.value)}>
              <option value="300">300 — Light</option>
              <option value="400">400 — Normal</option>
              <option value="500">500 — Medium</option>
              <option value="600">600 — Semi-Bold</option>
              <option value="700">700 — Bold</option>
            </select>
          </div>
          <div className="field">
            <label>Altura da linha</label>
            <input type="number" step="0.1" className="input" value={chat.lineHeight} onChange={(e) => update("lineHeight", parseFloat(e.target.value))} min="1" max="3" />
          </div>
        </div>
      </div>

      <div className="card">
        <div className="card-header">
          <h3><i className="fas fa-comment"></i> Mensagens automáticas</h3>
        </div>
        <div className="form-row">
          <div className="field">
            <label><i className="fas fa-hand-paper"></i> Saudação inicial</label>
            <textarea className="input" rows="3" value={chat.greeting} onChange={(e) => update("greeting", e.target.value)}></textarea>
            <span className="hint">Primeira mensagem do bot ao iniciar o chat.</span>
          </div>
          <div className="field">
            <label><i className="fas fa-question-circle"></i> Mensagem de fallback</label>
            <textarea className="input" rows="3" value={chat.fallback} onChange={(e) => update("fallback", e.target.value)}></textarea>
            <span className="hint">Dita quando a busca semântica não encontra match.</span>
          </div>
        </div>
      </div>
    </>
  );
}

// Campo de upload de imagem com preview + botão "Trocar".
// Reusa o endpoint /api/admin/upload-avatar-video (multer aceita imagens também,
// retorna { url: 'uploads/...' }). Pra MVP é mais simples que criar endpoint novo.
function AvatarUploadField({ label, hint, value, onChange, fallback }) {
  const inputRef = useRef(null);
  const [uploading, setUploading] = useState(false);
  const toast = useToast();

  const previewSrc = value
    ? (value.startsWith('http') || value.startsWith('/') ? value : '/' + value)
    : (fallback || null);

  const onPick = () => inputRef.current && inputRef.current.click();
  const onFile = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    if (!file.type.startsWith('image/')) {
      toast({ title: 'Arquivo inválido', msg: 'Selecione uma imagem (PNG, JPG, WebP).', kind: 'error' });
      return;
    }
    const fd = new FormData();
    fd.append('file', file);
    setUploading(true);
    try {
      const r = await fetch('/api/admin/upload-avatar-video', {
        method: 'POST',
        body: fd,
        headers: { Authorization: 'Bearer ' + (Auth && Auth.token ? Auth.token : '') },
      });
      const data = await r.json();
      if (!r.ok || !data.url) throw new Error(data.error || 'Falha no upload');
      onChange(data.url);
      toast({ title: 'Imagem enviada', msg: 'Lembre de clicar em Salvar.', kind: 'success' });
    } catch (err) {
      toast({ title: 'Falha no upload', msg: err.message, kind: 'error' });
    } finally {
      setUploading(false);
      if (inputRef.current) inputRef.current.value = '';
    }
  };

  return (
    <div className="field" style={{ flex: 1 }}>
      <label>{label}</label>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <div style={{
          width: 56, height: 56, borderRadius: '50%',
          background: 'var(--bg2)', border: '1px solid var(--b1)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          overflow: 'hidden', flexShrink: 0,
        }}>
          {previewSrc ? (
            <img src={previewSrc} alt="" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
          ) : (
            <i className="fas fa-user" style={{ color: 'var(--t3)', fontSize: 18 }}></i>
          )}
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <button
            type="button"
            className="btn btn-soft btn-sm"
            onClick={onPick}
            disabled={uploading}
            style={{ marginRight: 8 }}
          >
            <i className={'fas ' + (uploading ? 'fa-spinner fa-spin' : 'fa-upload')}></i>{' '}
            {uploading ? 'Enviando...' : 'Trocar imagem'}
          </button>
          {value && (
            <button
              type="button"
              className="btn btn-ghost btn-sm"
              onClick={() => onChange('')}
              disabled={uploading}
              title="Remover imagem"
            >
              <i className="fas fa-trash"></i>
            </button>
          )}
          <div style={{ fontSize: 11, color: 'var(--t3)', marginTop: 4 }}>{hint}</div>
        </div>
        <input
          ref={inputRef}
          type="file"
          accept="image/*"
          style={{ display: 'none' }}
          onChange={onFile}
        />
      </div>
    </div>
  );
}

// MediaCard — card de upload de imagem OU vídeo do widget.
// Props:
//   - label, hint: textos do card
//   - value: caminho atual (ex: "uploads/mascot.png" ou URL completa)
//   - onChange(newValue): callback ao trocar/remover (atualiza state do chat)
//   - kind: "image" | "video" → define accept do input e preview
// Reusa o endpoint /api/admin/upload-avatar-video (multer aceita img + vídeo).
function MediaCard({ label, hint, value, onChange, kind }) {
  const inputRef = useRef(null);
  const [uploading, setUploading] = useState(false);
  const toast = useToast();

  const accept = kind === "video" ? "video/mp4,video/*" : "image/*";
  const previewSrc = value
    ? (value.startsWith('http') || value.startsWith('/') ? value : '/' + value)
    : null;
  const fileName = value ? value.split('/').pop() : '';

  const onPick = () => inputRef.current && inputRef.current.click();
  const onFile = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    if (kind === "video" && !file.type.startsWith('video/')) {
      toast({ title: 'Arquivo inválido', msg: 'Selecione um vídeo MP4.', kind: 'error' });
      return;
    }
    if (kind === "image" && !file.type.startsWith('image/')) {
      toast({ title: 'Arquivo inválido', msg: 'Selecione uma imagem (PNG, JPG, WebP).', kind: 'error' });
      return;
    }
    const fd = new FormData();
    fd.append('file', file);
    setUploading(true);
    try {
      const r = await fetch('/api/admin/upload-avatar-video', {
        method: 'POST',
        body: fd,
        headers: { Authorization: 'Bearer ' + (Auth && Auth.token ? Auth.token : '') },
      });
      const data = await r.json();
      if (!r.ok || !data.url) throw new Error(data.error || 'Falha no upload');
      onChange(data.url);
      toast({ title: 'Arquivo enviado', msg: 'Lembre de clicar em Salvar.', kind: 'success' });
    } catch (err) {
      toast({ title: 'Falha no upload', msg: err.message, kind: 'error' });
    } finally {
      setUploading(false);
      if (inputRef.current) inputRef.current.value = '';
    }
  };

  return (
    <div className="media-card">
      <div className="media-prev" style={{ background: 'var(--bg2)', overflow: 'hidden' }}>
        {previewSrc ? (
          kind === "video" ? (
            <video
              src={previewSrc}
              muted
              loop
              playsInline
              autoPlay
              style={{ width: '100%', height: '100%', objectFit: 'cover' }}
            />
          ) : (
            <img
              src={previewSrc}
              alt={label}
              style={{ width: '100%', height: '100%', objectFit: 'contain' }}
            />
          )
        ) : (
          <div className="ph">
            <i className={"fas " + (kind === "video" ? "fa-film" : "fa-image")}></i>
            <span>{kind === "video" ? "MP4 · loop" : "PNG · 512×512"}</span>
          </div>
        )}
      </div>
      <div className="media-info">
        <div className="mt">{label}</div>
        <div className="ms">{hint}</div>
        <div className="mf" title={value || '(sem arquivo)'}>
          <i className="fas fa-paperclip" style={{ marginRight: 4 }}></i>
          {fileName || <em style={{ color: 'var(--t3)' }}>nenhum arquivo</em>}
        </div>
      </div>
      <div className="media-foot">
        <button
          type="button"
          className="btn btn-soft btn-sm"
          style={{ flex: 1 }}
          onClick={onPick}
          disabled={uploading}
        >
          <i className={'fas ' + (uploading ? 'fa-spinner fa-spin' : 'fa-upload')}></i>{' '}
          {uploading ? 'Enviando…' : 'Trocar'}
        </button>
        <button
          type="button"
          className="btn btn-ghost btn-sm btn-icon"
          onClick={() => onChange('')}
          disabled={uploading || !value}
          title={value ? 'Remover arquivo' : 'Nada pra remover'}
        >
          <i className="fas fa-trash"></i>
        </button>
        <input
          ref={inputRef}
          type="file"
          accept={accept}
          style={{ display: 'none' }}
          onChange={onFile}
        />
      </div>
    </div>
  );
}

// ---------- Prompt pane ----------
function PromptPane({ value, onChange }) {
  const tokens = value.length;
  const wordCount = value.split(/\s+/).filter(Boolean).length;
  const [showVars, setShowVars] = useState(false);
  const [showVersions, setShowVersions] = useState(false);
  return (
    <>
      <div className="card" style={{ background: "linear-gradient(135deg, var(--og) 0%, transparent 60%)" }}>
        <div style={{ display: "flex", gap: 14, alignItems: "flex-start" }}>
          <div style={{
            width: 36, height: 36, borderRadius: 8, background: "var(--or)", color: "#fff",
            display: "grid", placeItems: "center", fontSize: 14, flexShrink: 0,
          }}>
            <i className="fas fa-lightbulb"></i>
          </div>
          <div>
            <div style={{ fontWeight: 600, fontSize: 14, marginBottom: 4 }}>System prompt define como a IA pensa</div>
            <div style={{ fontSize: 12.5, color: "var(--t2)", lineHeight: 1.55 }}>
              Use <code style={{ background: "var(--bg2)", padding: "1px 6px", borderRadius: 4, fontSize: 11 }}>{`{{voice_tone}}`}</code>, <code style={{ background: "var(--bg2)", padding: "1px 6px", borderRadius: 4, fontSize: 11 }}>{`{{current_date}}`}</code> e <code style={{ background: "var(--bg2)", padding: "1px 6px", borderRadius: 4, fontSize: 11 }}>{`{{contexts}}`}</code> para inserir valores dinâmicos. Inicie sempre com regras de comportamento antes de fontes.
            </div>
          </div>
        </div>
      </div>

      <div className="card flush">
        <div className="editor-wrap" style={{ border: "none", borderRadius: "var(--r-card)" }}>
          <div className="editor-toolbar">
            <span className="dot"></span>
            <span className="name">system_prompt.md</span>
            <span style={{ color: "var(--t3)" }}>·</span>
            <span style={{ color: "var(--t3)" }}>{wordCount} palavras · ~{Math.round(tokens / 4)} tokens</span>
            <div className="right">
              <button type="button" className="btn btn-ghost btn-sm" onClick={() => setShowVersions(true)}>
                <i className="fas fa-history"></i> Versões
              </button>
              <button type="button" className="btn btn-ghost btn-sm" onClick={() => setShowVars(true)}>
                <i className="fas fa-code"></i> Variáveis
              </button>
            </div>
          </div>
          <div className="editor">
            <textarea
              value={value}
              onChange={(e) => onChange(e.target.value)}
              spellCheck="false"
              style={{ minHeight: 520 }}
            ></textarea>
          </div>
        </div>
      </div>

      {showVars && <VariablesModal onClose={() => setShowVars(false)} onInsert={(v) => { onChange(value + v); setShowVars(false); }} />}
      {showVersions && <VersionsModal onClose={() => setShowVersions(false)} />}
    </>
  );
}

// ---- Variables reference modal ----
function VariablesModal({ onClose, onInsert }) {
  const vars = [
    { v: '{{voice_tone}}', d: 'Tom de voz ativo (amigavel, formal, consultivo…). Definido na aba Persona & Voz.' },
    { v: '{{current_date}}', d: 'Data atual em pt-BR (ex.: 16 de maio de 2026). Substituída a cada requisição.' },
    { v: '{{contexts}}', d: 'Bloco com todos os contextos diretos relevantes para a pergunta atual.' },
    { v: '{{user_message}}', d: 'Mensagem original do usuário (antes do query refinement).' },
    { v: '{{refined_query}}', d: 'Versão reescrita da pergunta usada para retrieval (pós-resolução de pronomes).' },
    { v: '{{retrieved_chunks}}', d: 'Trechos recuperados do RAG (já filtrados pelo reranker).' },
    { v: '{{session_history}}', d: 'Últimas N mensagens da conversa atual, para manter contexto.' },
  ];
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3><i className="fas fa-code"></i> Variáveis disponíveis</h3>
          <button type="button" className="icon-btn" onClick={onClose}><i className="fas fa-times"></i></button>
        </div>
        <div className="modal-body">
          <p style={{ margin: 0, fontSize: 12.5, color: 'var(--t2)' }}>
            Tokens entre <code style={{ background: 'var(--bg3)', padding: '1px 5px', borderRadius: 4 }}>{`{{...}}`}</code> são substituídos antes do prompt ser enviado ao LLM. Clique para inserir no editor.
          </p>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {vars.map((x) => (
              <button
                key={x.v}
                type="button"
                onClick={() => onInsert(' ' + x.v)}
                style={{
                  textAlign: 'left',
                  padding: '12px 14px',
                  background: 'var(--bg1)',
                  border: '1px solid var(--b1)',
                  borderRadius: 'var(--r-input)',
                  cursor: 'pointer',
                  display: 'flex', flexDirection: 'column', gap: 4,
                }}
              >
                <code style={{ color: 'var(--or)', fontWeight: 600, fontSize: 13 }}>{x.v}</code>
                <span style={{ fontSize: 12, color: 'var(--t2)', lineHeight: 1.4 }}>{x.d}</span>
              </button>
            ))}
          </div>
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-ghost" onClick={onClose}>Fechar</button>
        </div>
      </div>
    </div>
  );
}

// ---- Versions placeholder modal ----
function VersionsModal({ onClose }) {
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h3><i className="fas fa-history"></i> Versões do prompt</h3>
          <button type="button" className="icon-btn" onClick={onClose}><i className="fas fa-times"></i></button>
        </div>
        <div className="modal-body">
          <div className="empty" style={{ padding: '24px 0' }}>
            <i className="fas fa-clock-rotate-left"></i>
            <p><strong>Histórico de versões em breve.</strong></p>
            <p style={{ fontSize: 12, color: 'var(--t3)' }}>
              Cada salvamento criará uma versão com timestamp + autor.<br />
              Você poderá comparar e restaurar versões anteriores deste prompt.
            </p>
          </div>
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-ghost" onClick={onClose}>Entendi</button>
        </div>
      </div>
    </div>
  );
}

// ---------- Handoff pane ----------
function HandoffPane({ onAction }) {
  const toast = useToast();
  const confirm = useConfirm();
  const [redirects, setRedirects] = useState(Data.redirects);
  const [editing, setEditing] = useState(null); // null = fechado; {} = criar; {id, ...} = editar

  const reload = async () => {
    await DataLoader.redirects();
    setRedirects([...Data.redirects]);
  };

  useEffect(() => {
    let alive = true;
    DataLoader.redirects().then(() => { if (alive) setRedirects([...Data.redirects]); });
    return () => { alive = false; };
  }, []);

  const channelIcon = { whatsapp: "fab fa-whatsapp", phone: "fas fa-phone", email: "fas fa-envelope", rdstation: "fas fa-broadcast-tower", link: "fas fa-link" };
  const channelClass = { whatsapp: "b-gr", phone: "b-bl", email: "b-or", rdstation: "b-am", link: "b-mut" };

  const onDelete = async (r) => {
    const ok = await confirm({
      title: "Remover canal?",
      message: `O canal "${r.label}" será apagado permanentemente. Essa ação não pode ser desfeita.`,
      confirmLabel: "Remover",
      danger: true,
    });
    if (!ok) return;
    try {
      await api(`/api/admin/support-redirects/${r.id}`, { method: 'DELETE' });
      toast({ title: "Canal removido", kind: "success" });
      reload();
    } catch (e) {
      toast({ title: "Falha ao remover", msg: e.message, kind: "error" });
    }
  };

  const onToggleEnabled = async (r) => {
    try {
      await api(`/api/admin/support-redirects/${r.id}`, {
        method: 'PATCH',
        body: { enabled: !r.enabled },
      });
      reload();
    } catch (e) {
      toast({ title: "Falha ao atualizar status", msg: e.message, kind: "error" });
    }
  };

  return (
    <>
    <div className="card">
      <div className="card-header">
        <h3><i className="fas fa-headset"></i> Canais de atendimento humano</h3>
        <div className="row gap-sm">
          <span className="meta">Oferecidos quando a IA cai em fallback ou usuário pede.</span>
          <button
            className="btn btn-primary btn-sm"
            onClick={() => setEditing({ channel: 'whatsapp', label: '', url: '', sort_order: 100, enabled: true })}
          >
            <i className="fas fa-plus"></i> Adicionar canal
          </button>
        </div>
      </div>

      {redirects.length === 0 ? (
        <div style={{ padding: 30, textAlign: 'center', color: 'var(--t3)' }}>
          <i className="fas fa-inbox" style={{ fontSize: 28, marginBottom: 10 }}></i>
          <h4 style={{ margin: '0 0 6px', fontSize: 14, color: 'var(--t2)' }}>Nenhum canal cadastrado</h4>
          <p style={{ fontSize: 12, margin: 0 }}>
            Clique em <strong>Adicionar canal</strong> pra criar o primeiro (WhatsApp, telefone, e-mail…).
          </p>
        </div>
      ) : (
      <div className="table-wrap">
        <table className="dt">
          <thead>
            <tr>
              <th>Canal</th>
              <th>Rótulo</th>
              <th>URL</th>
              <th style={{ width: 80 }}>Ordem</th>
              <th style={{ width: 90 }}>Status</th>
              <th style={{ width: 110, textAlign: "right" }}>Ações</th>
            </tr>
          </thead>
          <tbody>
            {redirects.map((r) => (
              <tr key={r.id}>
                <td>
                  <span className={"badge " + (channelClass[r.channel] || 'b-mut')}>
                    <i className={channelIcon[r.channel] || 'fas fa-link'}></i> {r.channel}
                  </span>
                </td>
                <td>{r.label}</td>
                <td><code style={{ fontSize: 11, color: "var(--t2)", wordBreak: 'break-all' }}>{r.url}</code></td>
                <td><code style={{ fontFamily: "var(--ff-mono)", fontSize: 12 }}>{r.sort}</code></td>
                <td>
                  <button
                    type="button"
                    className="icon-btn"
                    onClick={() => onToggleEnabled(r)}
                    title={r.enabled ? "Clique pra desativar" : "Clique pra ativar"}
                    style={{ padding: 0 }}
                  >
                    <StatusBadge status={r.enabled ? "enabled" : "disabled"} />
                  </button>
                </td>
                <td>
                  <div className="row-actions">
                    <button
                      type="button"
                      className="icon-btn"
                      onClick={() => setEditing({ ...r, sort_order: r.sort })}
                      title="Editar canal"
                    >
                      <i className="fas fa-edit"></i>
                    </button>
                    <button
                      type="button"
                      className="icon-btn"
                      style={{ color: "var(--rd)" }}
                      onClick={() => onDelete(r)}
                      title="Remover canal"
                    >
                      <i className="fas fa-trash"></i>
                    </button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      )}
    </div>

    {editing && (
      <HandoffEditModal
        initial={editing}
        onClose={() => setEditing(null)}
        onSaved={() => { setEditing(null); reload(); }}
      />
    )}
    </>
  );
}

// Modal de criação/edição de canal de suporte. Usado pelo HandoffPane pra
// substituir o SimpleModal genérico — assim conseguimos refetch da lista
// quando salva, sem depender de prop drilling pelo handleAction global.
function HandoffEditModal({ initial, onClose, onSaved }) {
  const toast = useToast();
  const isEdit = !!initial.id;
  const [vals, setVals] = useState({
    channel: initial.channel || 'whatsapp',
    label: initial.label || '',
    url: initial.url || '',
    sort_order: typeof initial.sort_order === 'number' ? initial.sort_order : 100,
    enabled: initial.enabled !== false,
  });
  const [busy, setBusy] = useState(false);
  const setV = (k, v) => setVals((s) => ({ ...s, [k]: v }));

  const placeholderByChannel = {
    whatsapp:  'https://wa.me/5511999999999',
    phone:     'tel:+5511999999999',
    email:     'mailto:contato@sintracon.org.br',
    rdstation: 'https://...rdstation.com.br/...',
    link:      'https://...',
  };
  const labelHintByChannel = {
    whatsapp:  'Falar pelo WhatsApp',
    phone:     'Ligar para o SINTRACON',
    email:     'Enviar e-mail',
    rdstation: 'Atendimento RD Station',
    link:      'Falar pela Central',
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    if (!vals.label.trim() || !vals.url.trim()) {
      toast({ title: 'Preencha rótulo e URL', kind: 'info' });
      return;
    }
    setBusy(true);
    try {
      if (isEdit) {
        await api(`/api/admin/support-redirects/${initial.id}`, {
          method: 'PATCH',
          body: {
            channel: vals.channel,
            label: vals.label.trim(),
            url: vals.url.trim(),
            sort_order: parseInt(vals.sort_order, 10) || 100,
            enabled: vals.enabled,
          },
        });
        toast({ title: 'Canal atualizado', kind: 'success' });
      } else {
        await api('/api/admin/support-redirects', {
          method: 'POST',
          body: {
            channel: vals.channel,
            label: vals.label.trim(),
            url: vals.url.trim(),
            sort_order: parseInt(vals.sort_order, 10) || 100,
            enabled: vals.enabled,
          },
        });
        toast({ title: 'Canal adicionado', kind: 'success' });
      }
      onSaved();
    } catch (err) {
      toast({ title: 'Falha ao salvar', msg: err.message, kind: 'error' });
      setBusy(false);
    }
  };

  return (
    <div className="modal-overlay" onClick={onClose}>
      <form className="modal" onClick={(e) => e.stopPropagation()} onSubmit={onSubmit}>
        <div className="modal-head">
          <h3>
            <i className="fas fa-headset"></i>{' '}
            {isEdit ? 'Editar canal de atendimento' : 'Novo canal de atendimento'}
          </h3>
          <button type="button" className="icon-btn" onClick={onClose}><i className="fas fa-times"></i></button>
        </div>
        <div className="modal-body">
          <div className="field">
            <label>Tipo</label>
            <select className="input" value={vals.channel} onChange={(e) => setV('channel', e.target.value)}>
              <option value="whatsapp">WhatsApp</option>
              <option value="phone">Telefone</option>
              <option value="email">E-mail</option>
              <option value="rdstation">RD Station</option>
              <option value="link">Link (outro)</option>
            </select>
          </div>
          <div className="field">
            <label>Rótulo (texto do botão)</label>
            <input
              className="input"
              value={vals.label}
              onChange={(e) => setV('label', e.target.value)}
              placeholder={labelHintByChannel[vals.channel] || 'Ex: Falar pelo WhatsApp'}
              maxLength={120}
            />
          </div>
          <div className="field">
            <label>URL</label>
            <input
              className="input"
              value={vals.url}
              onChange={(e) => setV('url', e.target.value)}
              placeholder={placeholderByChannel[vals.channel] || 'https://...'}
            />
            <span className="hint">
              WhatsApp: <code>wa.me/55DDDNUMERO</code> · Telefone: <code>tel:+55...</code> · E-mail: <code>mailto:...</code>
            </span>
          </div>
          <div className="form-row">
            <div className="field" style={{ flex: 1 }}>
              <label>Ordem de exibição</label>
              <input
                type="number"
                className="input"
                value={vals.sort_order}
                onChange={(e) => setV('sort_order', e.target.value)}
                min={0}
                max={9999}
              />
              <span className="hint">Menor número = aparece antes.</span>
            </div>
            <div className="field" style={{ flex: 1 }}>
              <label>Status</label>
              <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '6px 0' }}>
                <Switch on={vals.enabled} onChange={(v) => setV('enabled', v)} />
                <span style={{ fontSize: 12, color: 'var(--t2)' }}>
                  {vals.enabled ? 'Ativo — aparece pro usuário' : 'Desativado — não aparece'}
                </span>
              </label>
            </div>
          </div>
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-soft" onClick={onClose} disabled={busy}>Cancelar</button>
          <button type="submit" className="btn btn-primary" disabled={busy}>
            {busy
              ? <><i className="fas fa-circle-notch fa-spin"></i> Salvando…</>
              : <><i className="fas fa-save"></i> {isEdit ? 'Salvar alterações' : 'Adicionar canal'}</>}
          </button>
        </div>
      </form>
    </div>
  );
}

window.ScreenChatbot = ScreenChatbot;
