const { useState, useEffect, useCallback, useRef } = React;

const EMPTY_TEASER = {
  companyName: "", ticker: "", exchange: "", sector: "", tagline: "",
  profile: "", asOfDate: "",
  metrics: [
    { label: "Market Cap", value: "", unit: "" },
    { label: "Revenue (LTM)", value: "", unit: "" },
    { label: "Net Profit", value: "", unit: "" },
    { label: "Revenue Growth", value: "", unit: "" },
    { label: "ROE", value: "", unit: "" },
    { label: "Net Margin", value: "", unit: "" },
  ],
  shareholders: [],
  financialTrend: [],
  operational: [],
  highlights: [],
  peers: [],
  dealInfo: { type: "", size: "", useOfProceeds: "" },
};

async function apiJSON(method, path, body) {
  const opts = {
    method,
    headers: { "Content-Type": "application/json" },
    credentials: "same-origin",
  };
  if (body !== undefined) opts.body = JSON.stringify(body);
  const r = await fetch(path, opts);
  const data = await r.json().catch(() => ({}));
  if (!r.ok) {
    const err = new Error(data.error || `HTTP ${r.status}`);
    err.status = r.status;
    throw err;
  }
  return data;
}

function App() {
  const [me, setMe] = useState(null);       // null = not loaded, false = not authed, object = authed
  const [booting, setBooting] = useState(true);

  const bootstrap = useCallback(async () => {
    try {
      const data = await apiJSON("GET", "/api/me");
      setMe(data);
    } catch (e) {
      if (e.status === 401) setMe(false);
      else setMe(false);
    } finally {
      setBooting(false);
    }
  }, []);

  useEffect(() => { bootstrap(); }, [bootstrap]);

  if (booting) return <div className="center-screen"><div>Đang tải...</div></div>;

  if (!me) return <AuthScreen onAuthed={(u) => setMe(u)} />;

  return <MainApp me={me} setMe={setMe} />;
}

function AuthScreen({ onAuthed }) {
  const [mode, setMode] = useState("login"); // login | register
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setErr("");
    setBusy(true);
    try {
      const path = mode === "login" ? "/api/auth/login" : "/api/auth/register";
      const data = await apiJSON("POST", path, { username: username.trim(), password });
      onAuthed(data);
    } catch (e) {
      setErr(e.message);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="center-screen">
      <form className="panel auth-panel" onSubmit={submit}>
        <div className="brand-big">TCBS<span className="sub">ECM Teaser Generator</span></div>
        <div className="tab-bar" style={{ marginTop: 8 }}>
          <button type="button" className={mode === "login" ? "active" : ""} onClick={() => setMode("login")}>Đăng nhập</button>
          <button type="button" className={mode === "register" ? "active" : ""} onClick={() => setMode("register")}>Đăng ký</button>
        </div>
        <label>Username</label>
        <input type="text" value={username} onChange={e => setUsername(e.target.value)} autoFocus autoComplete="username" placeholder="3-32 ký tự: chữ, số, . _ -" required />
        <label>Password</label>
        <input type="password" value={password} onChange={e => setPassword(e.target.value)} autoComplete={mode === "login" ? "current-password" : "new-password"} placeholder="tối thiểu 8 ký tự" required />
        {err && <div className="status error">{err}</div>}
        <button type="submit" disabled={busy} style={{ marginTop: 10, width: "100%" }}>
          {busy ? "..." : (mode === "login" ? "Đăng nhập" : "Đăng ký")}
        </button>
      </form>
    </div>
  );
}

function MainApp({ me, setMe }) {
  const [apiKey, setApiKey] = useState("");
  const [urlsInput, setUrlsInput] = useState("");
  const [sources, setSources] = useState([]);
  const [teaser, setTeaser] = useState(EMPTY_TEASER);
  const [teaserId, setTeaserId] = useState(null);
  const [status, setStatus] = useState("");
  const [statusErr, setStatusErr] = useState(false);
  const [history, setHistory] = useState([]);
  const [tab, setTab] = useState("sources");
  const [loading, setLoading] = useState(false);
  const fileRef = useRef(null);
  const previewRef = useRef(null);

  const setMsg = (m, err = false) => { setStatus(m); setStatusErr(err); };

  const refreshMe = useCallback(async () => {
    try { setMe(await apiJSON("GET", "/api/me")); } catch (e) { /* */ }
  }, [setMe]);

  const loadHistory = useCallback(async () => {
    try {
      const data = await apiJSON("GET", "/api/teasers");
      setHistory(data.teasers || []);
    } catch (e) { /* ignore */ }
  }, []);

  useEffect(() => { loadHistory(); }, [loadHistory]);

  const logout = async () => {
    try { await apiJSON("POST", "/api/auth/logout"); } catch (e) { /* ignore */ }
    setMe(false);
  };

  const saveAPIKey = async () => {
    if (!apiKey.trim()) return;
    try {
      await apiJSON("PUT", "/api/me/apikey", { apiKey: apiKey.trim() });
      setApiKey("");
      setMsg("API key đã lưu (mã hoá AES-GCM).");
      refreshMe();
    } catch (e) { setMsg(e.message, true); }
  };

  const extractSources = async () => {
    const urls = urlsInput.split(/\s+/).map(s => s.trim()).filter(Boolean);
    const files = fileRef.current?.files || [];
    if (urls.length === 0 && files.length === 0) {
      setMsg("Nhập URL hoặc chọn file PDF.", true);
      return;
    }
    setLoading(true);
    setMsg("Đang trích text từ PDF...");
    try {
      const fd = new FormData();
      if (urls.length > 0) fd.append("urls", JSON.stringify(urls));
      for (const f of files) fd.append("files", f);
      const r = await fetch("/api/pdf/extract", { method: "POST", body: fd, credentials: "same-origin" });
      const data = await r.json();
      if (!r.ok) throw new Error(data.error || `HTTP ${r.status}`);
      setSources(data.results || []);
      const ok = (data.results || []).filter(x => !x.error).length;
      setMsg(`Trích ${ok}/${(data.results || []).length} nguồn thành công.`);
      if (fileRef.current) fileRef.current.value = "";
    } catch (e) {
      setMsg(e.message, true);
    } finally {
      setLoading(false);
    }
  };

  const extractTeaser = async () => {
    const texts = sources.filter(s => !s.error && s.text).map(s => `=== ${s.sourceRef} ===\n${s.text}`);
    if (texts.length === 0) {
      setMsg("Không có nguồn text nào để gọi Claude.", true);
      return;
    }
    setLoading(true);
    setMsg("Đang gọi Claude Opus 4.7 (adaptive thinking)...");
    try {
      const combinedText = texts.join("\n\n").slice(0, 60000);
      const sourceRefs = sources.filter(s => !s.error).map(s => s.sourceRef);
      const data = await apiJSON("POST", "/api/teasers/extract", { combinedText, sourceRefs });
      setTeaser({ ...EMPTY_TEASER, ...data.payload });
      setTeaserId(data.id);
      const u = data.usage || {};
      setMsg(`Trích teaser OK. tokens in/out=${u.InputTokens}/${u.OutputTokens}, latency=${u.LatencyMS}ms`);
      loadHistory();
    } catch (e) {
      setMsg(e.message, true);
    } finally {
      setLoading(false);
    }
  };

  const saveEdit = async () => {
    if (!teaserId) return;
    try {
      await apiJSON("PUT", `/api/teasers/${teaserId}`, teaser);
      setMsg("Đã lưu chỉnh sửa.");
      loadHistory();
    } catch (e) { setMsg(e.message, true); }
  };

  const loadTeaser = async (id) => {
    try {
      const data = await apiJSON("GET", `/api/teasers/${id}`);
      setTeaser({ ...EMPTY_TEASER, ...data.payload });
      setTeaserId(data.id);
      setMsg(`Đã tải teaser #${id}.`);
      setTab("edit");
    } catch (e) { setMsg(e.message, true); }
  };

  const deleteTeaser = async (id) => {
    if (!confirm(`Xoá teaser #${id}?`)) return;
    try {
      await apiJSON("DELETE", `/api/teasers/${id}`);
      if (teaserId === id) { setTeaser(EMPTY_TEASER); setTeaserId(null); }
      loadHistory();
    } catch (e) { setMsg(e.message, true); }
  };

  const exportPDF = async () => {
    const el = previewRef.current;
    if (!el) return;
    setLoading(true);
    setMsg("Đang render PDF...");
    try {
      const canvas = await html2canvas(el, { scale: 2, backgroundColor: "#ffffff" });
      const imgData = canvas.toDataURL("image/png");
      const { jsPDF } = window.jspdf;
      const pdf = new jsPDF({ unit: "mm", format: "a4", orientation: "portrait" });
      const pageW = pdf.internal.pageSize.getWidth();
      const pageH = pdf.internal.pageSize.getHeight();
      const ratio = Math.min(pageW / canvas.width, pageH / canvas.height);
      const w = canvas.width * ratio;
      const h = canvas.height * ratio;
      pdf.addImage(imgData, "PNG", (pageW - w) / 2, 0, w, h);
      const fname = `${(teaser.ticker || "TEASER").toUpperCase()}_ECM_Teaser.pdf`;
      pdf.save(fname);
      setMsg("PDF tải xong.");
    } catch (e) {
      setMsg("Export PDF lỗi: " + e.message, true);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="app">
      <div className="sidebar">
        <div className="panel">
          <h2>Người dùng</h2>
          <div className="row">
            <div style={{ flex: 2 }}>
              <strong>{me?.name}</strong>
              <span style={{ color: "var(--muted)", fontSize: 12 }}>{me?.hasApiKey ? " • API key ✓" : " • chưa có API key"}</span>
            </div>
            <button className="ghost" onClick={logout}>Đăng xuất</button>
          </div>
        </div>

        <div className="panel">
          <h2>Anthropic API Key</h2>
          <div className="row">
            <input type="password" value={apiKey} onChange={e => setApiKey(e.target.value)} placeholder={me?.hasApiKey ? "(đã có — nhập để thay)" : "sk-ant-..."} />
            <button onClick={saveAPIKey} style={{ flex: "none" }}>Lưu</button>
          </div>
          <div className="status" style={{ fontSize: 11 }}>Lưu mã hoá AES-GCM trong SQLite.</div>
        </div>

        <div className="tab-bar">
          <button className={tab === "sources" ? "active" : ""} onClick={() => setTab("sources")}>Nguồn PDF</button>
          <button className={tab === "edit" ? "active" : ""} onClick={() => setTab("edit")}>Chỉnh tay</button>
          <button className={tab === "history" ? "active" : ""} onClick={() => setTab("history")}>Lịch sử</button>
        </div>

        {tab === "sources" && (
          <div className="panel stack">
            <h2>PDF nguồn</h2>
            <label>URL (mỗi URL một dòng, cách nhau bằng khoảng trắng)</label>
            <textarea value={urlsInput} onChange={e => setUrlsInput(e.target.value)} placeholder="https://..." />
            <label>Hoặc upload PDF</label>
            <input type="file" ref={fileRef} accept="application/pdf" multiple />
            <div className="row">
              <button onClick={extractSources} disabled={loading}>Trích text</button>
              <button className="secondary" onClick={extractTeaser} disabled={loading || sources.length === 0}>Gọi Claude → teaser</button>
            </div>
            {sources.length > 0 && (
              <ul className="source-list">
                {sources.map((s, i) => (
                  <li key={i} className={s.error ? "error" : s.cached ? "cached" : ""}>
                    <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{s.sourceRef}</span>
                    <span style={{ color: "var(--muted)", fontSize: 11 }}>
                      {s.error ? `❌ ${s.error}` : `${s.pageCount}p${s.cached ? " • cached" : ""}`}
                    </span>
                  </li>
                ))}
              </ul>
            )}
          </div>
        )}

        {tab === "edit" && (
          <EditPanel teaser={teaser} setTeaser={setTeaser} onSave={saveEdit} teaserId={teaserId} />
        )}

        {tab === "history" && (
          <div className="panel">
            <h2>Teaser đã tạo</h2>
            {history.length === 0 && <div style={{ color: "var(--muted)", fontSize: 12 }}>Chưa có teaser nào.</div>}
            <ul className="history" style={{ listStyle: "none", padding: 0, margin: 0 }}>
              {history.map(h => (
                <li key={h.id} onClick={() => loadTeaser(h.id)}>
                  <div style={{ display: "flex", justifyContent: "space-between" }}>
                    <strong>{h.ticker || "—"}</strong>
                    <button className="ghost" onClick={e => { e.stopPropagation(); deleteTeaser(h.id); }}>✕</button>
                  </div>
                  <div style={{ color: "var(--muted)", fontSize: 11 }}>{h.companyName}</div>
                </li>
              ))}
            </ul>
          </div>
        )}

        <div className="panel">
          <button onClick={exportPDF} disabled={loading} style={{ width: "100%" }}>Generate PDF</button>
          <div className={"status" + (statusErr ? " error" : "")}>{status || (loading ? "..." : "")}</div>
        </div>
      </div>

      <div className="preview-wrap">
        <TeaserPreview teaser={teaser} refEl={previewRef} />
      </div>
    </div>
  );
}

function EditPanel({ teaser, setTeaser, onSave, teaserId }) {
  const upd = (k, v) => setTeaser(t => ({ ...t, [k]: v }));
  const updMetric = (i, k, v) => setTeaser(t => ({ ...t, metrics: t.metrics.map((m, idx) => idx === i ? { ...m, [k]: v } : m) }));
  return (
    <div className="panel stack">
      <h2>Chỉnh tay</h2>
      {!teaserId && <div style={{ color: "var(--muted)", fontSize: 12 }}>Chưa có teaser. Trích từ PDF trước.</div>}
      <div className="edit-grid">
        <label>Company</label><input value={teaser.companyName} onChange={e => upd("companyName", e.target.value)} />
        <label>Ticker</label><input value={teaser.ticker} onChange={e => upd("ticker", e.target.value)} />
        <label>Exchange</label><input value={teaser.exchange} onChange={e => upd("exchange", e.target.value)} />
        <label>Sector</label><input value={teaser.sector} onChange={e => upd("sector", e.target.value)} />
        <label>Tagline</label><input value={teaser.tagline} onChange={e => upd("tagline", e.target.value)} />
        <label>As of</label><input value={teaser.asOfDate} onChange={e => upd("asOfDate", e.target.value)} />
      </div>
      <label>Profile</label>
      <textarea value={teaser.profile} onChange={e => upd("profile", e.target.value)} />
      <label>Highlights (mỗi dòng 1 bullet)</label>
      <textarea value={(teaser.highlights || []).join("\n")} onChange={e => upd("highlights", e.target.value.split("\n").filter(Boolean))} />
      <h2 style={{ marginTop: 8 }}>Metrics (6 KPI)</h2>
      {teaser.metrics?.map((m, i) => (
        <div key={i} className="row">
          <input value={m.label} onChange={e => updMetric(i, "label", e.target.value)} />
          <input value={m.value} onChange={e => updMetric(i, "value", e.target.value)} placeholder="value" />
          <input value={m.unit} onChange={e => updMetric(i, "unit", e.target.value)} placeholder="unit" style={{ maxWidth: 80 }} />
        </div>
      ))}
      <div className="row">
        <button onClick={onSave} disabled={!teaserId}>Lưu</button>
      </div>
    </div>
  );
}

function TeaserPreview({ teaser, refEl }) {
  const t = teaser || EMPTY_TEASER;
  const maxRev = Math.max(1, ...(t.financialTrend || []).map(f => Math.max(f.revenue || 0, f.profit || 0)));
  return (
    <div ref={refEl} className="teaser" id="teaser-preview">
      <div className="t-header">
        <div>
          <div className="brand">TCBS<span className="sub">Techcombank Securities — ECM Teaser</span></div>
          <h1 className="t-title">{t.companyName || "Company Name"}<span className="ticker">{t.ticker ? ` (${t.ticker})` : ""}</span></h1>
          <div className="t-subtitle">{[t.exchange, t.sector].filter(Boolean).join(" • ") || "Exchange • Sector"}</div>
        </div>
        <div style={{ textAlign: "right", fontSize: 10, color: "var(--muted)" }}>
          {t.asOfDate ? `As of ${t.asOfDate}` : ""}
        </div>
      </div>

      {t.tagline && <div className="t-tagline">{t.tagline}</div>}

      <div className="metrics">
        {(t.metrics || []).map((m, i) => (
          <div key={i} className="metric">
            <div className="label">{m.label}</div>
            <div><span className="value">{m.value || "—"}</span><span className="unit">{m.unit}</span></div>
          </div>
        ))}
      </div>

      <div className="two-col">
        <div className="sec">
          <h3>Company profile</h3>
          <div>{t.profile || "—"}</div>
          {(t.highlights || []).length > 0 && (
            <>
              <h3 style={{ marginTop: 8 }}>Key highlights</h3>
              <ul className="highlights">
                {t.highlights.map((h, i) => <li key={i}>{h}</li>)}
              </ul>
            </>
          )}
        </div>
        <div className="sec">
          <h3>Shareholder structure</h3>
          {(t.shareholders || []).length === 0 ? <div>—</div> : t.shareholders.map((s, i) => (
            <div key={i} className="shareholder-row">
              <span style={{ minWidth: 90 }}>{s.name}</span>
              <div className="bar"><span style={{ width: `${Math.min(100, s.pct)}%` }} /></div>
              <span style={{ minWidth: 40, textAlign: "right" }}>{(s.pct || 0).toFixed(1)}%</span>
            </div>
          ))}
          <h3 style={{ marginTop: 8 }}>Operational footprint</h3>
          {(t.operational || []).length === 0 ? <div>—</div> : (
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 4 }}>
              {t.operational.map((o, i) => (
                <div key={i} style={{ border: "1px solid var(--border)", padding: 4, borderRadius: 3 }}>
                  <div style={{ fontSize: 9, color: "var(--muted)" }}>{o.label}</div>
                  <div style={{ fontWeight: 600 }}>{o.value}</div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>

      <div className="two-col">
        <div className="sec">
          <h3>Financial trend (VND bn)</h3>
          {(t.financialTrend || []).length === 0 ? <div>—</div> : (
            <div className="fin-chart">
              {t.financialTrend.map((f, i) => (
                <div key={i} className="bar-group">
                  <div className="bars">
                    <div className="rev" style={{ height: `${((f.revenue || 0) / maxRev) * 80}px` }} title={`Rev ${f.revenue}`} />
                    <div className="prof" style={{ height: `${((f.profit || 0) / maxRev) * 80}px` }} title={`Profit ${f.profit}`} />
                  </div>
                  <div className="year">{f.year}</div>
                </div>
              ))}
            </div>
          )}
          <div style={{ fontSize: 9, color: "var(--muted)" }}>
            <span style={{ display: "inline-block", width: 8, height: 8, background: "var(--navy)", marginRight: 4 }} />Revenue
            <span style={{ display: "inline-block", width: 8, height: 8, background: "var(--gold)", marginLeft: 10, marginRight: 4 }} />Profit
          </div>
        </div>
        <div className="sec">
          <h3>Peer comparison</h3>
          {(t.peers || []).length === 0 ? <div>—</div> : (
            <table>
              <thead><tr><th>Peer</th><th>P/E</th><th>P/B</th><th>ROE %</th></tr></thead>
              <tbody>
                {t.peers.map((p, i) => (
                  <tr key={i}>
                    <td>{p.name}</td>
                    <td>{(p.pe || 0).toFixed(1)}</td>
                    <td>{(p.pb || 0).toFixed(1)}</td>
                    <td>{(p.roe || 0).toFixed(1)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>

      {(t.dealInfo?.type || t.dealInfo?.size || t.dealInfo?.useOfProceeds) && (
        <div className="deal-strip">
          <div><div className="label">Deal type</div>{t.dealInfo.type || "—"}</div>
          <div><div className="label">Size</div>{t.dealInfo.size || "—"}</div>
          <div><div className="label">Use of proceeds</div>{t.dealInfo.useOfProceeds || "—"}</div>
        </div>
      )}

      <div className="footer">
        <span>Techcombank Securities — ECM</span>
        <span>Confidential — for institutional investors only</span>
      </div>
    </div>
  );
}

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