/* Tract Console v2 — Advisor-only "Tract Counsel AI" tab.
   ChatGPT-style. Attach deal documents, run analysis, copy output into a chat thread.
   Uses window.claude.complete when available; falls back to canned CRE analysis. */
const { Icon: AIcon, Avatar: AAvatar, Composer: AComposer, RichText: ARich, Modal: AModal, Popover: APop, useDeal: useDealAI, Store: StoreAI, mdToHtml: md2, useState: uSt, useEffect: uEf, useRef: uRf } = window;
const Dai = window.V2DATA;

const SUGGESTIONS = [
  { icon: "scale", t: "Review the PSA assignment clause", p: "Review the assignment clause in the Purchase & Sale Agreement and flag anything that limits the buyer's ability to assign to a single-purpose entity at closing." },
  { icon: "file-search", t: "Summarize title commitment exceptions", p: "Summarize the Schedule B exceptions in the title commitment and tell me which ones a buyer should object to before the due-diligence deadline." },
  { icon: "leaf", t: "Flag environmental risks (Phase I)", p: "Read the Phase I environmental report and flag any recognized environmental conditions (RECs) or recommendations for further investigation." },
  { icon: "calculator", t: "Check lease economics vs. valuation", p: "Compare the rent roll economics to the valuation estimate — is the going-in cap rate consistent with the price, and are the rent bumps modeled correctly?" },
];

function cannedAnalysis(prompt, attached) {
  const p = prompt.toLowerCase();
  const ctx = attached.length ? attached.map((d) => d.name).join(", ") : "the deal record";
  let body;
  if (/title|schedule b|exception|lien/.test(p)) {
    body = `## Title commitment — Schedule B review\n\nReading **Title commitment** against the deal file, three exceptions stand out:\n\n1. **Access easement (Item 7).** Recorded in favor of the adjoining parcel. Confirm it doesn't cross the drive-thru lane.\n2. **Unreleased UCC fixture filing (Item 11).** Likely stale — request a payoff/release letter from the prior lender before closing.\n3. **Survey-dependent matters (Item 12).** Cleared once the **ALTA survey** is reviewed; flag any encroachments.\n\n**Suggested objections before the DD deadline:** Items 7 and 11.\n\n> This is document analysis, not legal advice — route to the reviewing attorney before relying on it.`;
  } else if (/psa|assignment|purchase|sale agreement|clause/.test(p)) {
    body = `## PSA assignment clause\n\nThe assignment language in the **PSA** is moderately restrictive:\n\n- Assignment to an **affiliate / single-purpose entity** is permitted **with notice** — good for the buyer.\n- But it requires the assignee to assume **all** obligations and keeps the original buyer **jointly liable** until closing.\n\n**Recommend** negotiating a release of the original buyer's liability upon a permitted SPE assignment, and confirming the deposit follows the assignment.\n\n> Document analysis only — the attorney must approve any redline.`;
  } else if (/environment|phase|esa|rec|contamin/.test(p)) {
    body = `## Phase I environmental (ESA)\n\nNo **recognized environmental conditions (RECs)** were identified in the Phase I.\n\n- Historical use is consistent with retail/food service.\n- One **de minimis condition** noted (floor-drain near the prep area) — not a REC, no Phase II recommended.\n\n**Action:** none required for financing. Keep the report in the closing binder.\n\n> Advisory summary — confirm with the attorney and lender's environmental policy.`;
  } else if (/rent|lease|cap rate|valuation|econom|noi/.test(p)) {
    body = `## Lease economics vs. valuation\n\nUsing the **rent roll (T-12)** and **valuation estimate**:\n\n- Base rent **$229,500/yr** ÷ price **$4,250,000** ≈ **5.40% going-in cap** — consistent with the listed cap.\n- **3% annual bumps** are modeled correctly; year-5 rent supports a reversion in line with the estimate.\n- NNN structure means landlord expenses are minimal — NOI ≈ base rent.\n\n**Takeaway:** pricing is supported. Watch the option-renewal rent, which resets to market.\n\n> Starting estimate, not an appraisal or legal advice.`;
  } else {
    body = `## Analysis\n\nLooking at ${ctx}, here's a first pass on **"${prompt.trim()}"**:\n\n- The deal is at the **PSA** stage; the binding agreement governs from here.\n- Nothing in the attached files blocks advancing, but two items are still open: the **title commitment** Schedule B and the **estoppel** return.\n\n**Suggested next steps**\n1. Clear the open title exceptions.\n2. Confirm which inspections to order on the Due-diligence tab.\n3. Send the buyer a short summary of what's outstanding.\n\n> Tract Counsel AI prepares analysis and drafts — a licensed attorney must review before anyone relies on it.`;
  }
  return body;
}

async function runModel(prompt, attached) {
  const ctx = attached.length ? attached.map((d) => `- ${d.name} (${d.kind})${d.note ? " — " + d.note : ""}`).join("\n") : "(none attached)";
  const sys = `You are "Tract Counsel AI", an assistant for a commercial real estate transaction advisor. You are specially oriented to CRE contracts, inspection reports, zoning, title commitments, lease economics, and environmental surveys. Be concise, use markdown with short headings and lists, and ALWAYS end with a one-line reminder that this is document analysis/preparation, not legal advice, and an attorney must review. Deal: Starbucks NNN — Bayshore, $4.25M, 5.4% cap, FL, currently at the PSA stage.\n\nAttached documents:\n${ctx}\n\nAdvisor asks: ${prompt}`;
  try {
    if (window.claude && typeof window.claude.complete === "function") {
      const r = await window.claude.complete(sys);
      if (r && r.trim()) return r.trim();
    }
  } catch (e) { /* fall through */ }
  await new Promise((res) => setTimeout(res, 650));
  return cannedAnalysis(prompt, attached);
}

function AITab({ role }) {
  const st = useDealAI();
  const [msgs, setMsgs] = uSt([]);
  const [attached, setAttached] = uSt(["ds", "dc"]); // PSA + title pre-attached
  const [loading, setLoading] = uSt(false);
  const [pickOpen, setPickOpen] = uSt(false);
  const [copyMsg, setCopyMsg] = uSt(null);
  const pickRef = uRf(null);
  const scroller = uRf(null);
  const attachedDocs = attached.map((id) => st.documents.find((d) => d.id === id)).filter(Boolean);
  uEf(() => { if (scroller.current) scroller.current.scrollTop = scroller.current.scrollHeight; }, [msgs.length, loading]);

  const ask = async (text) => {
    const plain = typeof text === "string" ? text : "";
    setMsgs((m) => [...m, { role: "user", html: "<p>" + plain.replace(/</g, "&lt;").replace(/\n/g, "<br/>") + "</p>" }]);
    setLoading(true);
    const out = await runModel(plain, attachedDocs);
    setMsgs((m) => [...m, { role: "assistant", md: out, html: md2(out) }]);
    setLoading(false);
  };
  const sendFromComposer = (html) => {
    const tmp = document.createElement("div"); tmp.innerHTML = html;
    ask(tmp.textContent || "");
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }}>
      <div className="wrap" style={{ flex: 1, minHeight: 0, display: "flex", flexDirection: "column", paddingTop: 16, paddingBottom: 16 }}>
        {/* header */}
        <div style={{ display: "flex", alignItems: "center", gap: 12, paddingBottom: 14, borderBottom: "1px solid var(--line)" }}>
          <span style={{ width: 38, height: 38, borderRadius: 10, background: "var(--ink)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center" }}><AIcon name="sparkles" size={20} /></span>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 700, fontSize: 16, letterSpacing: "-.01em" }}>Tract Counsel AI</div>
            <div className="faint" style={{ fontSize: 12 }}>Trained for CRE contracts · inspections · title · zoning · lease economics · environmental</div>
          </div>
          <span className="pill pill--dark"><AIcon name="lock" size={13} />Advisor only</span>
          {msgs.length > 0 && <button className="btn btn--quiet btn--sm" onClick={() => setMsgs([])}><AIcon name="rotate-ccw" size={14} />New chat</button>}
        </div>

        {/* messages */}
        <div ref={scroller} style={{ flex: 1, minHeight: 0, overflowY: "auto", padding: "18px 0" }}>
          {msgs.length === 0 ? (
            <div style={{ maxWidth: 680, margin: "0 auto", paddingTop: 24 }}>
              <h2 style={{ fontSize: 22, fontWeight: 700, letterSpacing: "-.02em", textAlign: "center" }}>How can I help on this deal?</h2>
              <p className="muted" style={{ textAlign: "center", fontSize: 13.5, marginTop: 4 }}>Attach documents and ask. Copy any answer straight into the buyer or group chat.</p>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, marginTop: 22 }}>
                {SUGGESTIONS.map((s) => (
                  <button key={s.t} onClick={() => ask(s.p)} style={{ textAlign: "left", border: "1px solid var(--line-2)", background: "var(--card)", borderRadius: 12, padding: "13px 14px", cursor: "pointer", display: "flex", gap: 11, alignItems: "flex-start" }}
                    onMouseEnter={(e) => e.currentTarget.style.borderColor = "var(--line-strong)"} onMouseLeave={(e) => e.currentTarget.style.borderColor = "var(--line-2)"}>
                    <span style={{ color: "var(--ink-2)", marginTop: 1 }}><AIcon name={s.icon} size={18} /></span>
                    <span><span style={{ fontWeight: 600, fontSize: 13.5 }}>{s.t}</span><span style={{ display: "block", fontSize: 12, color: "var(--ink-3)", marginTop: 3, lineHeight: 1.45 }}>{s.p.slice(0, 78)}…</span></span>
                  </button>
                ))}
              </div>
            </div>
          ) : (
            <div style={{ maxWidth: 720, margin: "0 auto", display: "flex", flexDirection: "column", gap: 20 }}>
              {msgs.map((m, i) => m.role === "user" ? (
                <div key={i} className="fade" style={{ display: "flex", gap: 11, justifyContent: "flex-end" }}>
                  <div style={{ maxWidth: "78%", padding: "10px 14px", borderRadius: 13, background: "var(--green-soft)", border: "1px solid var(--green-line)" }}><ARich html={m.html} /></div>
                  <AAvatar who="advisor" size={30} />
                </div>
              ) : (
                <div key={i} className="fade" style={{ display: "flex", gap: 11 }}>
                  <span style={{ flex: "none", width: 30, height: 30, borderRadius: 8, background: "var(--ink)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center" }}><AIcon name="sparkles" size={16} /></span>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{ padding: "12px 16px", borderRadius: 13, background: "var(--card)", border: "1px solid var(--line)" }}><ARich html={m.html} /></div>
                    <div style={{ display: "flex", gap: 8, marginTop: 7 }}>
                      <button className="btn btn--ghost btn--sm" onClick={() => setCopyMsg(m)}><AIcon name="corner-up-right" size={14} />Copy to chat</button>
                      <button className="btn btn--quiet btn--sm" onClick={() => navigator.clipboard && navigator.clipboard.writeText(m.md || "")}><AIcon name="copy" size={14} />Copy text</button>
                    </div>
                  </div>
                </div>
              ))}
              {loading && <div className="fade" style={{ display: "flex", gap: 11 }}><span style={{ flex: "none", width: 30, height: 30, borderRadius: 8, background: "var(--ink)", color: "#fff", display: "flex", alignItems: "center", justifyContent: "center" }}><AIcon name="sparkles" size={16} /></span><div style={{ padding: "13px 16px", borderRadius: 13, background: "var(--card)", border: "1px solid var(--line)", color: "var(--ink-3)", fontSize: 13 }}><Dots /></div></div>}
            </div>
          )}
        </div>

        {/* attached docs + composer */}
        <div style={{ maxWidth: 760, margin: "0 auto", width: "100%" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginBottom: 8 }}>
            <span className="faint" style={{ fontSize: 11.5, fontWeight: 600 }}><AIcon name="paperclip" size={13} style={{ marginRight: 4 }} />Context</span>
            {attachedDocs.map((d) => <span key={d.id} className="pill" style={{ paddingRight: 5 }}>{d.name}<button onClick={() => setAttached((a) => a.filter((x) => x !== d.id))} style={{ border: "none", background: "transparent", cursor: "pointer", color: "var(--ink-3)", display: "inline-flex", padding: 0, marginLeft: 2 }}><AIcon name="x" size={13} /></button></span>)}
            <button ref={pickRef} className="pill" style={{ cursor: "pointer", borderStyle: "dashed" }} onClick={() => setPickOpen((v) => !v)}><AIcon name="plus" size={13} />Add document</button>
            {pickOpen && <APop anchorRef={pickRef} onClose={() => setPickOpen(false)} width={250}>
              <div className="pop__sec">Attach from library</div>
              {st.documents.map((d) => <button key={d.id} className="pop__item" disabled={attached.includes(d.id)} onClick={() => { setAttached((a) => [...a, d.id]); setPickOpen(false); }}><AIcon name="file-text" size={15} color="var(--ink-2)" /><span style={{ flex: 1 }}>{d.name}</span>{attached.includes(d.id) && <AIcon name="check" size={14} color="var(--green)" />}</button>)}
            </APop>}
          </div>
          <AComposer placeholder="Ask Tract Counsel AI about this deal…" onSend={sendFromComposer} sendLabel="Ask" />
          <div className="faint" style={{ fontSize: 11, textAlign: "center", marginTop: 7 }}>Tract Counsel AI assists the advisor. Output is preparation/analysis, not legal advice — an attorney reviews before anyone relies on it.</div>
        </div>
      </div>
      {copyMsg && <CopyToChat msg={copyMsg} role={role} onClose={() => setCopyMsg(null)} />}
    </div>
  );
}

function Dots() {
  const [n, setN] = uSt(0);
  uEf(() => { const t = setInterval(() => setN((x) => (x + 1) % 4), 380); return () => clearInterval(t); }, []);
  return <span>Analyzing{".".repeat(n)}</span>;
}

function CopyToChat({ msg, role, onClose }) {
  const threads = window.Panels.visibleThreads(role);
  const st = useDealAI();
  const [done, setDone] = uSt(false);
  const post = (tid) => { StoreAI.dispatch({ type: "CHAT_ADD", thread: tid, from: role, html: msg.html }); setDone(tid); };
  if (done) return <window.Toast msg={"Posted to " + st.threads[done].title} onDone={onClose} />;
  return (
    <AModal icon="corner-up-right" iconColor="var(--green)" title="Copy analysis into a chat" onClose={onClose} width={460}
      footer={<button className="btn btn--ghost" onClick={onClose}>Cancel</button>}>
      <p className="muted" style={{ fontSize: 13.5, marginTop: 0 }}>Share this analysis with the parties. The formatting is preserved.</p>
      <div style={{ display: "flex", flexDirection: "column", gap: 9 }}>
        {threads.map((tid) => (
          <button key={tid} onClick={() => post(tid)} style={{ display: "flex", alignItems: "center", gap: 11, padding: "13px 14px", border: "1px solid var(--line-2)", borderRadius: 11, background: "var(--card)", cursor: "pointer", textAlign: "left" }}
            onMouseEnter={(e) => e.currentTarget.style.background = "var(--bg-soft)"} onMouseLeave={(e) => e.currentTarget.style.background = "var(--card)"}>
            <AIcon name={st.threads[tid].kind === "group" ? "users" : "user"} size={18} color="var(--ink-2)" />
            <span style={{ flex: 1 }}><span style={{ fontWeight: 600 }}>{st.threads[tid].title}</span><span style={{ display: "block", fontSize: 12, color: "var(--ink-3)" }}>{st.threads[tid].members.map((m) => Dai.PEOPLE[m].name.split(" ")[0]).join(", ")}</span></span>
            <AIcon name="arrow-right" size={16} color="var(--ink-3)" />
          </button>
        ))}
      </div>
    </AModal>
  );
}

window.AITab = AITab;
