// Chat survey: conversational flow powered by Claude Sonnet (latest) via
// our /api/chat proxy. The model returns a reply plus structured signals
// that map free text to specific survey questions with a confidence score.
const ChatSurvey = (function () {

  function ConfPill({ confidence }) {
    const c = confidence >= 0.8 ? "high" : confidence >= 0.65 ? "med" : "low";
    const label = Math.round(confidence * 100) + "%";
    return <span className={"conf conf-" + c}>{label}</span>;
  }

  function SignalPill({ signal, onClick }) {
    const c = signal.confidence >= 0.8 ? "high" : signal.confidence >= 0.65 ? "med" : "low";
    const valLabel = signal.cell
      ? signal.cell.tool.split(" (")[0] + " · " + signal.cell.col + " = " + signal.value
      : (signal.value || "").toString().slice(0, 60);
    const q = window.SURVEY_FLAT.find(q => q.id === signal.questionId);
    return (
      <button className="signal-pill" onClick={onClick} title={"→ " + (q?.prompt || signal.questionId) + (signal.evidence ? '\nEvidence: "' + signal.evidence + '"' : '')}>
        <span className={"dot dot-" + c}></span>
        <span className="qid">{signal.questionId.toUpperCase()}</span>
        <span className="val">{valLabel}</span>
        <span className={"conf conf-" + c}>{Math.round(signal.confidence * 100)}%</span>
      </button>
    );
  }

  function Bubble({ from, children, signals, onSignalClick, offTopic }) {
    return (
      <div className={"bubble-row " + from}>
        {from === "bot" && <div className="bubble-avatar bot">AI</div>}
        <div className={"bubble " + from}>
          {children}
          {offTopic && (
            <div style={{marginTop:8,fontSize:11,color:"var(--muted)",fontStyle:"italic"}}>
              ↺ Steering us back to the survey.
            </div>
          )}
          {signals && signals.length > 0 && (
            <div className="signal-banner">
              <div style={{fontSize:12,color:"var(--ink-2)",fontWeight:500}}>
                ✦ I picked up signal for {signals.length === 1 ? "1 question" : signals.length + " questions"}:
              </div>
              <div style={{display:"flex",flexWrap:"wrap",gap:6}}>
                {signals.map((s, i) => (
                  <SignalPill key={i} signal={s} onClick={() => onSignalClick(s)} />
                ))}
              </div>
              <div style={{fontSize:11,color:"var(--muted)",marginTop:2}}>
                Tap a tag to see the question it filled. You'll review everything at the end.
              </div>
            </div>
          )}
        </div>
      </div>
    );
  }

  function AnswerCard({ q, answer, justAdded, confidence }) {
    const c = confidence ? (confidence >= 0.8 ? "conf-high" : confidence >= 0.65 ? "conf-med" : "conf-low") : null;
    let display;
    if (q.type === "multi") {
      const opts = answer?.options || [];
      display = opts.length === 0 && !answer?.other ? "—" : (
        <div>
          {opts.map((o,i) => <span key={i} className="tag">{o}</span>)}
          {answer?.other && <span className="tag">+ {answer.other}</span>}
        </div>
      );
    } else if (q.type === "table") {
      const cells = Object.entries(answer || {});
      display = cells.length === 0 ? "—" : (
        <div>{cells.slice(0,3).map(([k,v],i) => {
          const [tool,col] = k.split("::");
          return <span key={i} className="tag">{tool.split(" (")[0]}: {v}</span>;
        })}{cells.length > 3 && <span className="tag">+{cells.length-3} more</span>}</div>
      );
    } else if (q.type === "longtext") {
      display = answer?.text ? '"' + answer.text.slice(0, 80) + (answer.text.length > 80 ? '…' : '') + '"' : "—";
    } else {
      display = answer?.value || "—";
    }
    return (
      <div className={"answer-card" + (justAdded ? " just-added" : "")} data-qid={q.id}>
        <div className="qid">{q.id.toUpperCase()} · {q.sectionTitle}</div>
        <div className="qprompt">{q.prompt}</div>
        <div className="answer">{display}</div>
        {c && <div className={"conf " + c}>{Math.round(confidence * 100)}%</div>}
      </div>
    );
  }

  function isAnswered(q, a) {
    if (!a) return false;
    if (q.type === "multi") return (a.options && a.options.length > 0) || !!a.other;
    if (q.type === "table") return Object.keys(a).length > 0;
    if (q.type === "longtext") return !!(a.text && a.text.trim());
    return !!(a.value || a.text);
  }

  function AnswerRail({ answers, confidences, recentlyAdded }) {
    const filledQuestions = window.SURVEY_FLAT.filter(q => isAnswered(q, answers[q.id]));
    const total = window.SURVEY_FLAT.length;
    const needsReview = filledQuestions.filter(q => (confidences[q.id] || 1) < 0.8).length;

    return (
      <aside className="answer-rail">
        <div className="head">
          <h4>Live answer sheet <span className="live">LIVE</span></h4>
          <p>Updates as the assistant picks up signal from what you say. Tap any answer to jump to its question.</p>
          <div className="stats">
            <div className="stat">
              <div className="n">{filledQuestions.length}<span style={{fontSize:14,color:"var(--muted)"}}>/{total}</span></div>
              <div className="l">Captured</div>
            </div>
            <div className="stat">
              <div className="n">{needsReview}</div>
              <div className="l">Soft signal</div>
            </div>
          </div>
        </div>
        <div className="list">
          {filledQuestions.length === 0 && (
            <div className="empty">Answers will appear here as we chat.</div>
          )}
          {filledQuestions.slice().reverse().map(q => (
            <AnswerCard key={q.id} q={q} answer={answers[q.id]} confidence={confidences[q.id]} justAdded={recentlyAdded.has(q.id)} />
          ))}
        </div>
      </aside>
    );
  }

  function applySignal(answers, signal) {
    const next = { ...answers };
    const qid = signal.questionId;
    const cur = next[qid] || {};
    if (signal.valueOp === "set") {
      next[qid] = { ...cur, value: signal.value };
      if (signal.text) next[qid].text = signal.text;
    } else if (signal.valueOp === "add") {
      const existing = cur.options || [];
      if (!existing.includes(signal.value)) {
        next[qid] = { ...cur, options: [...existing, signal.value] };
      }
    } else if (signal.valueOp === "other") {
      const existingOther = cur.other ? cur.other + ", " : "";
      if (!cur.other || !cur.other.toLowerCase().includes((signal.value || "").toLowerCase())) {
        next[qid] = { ...cur, other: existingOther + signal.value };
      }
    } else if (signal.valueOp === "setCell") {
      if (signal.cell && signal.cell.tool && signal.cell.col) {
        const key = signal.cell.tool + "::" + signal.cell.col;
        next[qid] = { ...cur, [key]: signal.value };
      }
    } else if (signal.valueOp === "setText") {
      next[qid] = { ...cur, text: signal.value };
    }
    return next;
  }

  function ChatSurvey({ user, answers, setAnswers, confidences, setConfidences, onLogout, onFinish, onSwitchMode }) {
    const [messages, setMessages] = useState([]);
    const [input, setInput] = useState("");
    const [typing, setTyping] = useState(false);
    const [recentlyAdded, setRecentlyAdded] = useState(() => new Set());
    const [surveyComplete, setSurveyComplete] = useState(false);
    const [error, setError] = useState("");
    const streamRef = useRef(null);

    // Initial greeting from the assistant — kicks the conversation off so
    // the user has somewhere to reply to before our first /api/chat call.
    useEffect(() => {
      if (messages.length === 0) {
        const firstName = (user?.name || "there").split(" ")[0];
        const greeting =
          "Hi " + firstName + " — I'm your discovery assistant. We'll cover the same ground as the standard survey, but in a conversation rather than a form. " +
          "Wherever you give me clear signal I'll auto-fill answers on the right (you can review and adjust everything before submitting). " +
          "To start: what does a typical week look like for your team — what kinds of programs and sessions are you running, and which tools do you reach for most?";
        setTimeout(() => {
          setMessages([{ id: 1, from: "bot", text: greeting }]);
        }, 300);
      }
    }, []);

    useEffect(() => {
      if (streamRef.current) {
        streamRef.current.scrollTo({ top: streamRef.current.scrollHeight, behavior: "smooth" });
      }
    }, [messages, typing]);

    async function send() {
      const text = input.trim();
      if (!text || typing) return;
      setInput("");
      setError("");

      const userMsg = { id: Date.now(), from: "user", text };
      setMessages(prev => [...prev, userMsg]);

      const history = [...messages, userMsg].map(m => ({
        role: m.from === "bot" ? "assistant" : "user",
        content: m.text,
      }));

      setTyping(true);
      let resp;
      try {
        resp = await window.api.post("/api/chat", {
          messages: history,
          answers,
          confidences,
          userName: user.name,
        });
      } catch (ex) {
        setTyping(false);
        setError(ex.message || "Chat is temporarily unavailable.");
        setMessages(prev => [...prev, {
          id: Date.now() + 1, from: "bot",
          text: "Sorry — I'm having trouble reaching the assistant. Please try again, or switch to the standard form.",
          error: true,
        }]);
        return;
      }

      const signals = Array.isArray(resp.signals) ? resp.signals : [];
      let newAnswers = answers;
      const newConfidences = { ...confidences };
      const newlyAddedQids = new Set();
      const validSignals = [];
      for (const s of signals) {
        if (!s || !s.questionId || !s.valueOp) continue;
        const c = typeof s.confidence === "number" ? Math.max(0, Math.min(1, s.confidence)) : 0.7;
        if (c < 0.55) continue; // skip very low-confidence signals
        const enriched = { ...s, confidence: c };
        newAnswers = applySignal(newAnswers, enriched);
        if (!newConfidences[s.questionId] || c > newConfidences[s.questionId]) {
          newConfidences[s.questionId] = c;
        }
        newlyAddedQids.add(s.questionId);
        validSignals.push(enriched);
      }
      setAnswers(newAnswers);
      setConfidences(newConfidences);

      setRecentlyAdded(newlyAddedQids);
      setTimeout(() => setRecentlyAdded(new Set()), 1800);

      const botMsg = {
        id: Date.now() + 1,
        from: "bot",
        text: resp.reply || "…",
        signals: validSignals,
        offTopic: !!resp.offTopic,
        final: !!resp.surveyComplete,
      };
      setMessages(prev => [...prev, botMsg]);
      if (resp.surveyComplete) setSurveyComplete(true);
      setTyping(false);
    }

    function handleSignalClick(signal) {
      const el = document.querySelector('[data-qid="' + signal.questionId + '"]');
      if (el) {
        el.scrollIntoView({ block: "center", behavior: "smooth" });
        el.classList.add("just-added");
        setTimeout(() => el.classList.remove("just-added"), 1500);
      }
    }

    const total = window.SURVEY_FLAT.length;
    const filledCount = window.SURVEY_FLAT.filter(q => isAnswered(q, answers[q.id])).length;
    const pct = Math.round((filledCount / total) * 100);

    return (
      <>
        <Topbar user={user} onLogout={onLogout} crumb="Conversational mode" />
        <div className="chat-shell">
          <div className="chat-pane">
            <div className="chat-header">
              <div className="agent-avatar">AI</div>
              <div className="who">
                <h4>Discovery Assistant</h4>
                <span>Powered by Claude Sonnet · grounded on the Wellbeing Outfit survey</span>
              </div>
              <div style={{flex:1}}></div>
              <button className="btn ghost" style={{padding:"8px 14px",fontSize:13}} onClick={onSwitchMode} title="Switch to the standard form">↺ Switch to standard form</button>
              <div className="progress-mini">
                <div className="lbl">{filledCount} of {total} captured · {pct}%</div>
                <div className="bar"><div style={{width: pct + "%"}}></div></div>
              </div>
            </div>
            <div className="chat-stream" ref={streamRef}>
              {messages.map(m => (
                <Bubble key={m.id} from={m.from} signals={m.signals} offTopic={m.offTopic} onSignalClick={handleSignalClick}>
                  {m.text}
                  {m.final && (
                    <div style={{marginTop:14}}>
                      <button className="btn primary" onClick={onFinish}>Review my answers →</button>
                    </div>
                  )}
                </Bubble>
              ))}
              {typing && (
                <div className="bubble-row bot">
                  <div className="bubble-avatar bot">AI</div>
                  <div className="bubble bot"><span className="typing"><span></span><span></span><span></span></span></div>
                </div>
              )}
            </div>
            <div className="chat-input">
              <div className="field">
                <textarea
                  rows={1}
                  value={input}
                  placeholder="Type your reply…"
                  onChange={e => {
                    setInput(e.target.value);
                    e.target.style.height = "auto";
                    e.target.style.height = Math.min(e.target.scrollHeight, 160) + "px";
                  }}
                  onKeyDown={e => {
                    if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); }
                  }}
                  disabled={typing}
                />
                <button className="send" onClick={send} disabled={!input.trim() || typing}>Send ↵</button>
              </div>
              <div className="hint">
                Press <kbd>Enter</kbd> to send · <kbd>Shift</kbd>+<kbd>Enter</kbd> for a new line · or <span style={{textDecoration:"underline",cursor:"pointer"}} onClick={onSwitchMode}>switch to the standard form</span>
                {(surveyComplete || filledCount >= Math.floor(total * 0.7)) && (
                  <span> · <button onClick={onFinish} style={{background:"none",border:"none",color:"var(--navy)",fontWeight:600,cursor:"pointer",textDecoration:"underline"}}>Review my answers</button></span>
                )}
                {error && <span style={{color:"var(--danger)",marginLeft:8}}>· {error}</span>}
              </div>
            </div>
          </div>
          <AnswerRail answers={answers} confidences={confidences} recentlyAdded={recentlyAdded} />
        </div>
      </>
    );
  }

  return ChatSurvey;
})();

window.ChatSurvey = ChatSurvey;
