// sense-check-app.jsx
// UI components and state machine.
// Visual treatment: Claude Design. Copy + data wiring: authoritative spec.
// Requires: React 18, marked.js, window.SenseCheckData (from sense-check-data.jsx).

const { useState, useEffect, useRef, useCallback } = React;
const { QUESTIONS, ackAnswer, generateReadback, generateReport, submitEmail } = window.SenseCheckData;

// ── Markdown renderer (requires marked.js in index.html) ──────────────────────
function Markdown({ text, className }) {
  if (!text) return null;
  const html = marked.parse(String(text), { breaks: true });
  return <div className={className} dangerouslySetInnerHTML={{ __html: html }} />;
}

// ── Step names ────────────────────────────────────────────────────────────────
const STEP = { INTRO: "intro", QUESTION: "question", READBACK: "readback", REPORT: "report" };

// ── Shared UI atoms ───────────────────────────────────────────────────────────
function TealDot() { return <span className="teal-dot" />; }

function Typing() {
  return <span className="sc-typing"><span /><span /><span /></span>;
}

// Progress bar — label format "1 of 6" per spec; no percentage
function Progress({ current, total, pulse }) {
  const pct = Math.round((current / total) * 100);
  return (
    <div className="sc-progress">
      <span className="sc-progress__count">{current} of {total}</span>
      <span className="sc-progress__track">
        <span
          className={`sc-progress__fill${pulse ? " pulse" : ""}`}
          style={{ width: `${pct}%` }}
        />
      </span>
    </div>
  );
}

// Sticky header bar
// TODO (Claude Code): verify logo asset path — /assets/logos/wordmark-transparent.svg
// should resolve correctly relative to the deployed site root.
function Bar({ progress, pulse }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return (
    <header className={`sc-bar${scrolled ? " scrolled" : ""}`}>
      <a href="/" className="sc-bar__brand">
        <img src="/assets/logos/wordmark-transparent.svg" alt="Brendan O'Neill" />
      </a>
      <div className="sc-bar__progress">
        {progress && (
          <Progress current={progress.current} total={progress.total} pulse={pulse} />
        )}
      </div>
      <div className="sc-bar__right" />
    </header>
  );
}

function Foot() {
  return (
    <footer className="sc-foot">
      <span>Brendan O&rsquo;Neill &mdash; Loul&eacute;, Portugal</span>
      <span><a href="/">&#8592; Back to site</a></span>
    </footer>
  );
}

// ── Intro ─────────────────────────────────────────────────────────────────────
function Intro({ onBegin }) {
  return (
    <div className="sc-step sc-intro">
      <h1 className="sc-intro__title">
        AI Sense Check<span className="dot" />
      </h1>

      <p className="sc-intro__lede">
        Six questions about your practice. A written read of where you actually are
        with AI &mdash; not a generic audit.
      </p>
      <p className="sc-intro__lede">
        Free. No login. You read the full report before we ask for your email.
      </p>

      <div className="sc-intro__meta">
        <div className="sc-intro__meta-item">
          <span className="sc-intro__meta-label">Time</span>
          <span className="sc-intro__meta-value">~8 minutes</span>
        </div>
        <div className="sc-intro__meta-item">
          <span className="sc-intro__meta-label">Cost</span>
          <span className="sc-intro__meta-value">Free</span>
        </div>
        <div className="sc-intro__meta-item">
          <span className="sc-intro__meta-label">You get</span>
          <span className="sc-intro__meta-value">A written read, not a score</span>
        </div>
      </div>

      <p style={{
        fontSize: "13px",
        lineHeight: "1.6",
        color: "var(--fg-3)",
        marginBottom: "40px",
        maxWidth: "52ch",
      }}>
        Your answers are processed by Claude (Anthropic) to generate your report.
        Don&rsquo;t share sensitive personal information or anything you wouldn&rsquo;t
        put in a professional context.{" "}
        <a href="/privacy" style={{ color: "var(--fg-3)", textDecoration: "underline" }}>
          Privacy policy
        </a>
      </p>

      <button className="sc-btn" onClick={onBegin}>
        <TealDot /> Begin <span className="arrow">&#8594;</span>
      </button>
    </div>
  );
}

// ── Question ──────────────────────────────────────────────────────────────────
// Props:
//   question        — { id, title, desc, placeholder }
//   index           — 0-based question index
//   total           — total questions (6)
//   probesRemaining — budget passed to ackAnswer so backend knows whether to probe
//   priorAnswers    — [{ title, answer }] for already-completed questions
//   onComplete      — ({ answer, probeQuestion, probeAnswer, probeUsed }) => void

function QuestionStep({ question, index, total, probesRemaining, priorAnswers, onComplete }) {
  const [answer, setAnswer] = useState("");
  // phase: answering | thinking | acked | probing | probing-thinking | done
  const [phase, setPhase] = useState("answering");
  const [ack, setAck] = useState(null);   // { acknowledgement, probe }
  const [probe, setProbe] = useState("");
  const [error, setError] = useState(null);
  const textareaRef = useRef(null);

  // Reset when question changes
  useEffect(() => {
    setAnswer("");
    setPhase("answering");
    setAck(null);
    setProbe("");
    setError(null);
    setTimeout(() => textareaRef.current?.focus(), 100);
  }, [question.id]);

  const submitAnswer = useCallback(async () => {
    if (!answer.trim()) return;
    setPhase("thinking");
    setError(null);
    try {
      const result = await ackAnswer({
        questionNumber: index + 1,
        questionTitle: question.title,
        currentAnswer: answer.trim(),
        priorAnswers,
        probesRemaining,
      });
      setAck(result);
      // Show probe only if server returned one AND budget allows
      setPhase(result.probe && probesRemaining > 0 ? "probing" : "acked");
    } catch (err) {
      setPhase("answering");
      setError(err.message || "Something went wrong. Please try again.");
    }
  }, [answer, question, index, priorAnswers, probesRemaining]);

  const submitProbe = useCallback(() => {
    if (!probe.trim()) return;
    setPhase("probing-thinking");
    setTimeout(() => setPhase("done"), 700);
  }, [probe]);

  const onKey = (e, handler) => {
    if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
      e.preventDefault();
      handler();
    }
  };

  const continueNext = () => {
    onComplete({
      answer: answer.trim(),
      probeQuestion: ack?.probe || null,
      probeAnswer: probe.trim() || null,
      probeUsed: !!(ack?.probe && probesRemaining > 0),
    });
  };

  const showProbeInput = phase === "probing" || phase === "probing-thinking";
  const showContinue  = phase === "acked" || phase === "done";

  return (
    <div className="sc-step">
      <div className="sc-eyebrow">Question {String(index + 1).padStart(2, "0")}</div>

      <h2 className="sc-q__title">{question.title}</h2>
      <p className="sc-q__desc">{question.desc}</p>

      {/* Answer input — shown while answering; replaced by echo once submitted */}
      {phase === "answering" ? (
        <>
          <textarea
            ref={textareaRef}
            className="sc-input"
            placeholder={question.placeholder || "Type your answer here\u2026"}
            value={answer}
            onChange={e => setAnswer(e.target.value)}
            onKeyDown={e => onKey(e, submitAnswer)}
          />
          {error && (
            <p style={{ fontSize: "13px", color: "#c00", marginTop: "8px" }}>{error}</p>
          )}
          <div className="sc-q__foot">
            <span className="sc-q__hint sc-q__hint--desktop">
              <kbd>&#8984;</kbd><kbd>&#9166;</kbd> to submit
            </span>
            <button
              className="sc-btn"
              onClick={submitAnswer}
              disabled={answer.trim().length < 10}
            >
              Continue <span className="arrow">&#8594;</span>
            </button>
          </div>
        </>
      ) : (
        <div className="sc-answer">{answer}</div>
      )}

      {/* Loading state while getting acknowledgement */}
      {phase === "thinking" && (
        <div className="sc-ack">
          <div className="sc-ack__label"><TealDot /> Reading</div>
          <Typing />
        </div>
      )}

      {/* Acknowledgement — no label above it per spec; teal border via CSS */}
      {ack && (phase === "acked" || phase === "done") && (
        <div className="sc-ack">
          <p className="sc-ack__body" dangerouslySetInnerHTML={{ __html: ack.acknowledgement }} />
        </div>
      )}

      {/* Probe / follow-up */}
      {showProbeInput && ack?.probe && (
        <div className="sc-probe">
          <div className="sc-probe__label">Follow-up</div>
          <p className="sc-probe__q">{ack.probe}</p>
          {phase === "probing" ? (
            <>
              <textarea
                className="sc-input"
                placeholder="Your answer\u2026"
                value={probe}
                onChange={e => setProbe(e.target.value)}
                onKeyDown={e => onKey(e, submitProbe)}
                autoFocus
              />
              <div className="sc-q__foot">
                <span className="sc-q__hint sc-q__hint--desktop">
                  <kbd>&#8984;</kbd><kbd>&#9166;</kbd> to submit
                </span>
                <button
                  className="sc-btn"
                  onClick={submitProbe}
                  disabled={!probe.trim()}
                >
                  Continue <span className="arrow">&#8594;</span>
                </button>
              </div>
            </>
          ) : (
            <div className="sc-answer">{probe}</div>
          )}
        </div>
      )}

      {/* Thinking after probe submit */}
      {phase === "probing-thinking" && (
        <div className="sc-ack">
          <div className="sc-ack__label"><TealDot /> Thinking</div>
          <Typing />
        </div>
      )}

      {/* Advance to next question */}
      {showContinue && (
        <div className="sc-q__foot" style={{ marginTop: 40, justifyContent: "flex-end" }}>
          <button className="sc-btn" onClick={continueNext}>
            Continue <span className="arrow">&#8594;</span>
          </button>
        </div>
      )}
    </div>
  );
}

// ── Read-Back ─────────────────────────────────────────────────────────────────
// Calls generateReadback(answers) on mount.
// On confirm: passes (readBackParagraph, correctionNote) to parent.

function ReadbackStep({ answers, onConfirm }) {
  const [text, setText]           = useState(null);
  const [error, setError]         = useState(null);
  const [mode, setMode]           = useState("reading"); // reading | correcting
  const [correction, setCorrection] = useState("");
  const correctRef = useRef(null);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const t = await generateReadback(answers);
        if (!cancelled) setText(t);
      } catch (err) {
        if (!cancelled) setError(err.message || "Failed to generate read-back. Please try again.");
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const openCorrection = () => {
    setMode("correcting");
    setTimeout(() => correctRef.current?.focus(), 60);
  };

  const submitCorrection = () => {
    onConfirm(text, correction.trim() || null);
  };

  const onCorrectKey = (e) => {
    if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
      e.preventDefault();
      submitCorrection();
    }
  };

  return (
    <div className="sc-step">
      <div className="sc-readback__eyebrow">Here&rsquo;s what I heard</div>
      <h2 className="sc-readback__title">
        Here&rsquo;s what I heard.
        {!text && !error && <><br /><span className="soft">Reading your answers&hellip;</span></>}
      </h2>

      {/* Loading */}
      {!text && !error && (
        <div className="sc-readback__body"><Typing /></div>
      )}

      {/* Error */}
      {error && (
        <div className="sc-readback__body">
          <p style={{ color: "var(--fg-2)" }}>{error}</p>
          <button
            className="sc-btn sc-btn--ghost"
            style={{ marginTop: "16px" }}
            onClick={() => { setError(null); }}
          >
            Try again
          </button>
        </div>
      )}

      {/* Read-back text */}
      {text && (
        <>
          <div className="sc-readback__body">
            <p>{text}</p>
          </div>
          <p style={{ fontSize: "12px", color: "var(--fg-3)", marginBottom: "32px" }}>
            AI-generated characterisation. Not professional advice.
          </p>
        </>
      )}

      {/* Actions — reading mode */}
      {text && mode === "reading" && (
        <div className="sc-readback__actions">
          <button className="sc-btn sc-btn--ghost" onClick={openCorrection}>
            Not quite right
          </button>
          <button className="sc-btn" onClick={() => onConfirm(text, null)}>
            <TealDot /> That&rsquo;s right <span className="arrow">&#8594;</span>
          </button>
        </div>
      )}

      {/* Correction form */}
      {text && mode === "correcting" && (
        <div className="sc-correct">
          <div className="sc-correct__label">
            <span className="sc-correct__dot" />
            What I got wrong
          </div>
          <textarea
            ref={correctRef}
            className="sc-input"
            placeholder="What did I get wrong, or what&rsquo;s missing?"
            value={correction}
            onChange={e => setCorrection(e.target.value)}
            onKeyDown={onCorrectKey}
          />
          <div className="sc-readback__actions">
            <button
              className="sc-btn sc-btn--ghost"
              onClick={() => { setMode("reading"); setCorrection(""); }}
            >
              &#8592; Cancel
            </button>
            <button
              className="sc-btn"
              onClick={submitCorrection}
              disabled={!correction.trim()}
            >
              <TealDot /> Continue to report <span className="arrow">&#8594;</span>
            </button>
          </div>
          <div className="sc-correct__foot">
            <span className="sc-q__hint sc-q__hint--desktop">
              <kbd>&#8984;</kbd><kbd>&#9166;</kbd> to submit
            </span>
          </div>
        </div>
      )}
    </div>
  );
}

// ── Report ────────────────────────────────────────────────────────────────────
// Calls generateReport on mount. Renders report sections, then email capture.

function ReportStep({ answers, readBackParagraph, correctionNote }) {
  const [report, setReport]           = useState(null);
  const [reportError, setReportError] = useState(null);

  // Email capture state
  const [email, setEmail]                       = useState("");
  const [requiredConsent, setRequiredConsent]   = useState(false);
  const [marketingConsent, setMarketingConsent] = useState(false);
  const [emailSent, setEmailSent]               = useState(false);
  const [emailLoading, setEmailLoading]         = useState(false);
  const [emailError, setEmailError]             = useState(null);

  // Fetch report on mount
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const r = await generateReport({ answers, readBackParagraph, correctionNote });
        if (!cancelled) setReport(r);
      } catch (err) {
        if (!cancelled) setReportError(err.message || "Report generation failed.");
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const onEmailSubmit = async (e) => {
    e.preventDefault();
    if (!requiredConsent) return;
    setEmailLoading(true);
    setEmailError(null);
    try {
      await submitEmail({ email, marketingConsent, reportSnapshot: report });
      setEmailSent(true);
    } catch (err) {
      setEmailError(err.message || "Email send failed. Please try again.");
    } finally {
      setEmailLoading(false);
    }
  };

  // Loading state
  if (!report && !reportError) {
    return (
      <div className="sc-step">
        <div className="sc-readback__eyebrow">Generating your report&hellip;</div>
        <div style={{ padding: "32px 0" }}><Typing /></div>
      </div>
    );
  }

  // Error state
  if (reportError) {
    return (
      <div className="sc-step">
        <div className="sc-readback__eyebrow">Something went wrong</div>
        <p style={{ color: "var(--fg-2)", marginBottom: "16px" }}>{reportError}</p>
      </div>
    );
  }

  const s = report.sections;

  return (
    <div className="sc-step sc-report">

      {/* Correction banner — shown only when user added a note */}
      {correctionNote && (
        <div className="sc-report__note">
          <div className="sc-report__note-label"><TealDot /> Your note was included.</div>
        </div>
      )}

      {/* ── The Read ─────────────────────────────────────────────── */}
      <section className="sc-section">
        <div className="sc-section__label">
          <span className="num">01</span>
          <span>&middot;</span>
          <span>The Read</span>
        </div>
        <h3 className="sc-section__title">The Read</h3>
        <Markdown text={s.the_read} className="sc-section__body" />
      </section>

      {/* ── The Hype Filter ──────────────────────────────────────── */}
      <section className="sc-section">
        <div className="sc-section__label">
          <span className="num">02</span>
          <span>&middot;</span>
          <span>The Hype Filter</span>
        </div>
        <h3 className="sc-section__title">The Hype Filter</h3>
        <Markdown text={s.hype_filter} className="sc-section__body" />
      </section>

      {/* ── The Real Opportunity ─────────────────────────────────── */}
      <section className="sc-section">
        <div className="sc-section__label">
          <span className="num">03</span>
          <span>&middot;</span>
          <span>The Real Opportunity</span>
        </div>
        <h3 className="sc-section__title">The Real Opportunity</h3>
        <Markdown text={s.real_opportunity} className="sc-section__body" />
      </section>

      {/* ── The Provocation ──────────────────────────────────────── */}
      <section className="sc-section">
        <div className="sc-section__label">
          <span className="num">04</span>
          <span>&middot;</span>
          <span>The Provocation</span>
        </div>
        <h3 className="sc-section__title">The Provocation</h3>
        <Markdown text={s.provocation} className="sc-section__body" />
      </section>

      {/* ── Do This First ────────────────────────────────────────── */}
      <div className="sc-do">
        <div className="sc-do__label"><TealDot /> Do this first</div>
        <h3 className="sc-do__headline">{s.next_step.headline}</h3>
        <Markdown text={s.next_step.detail} className="sc-do__detail" />
        <div className="sc-do__timeframe">
          <span className="sc-do__timeframe-label">Timeframe</span>
          <span className="sc-do__timeframe-value">{s.next_step.timeframe}</span>
        </div>
      </div>

      {/* ── I don't know close — no section label ────────────────── */}
      <section className="sc-section">
        <Markdown text={s.i_dont_know_close} className="sc-section__body" />
      </section>

      {/* AI disclaimer */}
      <p style={{ fontSize: "12px", color: "var(--fg-3)", margin: "0 0 80px" }}>
        This report is AI-generated and does not constitute professional advice.
      </p>

      {/* ── Email capture ─────────────────────────────────────────── */}
      <div className="sc-email">
        {emailSent ? (
          <>
            <div className="sc-email__eyebrow">Sent</div>
            <h3 className="sc-email__title">Sent. Check your inbox.</h3>
          </>
        ) : (
          <>
            <div className="sc-email__eyebrow">Get a copy in your inbox</div>
            <h3 className="sc-email__title">Get a copy in your inbox</h3>
            <p className="sc-email__sub">Enter your email and I&rsquo;ll send this report to you.</p>

            <form className="sc-email__form" onSubmit={onEmailSubmit}>
              <div className="sc-email__field">
                <label htmlFor="sc-email-input">so we can send the report</label>
                <input
                  id="sc-email-input"
                  type="email"
                  required
                  placeholder="your@email.com"
                  value={email}
                  onChange={e => setEmail(e.target.value)}
                />
              </div>

              {/* Required consent — first, must be checked to submit */}
              <label className="sc-email__consent">
                <input
                  type="checkbox"
                  checked={requiredConsent}
                  onChange={e => setRequiredConsent(e.target.checked)}
                  required
                />
                <span>
                  I agree to the{" "}
                  <a href="/privacy">privacy policy</a>{" "}
                  and understand this report is AI-generated and not professional advice.
                </span>
              </label>

              {/* Mailing list opt-in — second, unticked by default */}
              <label className="sc-email__consent">
                <input
                  type="checkbox"
                  checked={marketingConsent}
                  onChange={e => setMarketingConsent(e.target.checked)}
                />
                <span>
                  Keep me updated with occasional posts about AI in practice.
                  No spam. Unsubscribe any time.
                </span>
              </label>

              <p style={{ fontSize: "12px", color: "var(--fg-3)", marginTop: "-4px" }}>
                Your answers are processed by Claude (Anthropic) to generate this report.{" "}
                <a href="/privacy" style={{ color: "var(--fg-3)", textDecoration: "underline" }}>
                  Read the privacy policy.
                </a>
              </p>

              {emailError && (
                <p style={{ fontSize: "13px", color: "#c00" }}>{emailError}</p>
              )}

              <button
                type="submit"
                className="sc-btn sc-email__submit"
                disabled={emailLoading || !requiredConsent || !email}
              >
                {emailLoading ? "Sending\u2026" : "Send my report"}{" "}
                <span className="arrow">&#8594;</span>
              </button>
            </form>
          </>
        )}
      </div>
    </div>
  );
}

// ── App ───────────────────────────────────────────────────────────────────────
function App() {
  const [step, setStep]                     = useState(STEP.INTRO);
  const [qIndex, setQIndex]                 = useState(0);
  const [answers, setAnswers]               = useState([]); // [{ id, title, answer, probeQuestion, probeAnswer }]
  const [probesRemaining, setProbesRemaining] = useState(2);
  const [readBackParagraph, setReadBackParagraph] = useState(null);
  const [correctionNote, setCorrectionNote] = useState(null);
  const [completedCount, setCompletedCount] = useState(0);
  const [pulse, setPulse]                   = useState(false);

  // Scroll to top on step/question change
  useEffect(() => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  }, [step, qIndex]);

  const onBegin = () => setStep(STEP.QUESTION);

  // Called when a question is fully answered (after ack + optional probe)
  const onAnswered = ({ answer, probeQuestion, probeAnswer, probeUsed }) => {
    const q = QUESTIONS[qIndex];
    const newAnswer = {
      id: q.id,
      title: q.title,
      answer,
      probeQuestion: probeQuestion || null,
      probeAnswer:   probeAnswer   || null,
    };
    const allAnswers = [...answers, newAnswer];
    setAnswers(allAnswers);

    if (probeUsed) setProbesRemaining(prev => Math.max(0, prev - 1));

    // Progress bar: pulse on completion, advance fill
    setCompletedCount(qIndex + 1);
    setPulse(true);
    setTimeout(() => setPulse(false), 900);

    if (qIndex + 1 < QUESTIONS.length) {
      setQIndex(qIndex + 1);
    } else {
      setStep(STEP.READBACK);
    }
  };

  // Called when user confirms or corrects the read-back paragraph
  const onReadbackConfirmed = (rbParagraph, note) => {
    setReadBackParagraph(rbParagraph);
    setCorrectionNote(note || null);
    setStep(STEP.REPORT);
  };

  // priorAnswers for acknowledge call — only fully completed questions
  const priorAnswers = answers.map(a => ({ title: a.title, answer: a.answer }));

  // Progress indicator — fill advances only on completed questions (spec)
  let progress = null;
  if (step === STEP.QUESTION) {
    progress = { current: qIndex + 1, total: QUESTIONS.length };
  } else if (step === STEP.READBACK) {
    progress = { current: 7, total: 8 };
  } else if (step === STEP.REPORT) {
    progress = { current: 8, total: 8 };
  }

  return (
    <div className="sc-page">
      <Bar progress={progress} pulse={pulse} />
      <main className="sc-main">
        <div className="sc-col">

          {step === STEP.INTRO && (
            <Intro onBegin={onBegin} />
          )}

          {step === STEP.QUESTION && (
            <QuestionStep
              key={qIndex}
              question={QUESTIONS[qIndex]}
              index={qIndex}
              total={QUESTIONS.length}
              probesRemaining={probesRemaining}
              priorAnswers={priorAnswers}
              onComplete={onAnswered}
            />
          )}

          {step === STEP.READBACK && (
            <ReadbackStep
              answers={answers}
              onConfirm={onReadbackConfirmed}
            />
          )}

          {step === STEP.REPORT && (
            <ReportStep
              answers={answers}
              readBackParagraph={readBackParagraph}
              correctionNote={correctionNote}
            />
          )}

        </div>
      </main>
      <Foot />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
