/* global React, Homepage, StockDetail, RequestStock, CitationProvider, TweaksPanel, useTweaks, TweakSection, TweakRadio */
// app.jsx — root, routing, tweaks wiring

const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "density": "standard",
  "chatLayout": "rail"
}/*EDITMODE-END*/;

// Throughline logo mark — narrative line that bends and lands in a violet
// dot. Inline SVG so it scales crisp at any size and the dot recolors with
// --accent in both light/dark themes. Drawn on a 24×16 viewBox, vertically
// centered against the wordmark.
function ThroughlineMark({ size = 22 }) {
  return (
    <svg
      className="throughline-mark"
      width={size}
      height={Math.round(size * 16 / 24)}
      viewBox="0 0 24 16"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.6"
      strokeLinecap="round"
      strokeLinejoin="round"
      aria-hidden="true"
      focusable="false"
    >
      {/* The throughline: starts left, runs flat, dips, climbs back up,
          then ends just before the violet attention dot. */}
      <path d="M2 6 H8 C9.2 6 9.8 7 10.4 8.4 C11 9.8 11.6 11 12.8 11 H14.5" />
      {/* Short descender (the T-stem) */}
      <path d="M5.5 6 V12.5" />
      {/* Trailing tick after the dot */}
      <path d="M19.5 11 H22" />
      {/* The attention dot — fills with --accent so it pops violet */}
      <circle cx="17" cy="11" r="2.2" fill="var(--accent)" stroke="var(--accent)" />
    </svg>
  );
}

function parseRoute(hash) {
  const h = hash ? hash.replace(/^#/, "") : "";
  if (!h) return { name: "home" };
  if (h.startsWith("stock:")) return { name: "stock", ticker: h.slice(6) };
  if (h.startsWith("request:")) return { name: "request", query: h.slice(8) };
  if (h.startsWith("chat:")) return { name: "stock", ticker: h.slice(5) }; // legacy
  if (h === "about" || h === "methodology" || h.startsWith("methodology?")) {
    // Optional ?flag=… deep link from "Flag this finding" buttons.
    const qIdx = h.indexOf("?");
    const params = qIdx >= 0 ? new URLSearchParams(h.slice(qIdx + 1)) : null;
    return { name: "methodology", flag: params?.get("flag") || null };
  }
  return { name: "home" };
}

function App() {
  const [route, setRoute] = useState(() => parseRoute(location.hash));
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {
    const onHash = () => setRoute(parseRoute(location.hash));
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  function navigate(r) {
    location.hash = r;
    setRoute(parseRoute("#" + r));
    window.scrollTo({ top: 0, behavior: "instant" });
  }

  useEffect(() => {
    document.documentElement.dataset.density = tweaks.density;
    document.documentElement.dataset.chatLayout = tweaks.chatLayout;
  }, [tweaks.density, tweaks.chatLayout]);

  let view = null;
  if (route.name === "stock") view = <StockDetail ticker={route.ticker} navigate={navigate} />;
  else if (route.name === "request") view = <RequestStock query={route.query} navigate={navigate} />;
  else if (route.name === "methodology") view = <MethodologyPage navigate={navigate} flag={route.flag} />;
  else view = <Homepage navigate={navigate} />;

  const data = window.CCT_DATA;

  return (
    <CitationProvider>
      <header className="app-rail">
        <div className="app-rail-inner">
          <a href="#home" className="brand" aria-label="Throughline home" onClick={(e) => { e.preventDefault(); navigate("home"); }}>
            <ThroughlineMark />
            <b>Throughline</b>
          </a>
          <nav className="nav">
            <a href="#home" className={route.name === "home" ? "active" : ""} onClick={e => { e.preventDefault(); navigate("home"); }}>Home</a>
            <a href="#methodology" className={route.name === "methodology" ? "active" : ""} onClick={e => { e.preventDefault(); navigate("methodology"); }}>Methodology</a>
          </nav>
          <div className="app-rail-meta">
            <span><span className="dot"></span>{data?.latest_quarter || "Q3 FY26"}</span>
            <span className="dim">{data?.tickers_complete || 7} stocks</span>
          </div>
        </div>
      </header>

      {view}

      <TweaksPanel title="Tweaks">
        <TweakSection label="Density">
          <TweakRadio
            value={tweaks.density}
            onChange={v => setTweak("density", v)}
            options={[
              { value: "standard", label: "Standard" },
              { value: "compact", label: "Compact" }
            ]}
          />
        </TweakSection>
        <TweakSection label="Chat panel layout">
          <TweakRadio
            value={tweaks.chatLayout}
            onChange={v => setTweak("chatLayout", v)}
            options={[
              { value: "rail", label: "Right rail" },
              { value: "stacked", label: "Below brief" }
            ]}
          />
        </TweakSection>
      </TweaksPanel>
    </CitationProvider>
  );
}

// Methodology page — five sections: what Throughline does, how findings are
// produced, what we verify vs editorial, flag-an-error form, what we are not.
//
// The flag form accepts a deep-linked URL via ?flag=<base64-json> from the
// "Flag this finding" buttons on stock pages, so we pre-fill subject + URL.
const SUPPORT_EMAIL = "hello@throughline.co.in";

function decodeFlagPayload(flag) {
  if (!flag) return null;
  try {
    const json = atob(decodeURIComponent(flag));
    const payload = JSON.parse(json);
    if (typeof payload !== "object" || !payload) return null;
    return payload;
  } catch {
    return null;
  }
}

function MethodologyPage({ navigate, flag }) {
  const prefill = decodeFlagPayload(flag);
  const [errorKind, setErrorKind] = useState("");
  const [subject, setSubject] = useState(() => prefill?.subject || "");
  const [findingUrl, setFindingUrl] = useState(() => prefill?.url || "");
  const [details, setDetails] = useState("");
  const [email, setEmail] = useState("");
  const [submitted, setSubmitted] = useState(false);
  const flagRef = React.useRef(null);

  // If we landed with a deep link, scroll the form into view.
  useEffect(() => {
    if (prefill && flagRef.current) {
      flagRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  function buildMailto() {
    const subj = subject.trim() || "Flag a finding on Throughline";
    const body = [
      errorKind ? `Kind: ${errorKind}` : "",
      "",
      details.trim(),
      "",
      findingUrl.trim() ? `Finding URL: ${findingUrl.trim()}` : "",
      email.trim() ? `From: ${email.trim()}` : "",
    ].filter(Boolean).join("\n");
    return `mailto:${SUPPORT_EMAIL}?subject=${encodeURIComponent(subj)}&body=${encodeURIComponent(body)}`;
  }

  async function submit(e) {
    e.preventDefault();
    if (!subject.trim() && !details.trim()) return;
    // Try the backend (endpoint is wired but optional — we don't depend on it).
    if (window.CCT_USE_REAL_API) {
      try {
        const base = window.CCT_API_BASE || "";
        const res = await fetch(`${base}/api/flags`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          credentials: "include",
          body: JSON.stringify({
            kind: errorKind || null,
            subject: subject.trim(),
            finding_url: findingUrl.trim(),
            details: details.trim(),
            email: email.trim() || null,
          }),
        });
        if (res.ok) { setSubmitted(true); return; }
      } catch { /* fall through to mailto */ }
    }
    // Fallback: open the user's mail client with everything pre-filled. Nothing
    // is lost — the form contents become the email body.
    window.location.href = buildMailto();
    setSubmitted(true);
  }

  return (
    <div className="page">
      <article className="editorial methodology">
        <div className="meth-kicker">
          <span className="kicker eyebrow">Methodology</span>
          <span className="meth-updated mono">Last updated · April 2026</span>
        </div>
        <h1 className="h-display">How Throughline builds a brief.</h1>

        {/* §1 — What Throughline does */}
        <section className="meth-section">
          <h2 className="meth-h">What Throughline does</h2>
          <p>
            Throughline reads earnings concalls so you don't have to. For each Indian midcap we cover, we process four consecutive quarterly calls and
            surface the parts that matter: what management started saying, what they stopped saying, where they walked back guidance, and which questions
            they dodged. Every claim cites a verbatim transcript. The trade thesis stays yours; we hand you the narrative scaffolding.
          </p>
        </section>

        {/* §2 — How findings are produced */}
        <section className="meth-section">
          <h2 className="meth-h">How findings are produced</h2>
          <ol className="meth-pipeline">
            <li>
              <span className="step mono">01</span>
              <div>
                <h3>Source</h3>
                <p>
                  Earnings call transcripts from BSE / NSE filings and the company's own investor relations site. Always the official PDF.
                  Each brief on Throughline links directly to the source PDF for verification.
                </p>
              </div>
            </li>
            <li>
              <span className="step mono">02</span>
              <div>
                <h3>Clean</h3>
                <p>PDF → text with formatting normalized. Speaker names canonicalized. Boilerplate stripped. We keep the structured Q&A pairs intact.</p>
              </div>
            </li>
            <li>
              <span className="step mono">03</span>
              <div>
                <h3>Extract</h3>
                <p>
                  An LLM-assisted process reads the four quarters together and proposes candidate findings — emerged topics, walked-back guidance, dodged questions, governance changes.
                  Each candidate cites its quote. The editor reviews and selects which ones publish.
                </p>
              </div>
            </li>
            <li>
              <span className="step mono">04</span>
              <div>
                <h3>Verify</h3>
                <p className="strong">
                  Every quote in a published brief is checked verbatim against the cleaned transcript before the brief ships.
                  101 of 101 quotes across the seven launch tickers have been verified character-for-character. A finding does not enter the site without its quote passing this gate.
                </p>
              </div>
            </li>
            <li>
              <span className="step mono">05</span>
              <div>
                <h3>Edit</h3>
                <p>
                  An editor reviews proposed findings, drops the ones that don't hold up, writes the drift summary in their own voice, picks which findings lead, assigns severity
                  (material / notable / context), and writes the "what this implies" bullets. This is where mechanical detection becomes editorial product.
                </p>
              </div>
            </li>
          </ol>
        </section>

        {/* §3 — What we verify vs what's editorial */}
        <section className="meth-section">
          <h2 className="meth-h">What we verify vs what's editorial</h2>
          <div className="meth-cols">
            <div className="meth-col verify">
              <div className="meth-col-head">
                <span className="badge ok">✓ Verified</span>
                <span className="dim">Mechanically checked, gate to publication</span>
              </div>
              <ul>
                <li><strong>Verbatim quotes.</strong> Character-for-character against the cleaned transcript.</li>
                <li><strong>Quarter and section attribution.</strong> The transcript and section a quote came from.</li>
                <li><strong>Speaker.</strong> Who said it (CFO, CEO, named analyst, moderator).</li>
                <li><strong>Topic mention counts.</strong> How many times a phrase appeared across the four quarters.</li>
                <li><strong>Numerical facts when stated by management.</strong> Margin, growth, headcount numbers as quoted.</li>
              </ul>
            </div>
            <div className="meth-col editorial">
              <div className="meth-col-head">
                <span className="badge warn">⚠ Editorial</span>
                <span className="dim">Human judgment, debatable</span>
              </div>
              <ul>
                <li><strong>Severity.</strong> Whether a walk-back is "material," "notable," or "context."</li>
                <li><strong>Drift summary.</strong> The one-line characterization of what changed this quarter.</li>
                <li><strong>"What this implies."</strong> The bullets translating findings into thesis-level reads.</li>
                <li><strong>Topic clustering.</strong> What counts as the same topic across quarters when phrasing shifts.</li>
                <li><strong>Significance commentary.</strong> The "why this matters" prose under each finding.</li>
              </ul>
            </div>
          </div>
        </section>

        {/* §4 — Flag an error */}
        <section className="meth-section meth-flag" ref={flagRef} id="flag">
          <h2 className="meth-h">Flag an error</h2>
          <p>
            Sometimes we get things wrong. When we do, tell us — we'll fix it and credit the catch.
            Quote mismatches, attribution slips, mis-sectioned findings, severity calls you disagree with: all welcome.
          </p>
          {submitted ? (
            <div className="meth-thanks">
              <div className="badge ok" style={{ marginBottom: 8 }}>✓ Sent</div>
              <p>
                Thanks. We read every flag. If you left an email, expect a reply within a few days; if not, we'll fix it and the corrected
                brief will quietly update.
              </p>
              <button className="btn ghost" onClick={() => { setSubmitted(false); setErrorKind(""); setSubject(""); setFindingUrl(""); setDetails(""); setEmail(""); }}>Flag another</button>
            </div>
          ) : (
            <form className="meth-form" onSubmit={submit}>
              <label>
                <span className="lbl">What kind of error?</span>
                <select
                  className="meth-select"
                  value={errorKind}
                  onChange={e => setErrorKind(e.target.value)}
                  required
                >
                  <option value="" disabled>Pick one — helps us triage</option>
                  <option value="Quote mismatch">Quote mismatch</option>
                  <option value="Wrong attribution">Wrong attribution</option>
                  <option value="Wrong section">Wrong section</option>
                  <option value="Disagree with severity">Disagree with severity</option>
                  <option value="Disagree with interpretation">Disagree with interpretation</option>
                  <option value="Other">Other</option>
                </select>
              </label>
              <label>
                <span className="lbl">Subject</span>
                <input
                  type="text"
                  value={subject}
                  onChange={e => setSubject(e.target.value)}
                  placeholder="Quote mismatch on PERSISTENT Q3FY26"
                  maxLength={140}
                  required
                />
              </label>
              <label>
                <span className="lbl">Finding URL <span className="dim">— optional, pre-filled from "Flag this finding"</span></span>
                <input
                  type="text"
                  value={findingUrl}
                  onChange={e => setFindingUrl(e.target.value)}
                  placeholder="https://throughline.co.in/#stock:PERSISTENT"
                  maxLength={400}
                />
              </label>
              <label>
                <span className="lbl">What's wrong</span>
                <textarea
                  rows={5}
                  value={details}
                  onChange={e => setDetails(e.target.value)}
                  placeholder="The quote ends mid-sentence — should continue with '…and a 30 bps headwind from currency.' Source: Q3FY26 transcript p.7."
                  maxLength={2000}
                />
              </label>
              <label>
                <span className="lbl">Email <span className="dim">— optional, only used to reply to you</span></span>
                <input
                  type="email"
                  value={email}
                  onChange={e => setEmail(e.target.value)}
                  placeholder="you@example.com"
                  maxLength={200}
                />
              </label>
              <div className="meth-form-foot">
                <button type="submit" className="btn primary">Send flag →</button>
                <a className="meth-mailto dim" href={buildMailto()}>or email <span className="mono">{SUPPORT_EMAIL}</span> directly</a>
              </div>
            </form>
          )}
        </section>

        {/* §5 — What we are not */}
        <section className="meth-section">
          <h2 className="meth-h">What we are not</h2>
          <ul className="meth-not">
            <li><strong>Not investment advice.</strong> Throughline does not issue buy / sell / hold calls or price targets. The agent will refuse to.</li>
            <li><strong>Not registered advisors.</strong> We are not SEBI-registered investment advisors and nothing here should be read as a recommendation.</li>
            <li><strong>Not real-time.</strong> Briefs publish after the call has been transcribed and verified — typically days, not minutes.</li>
            <li><strong>Not the only source.</strong> The transcripts we work from are public. We link to the sourcing for every brief; please verify against the original when stakes are high.</li>
            <li><strong>Not an investment thesis.</strong> We tell you what management said and how it changed. The thesis is yours to write.</li>
          </ul>
        </section>

        <div style={{ marginTop: 32 }}>
          <button className="btn ghost" onClick={() => navigate("home")}>← Home</button>
        </div>
      </article>
    </div>
  );
}

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