// Teólogo: chat com /api/teologo (Claude + skill teologo-catolico-biblico), resposta em streaming.

const CHAT_KEY = (ctx) => `perseveranca.chat.${ctx || "geral"}`;
const CHAT_KEEP = 12;
const MAX_PERGUNTA = 800;

function escapeHtml(text) {
  return text.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
}

function inlineMd(text) {
  return escapeHtml(text)
    .replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
    .replace(/(^|[^*])\*(?!\s)(.+?)\*(?!\*)/g, "$1<em>$2</em>");
}

// Markdown mínimo e seguro: tudo é escapado antes de virar HTML.
function renderMd(text) {
  const blocks = [];
  let list = null;
  let quote = null;
  let para = [];
  const flushPara = () => {
    if (para.length) blocks.push(`<p>${para.map(inlineMd).join("<br>")}</p>`);
    para = [];
  };
  const flushList = () => {
    if (list) blocks.push(`<ul>${list.map((i) => `<li>${inlineMd(i)}</li>`).join("")}</ul>`);
    list = null;
  };
  const flushQuote = () => {
    if (quote) blocks.push(`<blockquote>${quote.map(inlineMd).join("<br>")}</blockquote>`);
    quote = null;
  };
  for (const raw of text.split("\n")) {
    const line = raw.trimEnd();
    if (!line.trim()) {
      flushPara();
      flushList();
      flushQuote();
      continue;
    }
    if (/^\s*>\s?/.test(line)) {
      flushPara();
      flushList();
      (quote = quote || []).push(line.replace(/^\s*>\s?/, ""));
      continue;
    }
    if (/^\s*[-*•]\s+/.test(line)) {
      flushPara();
      flushQuote();
      (list = list || []).push(line.replace(/^\s*[-*•]\s+/, ""));
      continue;
    }
    if (/^#{1,6}\s/.test(line)) {
      flushPara();
      flushList();
      flushQuote();
      blocks.push(`<p><strong>${inlineMd(line.replace(/^#{1,6}\s/, ""))}</strong></p>`);
      continue;
    }
    flushList();
    flushQuote();
    para.push(line);
  }
  flushPara();
  flushList();
  flushQuote();
  return blocks.join("");
}

async function askTeologo({ modulo, messages, onDelta, signal }) {
  const response = await fetch("api/teologo", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ modulo: modulo || null, messages }),
    signal,
  });
  if (!response.ok) {
    let msg = "O tira-dúvidas não está disponível agora.";
    try {
      msg = (await response.json()).error || msg;
    } catch (error) {
      // resposta sem JSON: mantém a mensagem padrão
    }
    throw new Error(msg);
  }
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";
  for (;;) {
    const { value, done } = await reader.read();
    if (done) break;
    buffer += decoder.decode(value, { stream: true });
    const events = buffer.split("\n\n");
    buffer = events.pop();
    for (const event of events) {
      const line = event.split("\n").find((l) => l.startsWith("data: "));
      if (!line) continue;
      const payload = JSON.parse(line.slice(6));
      if (payload.error) throw new Error(payload.error);
      if (payload.t) onDelta(payload.t);
    }
  }
}

function useOnline() {
  const [online, setOnline] = React.useState(() => navigator.onLine !== false);
  React.useEffect(() => {
    const on = () => setOnline(true);
    const off = () => setOnline(false);
    window.addEventListener("online", on);
    window.addEventListener("offline", off);
    return () => {
      window.removeEventListener("online", on);
      window.removeEventListener("offline", off);
    };
  }, []);
  return online;
}

function TeologoChat({ modulo, titulo, seed, onSeedUsed, padded = true }) {
  const [messages, setMessages] = React.useState(() => readStorage(CHAT_KEY(modulo), []));
  const [input, setInput] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState(null);
  const online = useOnline();
  const scrollRef = React.useRef(null);
  const inputRef = React.useRef(null);
  const abortRef = React.useRef(null);

  React.useEffect(() => {
    setMessages(readStorage(CHAT_KEY(modulo), []));
    setError(null);
    return () => abortRef.current && abortRef.current.abort();
  }, [modulo]);

  React.useEffect(() => {
    if (!seed) return;
    setInput(seed);
    onSeedUsed && onSeedUsed();
    window.setTimeout(() => inputRef.current && inputRef.current.focus(), 50);
  }, [seed]);

  React.useEffect(() => {
    const el = scrollRef.current;
    if (el) el.scrollTop = el.scrollHeight;
  }, [messages, busy]);

  const persist = (list) => writeStorage(CHAT_KEY(modulo), list.slice(-CHAT_KEEP));

  const send = async (text) => {
    const pergunta = (text ?? input).trim().slice(0, MAX_PERGUNTA);
    if (!pergunta || busy) return;
    setError(null);
    setInput("");
    const history = [...messages, { role: "user", content: pergunta }];
    setMessages([...history, { role: "assistant", content: "" }]);
    setBusy(true);
    const controller = new AbortController();
    abortRef.current = controller;
    let answer = "";
    try {
      await askTeologo({
        modulo,
        messages: history.slice(-8),
        signal: controller.signal,
        onDelta: (delta) => {
          answer += delta;
          setMessages([...history, { role: "assistant", content: answer }]);
        },
      });
      if (!answer.trim()) throw new Error("Não foi possível responder a essa pergunta. Tente reformular.");
      const final = [...history, { role: "assistant", content: answer }];
      setMessages(final);
      persist(final);
    } catch (err) {
      if (err.name === "AbortError") return;
      setMessages(history.slice(0, -1));
      setInput(pergunta);
      setError(
        err instanceof TypeError
          ? "Sem conexão com a internet. O tira-dúvidas precisa de rede; o material segue disponível."
          : err.message || "Não foi possível responder agora."
      );
    } finally {
      setBusy(false);
    }
  };

  const limpar = () => {
    setMessages([]);
    persist([]);
  };

  return (
    <div className="flex flex-col h-full min-h-0">
      <div ref={scrollRef} className={`flex-1 min-h-0 overflow-y-auto ${padded ? "px-5" : "px-1"} pt-4 pb-4`}>
        {!messages.length && (
          <div className="fade-in">
            <div className="rounded-[24px] silk-gradient p-5 text-on-primary relative overflow-hidden">
              <div
                className="absolute -top-16 -right-16 w-56 h-56 rounded-full pointer-events-none"
                style={{ background: "radial-gradient(circle, rgba(237,200,119,0.28) 0%, transparent 60%)" }}
              />
              <div className="font-label text-[10px] uppercase tracking-[0.25em] font-bold text-secondary-fixed-dim">
                Tira-dúvidas
              </div>
              <div className="font-headline text-[22px] leading-tight mt-2">
                {titulo ? `Dúvidas sobre ${titulo}?` : "Dúvidas de fé, Bíblia ou doutrina?"}
              </div>
              <p className="text-[13px] leading-relaxed mt-2 opacity-85">
                Respostas simples, fiéis à Igreja e sempre com uma passagem bíblica.
              </p>
            </div>
          </div>
        )}

        {messages.map((m, i) =>
          m.role === "user" ? (
            <div key={i} className="flex justify-end mb-3">
              <div className="max-w-[85%] rounded-2xl rounded-br-md silk-gradient text-on-primary px-4 py-2.5 text-[14.5px] leading-relaxed whitespace-pre-wrap">
                {m.content}
              </div>
            </div>
          ) : (
            <div key={i} className="mb-4">
              <div className="rounded-2xl rounded-bl-md bg-surface-container-lowest ambient px-4 py-3 text-[14.5px] leading-relaxed text-on-surface">
                {m.content ? (
                  <div className="md" dangerouslySetInnerHTML={{ __html: renderMd(m.content) }} />
                ) : (
                  <div className="dot-pulse text-on-surface-variant">
                    Consultando<span>.</span><span>.</span><span>.</span>
                  </div>
                )}
              </div>
            </div>
          )
        )}

        {error && (
          <div className="rounded-2xl px-4 py-3 text-[13px] mb-3" style={{ background: "#F6E2DC", color: "#7A2E1B" }}>
            {error}
          </div>
        )}
      </div>

      <div className={`${padded ? "px-4" : "px-0"} pt-2 pb-3 shrink-0`}>
        {!online && (
          <div className="flex items-center gap-2 text-[12px] text-on-surface-variant mb-2 px-1">
            <Icon name="wifi_off" style={{ fontSize: 16 }} />
            O tira-dúvidas precisa de internet. O material segue disponível offline.
          </div>
        )}
        <div className="flex items-end gap-2 rounded-[22px] bg-surface-container-lowest ambient px-3 py-2">
          <textarea
            ref={inputRef}
            value={input}
            onChange={(e) => setInput(e.target.value.slice(0, MAX_PERGUNTA))}
            onKeyDown={(e) => {
              if (e.key === "Enter" && !e.shiftKey) {
                e.preventDefault();
                send();
              }
            }}
            rows={1}
            placeholder={online ? "Escreva sua pergunta…" : "Sem internet"}
            disabled={!online}
            className="flex-1 resize-none border-0 bg-transparent focus:ring-0 text-[15px] leading-snug py-2 px-1 max-h-32"
            aria-label="Sua dúvida"
          />
          <button
            onClick={() => send()}
            disabled={!online || busy || !input.trim()}
            aria-label="Enviar pergunta"
            className="w-10 h-10 rounded-full silk-gradient text-on-primary flex items-center justify-center shrink-0 disabled:opacity-40 active:scale-95 transition-transform"
          >
            <Icon name="send" style={{ fontSize: 19 }} />
          </button>
        </div>
        <div className="flex items-center justify-between mt-2 px-1 text-[10.5px] text-outline">
          <span>Respostas geradas por IA. Para casos pessoais, converse com um padre.</span>
          {messages.length > 0 && !busy && (
            <button onClick={limpar} className="font-bold text-on-surface-variant shrink-0 ml-2">
              Limpar
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { TeologoChat, renderMd });
