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

/* ---------- constants & helpers ---------- */
const SIG_FONTS = window.SIG_FONTS;
const fontById = window.fontById;
const todayStr = window.todayStr;
const FileDocView = window.FileDocView;

const DEFAULT_PROFILE = {
  name: "Nicholas Perez",
  title: "Co-Founder",
  company: "R3VY Inc / Element Longevity",
  email: "",
  sigFont: "dancing",
};

const load = (k, fb) => {
  try { const v = localStorage.getItem(k); return v ? JSON.parse(v) : fb; }
  catch (e) { return fb; }
};
const save = (k, v) => { try { localStorage.setItem(k, JSON.stringify(v)); } catch (e) {} };

const initials = (name) =>
  (name || "").trim().split(/\s+/).slice(0, 2).map((w) => w[0] || "").join("").toUpperCase() || "—";

const clampNum = (v, lo, hi) => Math.max(lo, Math.min(hi, v));

/* ---------- icons ---------- */
const Nib = ({ s = 18 }) => (
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none">
    <path d="M12 3 5.5 14.5 12 21l6.5-6.5L12 3Z" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="round"/>
    <path d="M12 21V9.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
    <circle cx="12" cy="8.5" r="1.5" fill="currentColor"/>
  </svg>
);
const Check = ({ s = 16 }) => (
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none"><path d="m5 12.5 4.5 4.5L19 7" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"/></svg>
);
const Download = ({ s = 16 }) => (
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none"><path d="M12 4v11m0 0 4-4m-4 4-4-4M5 19h14" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/></svg>
);
const Plus = ({ s = 16 }) => (
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none"><path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round"/></svg>
);
const X = ({ s = 18 }) => (
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none"><path d="m6 6 12 12M18 6 6 18" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"/></svg>
);
const Pen = ({ s = 16 }) => (
  <svg width={s} height={s} viewBox="0 0 24 24" fill="none"><path d="M14.5 5.5 18.5 9.5M4 20l1-4L16 5a2 2 0 0 1 3 3L8 19l-4 1Z" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"/></svg>
);

/* ---------- signature block ---------- */
function Party({ partyName, sig, justSigned, signHere, onSign }) {
  return (
    <div className="sig-block">
      <div className="sig-party">{partyName || "\u00A0"}</div>
      <div className={"sig-line sig-by" + (sig ? " signed" : "")}>
        <span className="sig-label">By:</span>
        <span className="sig-fill" style={signHere ? { cursor: "pointer" } : null} onClick={signHere ? onSign : null}>
          {sig ? (
            <span
              className={"ink" + (justSigned ? " sig-anim" : "")}
              style={{ fontFamily: fontById(sig.sigFont).family, fontSize: (38 * fontById(sig.sigFont).size) + "px" }}
            >{sig.name}</span>
          ) : signHere ? (
            <button className="sign-flag no-print" onClick={(e) => { e.stopPropagation(); onSign(); }}><Pen s={13} /> Sign here</button>
          ) : null}
        </span>
        {sig && (
          <span className={"stamp" + (justSigned ? " badge-pop" : "")}><Check s={11} /> Signed</span>
        )}
      </div>
      <div className="sig-line"><span className="sig-label">Name:</span><span className="sig-fill">{sig ? sig.name : ""}</span></div>
      <div className="sig-line"><span className="sig-label">Title:</span><span className="sig-fill">{sig ? sig.title : ""}</span></div>
      <div className="sig-line"><span className="sig-label">Email&nbsp;Address:</span><span className="sig-fill">{sig ? sig.email : ""}</span></div>
      <div className="sig-line"><span className="sig-label">Date&nbsp;signed:</span><span className="sig-fill">{sig ? sig.date : ""}</span></div>
    </div>
  );
}

/* ---------- document ---------- */
function DocumentView({ doc, signed, justSigned, signMode, onInplaceSign }) {
  return (
    <div className="doc-scroll scroll">
      <article className="paper" id="paper">
        <div className="doc-eyebrow">Confidential</div>
        <h1 className="doc-title">{doc.title}</h1>
        <div className="doc-rule"></div>
        <div className="doc-body">
          {doc.intro && <p className="intro">{doc.intro}</p>}
          {doc.sections.map((s, i) => (
            <div className="doc-section" key={i}>
              {s.p.map((para, j) => (
                <p key={j}>
                  {j === 0 && s.h && <><span className="sec-num">{i + 1}.&nbsp;</span><span className="sec-h">{s.h}</span>{" "}</>}
                  {para}
                </p>
              ))}
            </div>
          ))}
          {doc.closing && <p className="closing">{doc.closing}</p>}
          <div className="sig-grid">
            <Party partyName={doc.counterparty?.org || "\u00A0"} sig={null} />
            <Party
              partyName={signed ? signed.company : "\u00A0"}
              sig={signed}
              justSigned={justSigned}
              signHere={signMode === "inplace" && !signed}
              onSign={onInplaceSign}
            />
          </div>
        </div>
      </article>
    </div>
  );
}

/* ---------- sign sheet ---------- */
function SignSheet({ profile, onClose, onSign }) {
  const [f, setF] = useState({
    name: profile.name, title: profile.title, company: profile.company,
    email: profile.email, sigFont: profile.sigFont, date: todayStr(),
  });
  const set = (k) => (e) => setF((p) => ({ ...p, [k]: e.target.value }));
  const font = fontById(f.sigFont);
  const ready = f.name.trim().length > 0;

  return (
    <>
      <div className="sheet-scrim no-print" onClick={onClose}></div>
      <section className="sheet no-print" role="dialog" aria-label="Adopt your signature">
        <div className="sheet-handle"></div>
        <div className="sheet-head">
          <div>
            <h2>Adopt &amp; sign</h2>
            <p>This is how your signature will appear on the agreement.</p>
          </div>
          <button className="x-btn" onClick={onClose} aria-label="Close"><X /></button>
        </div>

        <div className="sheet-body scroll">
          <div>
            <p className="field-label">Your signature</p>
            <div className="sig-preview">
              <span className="pv-ink" style={{ fontFamily: font.family, fontSize: (58 * font.size) + "px" }}>
                {f.name || "Your name"}
              </span>
              <span className="pv-base"></span>
              <span className="pv-x">✕</span>
              <span className="pv-cap">SIGNATURE</span>
            </div>
            <div className="font-row">
              {SIG_FONTS.map((sf) => (
                <button key={sf.id} className={"font-chip" + (sf.id === f.sigFont ? " on" : "")}
                  onClick={() => setF((p) => ({ ...p, sigFont: sf.id }))}>
                  <span className="fc-name" style={{ fontFamily: sf.family }}>{(f.name || "Abc").split(" ")[0]}</span>
                  <span className="fc-lab">{sf.label}</span>
                </button>
              ))}
            </div>
          </div>

          <div>
            <p className="field-label">Your details</p>
            <div className="field"><input className="input" value={f.name} onChange={set("name")} placeholder="Full name" /></div>
            <div className="field"><input className="input" value={f.title} onChange={set("title")} placeholder="Title" /></div>
            <div className="field"><input className="input" value={f.company} onChange={set("company")} placeholder="Company" /></div>
            <div className="field"><input className="input" value={f.email} onChange={set("email")} placeholder="Email address" /></div>
            <div className="field"><input className="input" value={f.date} onChange={set("date")} placeholder="Date signed" /></div>
          </div>
        </div>

        <div className="sheet-foot">
          <p className="legal">By selecting Adopt &amp; sign, I agree this is my legal electronic signature under the U.S. ESIGN Act.</p>
          <div style={{ display: "flex", gap: 10 }}>
            <button className="btn ghost" onClick={onClose}>Cancel</button>
            <button className="btn accent" disabled={!ready} onClick={() => onSign(f)}><Pen /> Adopt &amp; sign</button>
          </div>
        </div>
      </section>
    </>
  );
}

/* ---------- profile modal ---------- */
function ProfileModal({ profile, onClose, onSave }) {
  const [f, setF] = useState(profile);
  const set = (k) => (e) => setF((p) => ({ ...p, [k]: e.target.value }));
  const font = fontById(f.sigFont);
  return (
    <div className="modal-scrim no-print" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <h2>Your signing profile</h2>
            <p>Saved on this device and reused on every agreement you sign.</p>
          </div>
          <button className="x-btn" onClick={onClose}><X /></button>
        </div>
        <div className="modal-body">
          <div className="sig-preview" style={{ marginBottom: 18 }}>
            <span className="pv-ink" style={{ fontFamily: font.family, fontSize: (54 * font.size) + "px" }}>{f.name || "Your name"}</span>
            <span className="pv-base"></span>
            <span className="pv-x">✕</span>
            <span className="pv-cap">SIGNATURE</span>
          </div>
          <div className="field"><p className="field-label">Full name</p><input className="input" value={f.name} onChange={set("name")} /></div>
          <div className="field"><p className="field-label">Title</p><input className="input" value={f.title} onChange={set("title")} /></div>
          <div className="field"><p className="field-label">Company</p><input className="input" value={f.company} onChange={set("company")} /></div>
          <div className="field"><p className="field-label">Email address</p><input className="input" value={f.email} onChange={set("email")} placeholder="you@company.com" /></div>
          <p className="field-label" style={{ marginTop: 4 }}>Default signature style</p>
          <div className="font-row" style={{ marginTop: 0 }}>
            {SIG_FONTS.map((sf) => (
              <button key={sf.id} className={"font-chip" + (sf.id === f.sigFont ? " on" : "")}
                onClick={() => setF((p) => ({ ...p, sigFont: sf.id }))}>
                <span className="fc-name" style={{ fontFamily: sf.family }}>{(f.name || "Abc").split(" ")[0]}</span>
                <span className="fc-lab">{sf.label}</span>
              </button>
            ))}
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn ghost" onClick={onClose}>Cancel</button>
          <button className="btn primary" onClick={() => onSave(f)}><Check /> Save profile</button>
        </div>
      </div>
    </div>
  );
}

/* ---------- new agreement modal ---------- */
function NewAgreementModal({ onClose, onLoad, onLoadFile }) {
  const [tab, setTab] = useState("upload");
  const [title, setTitle] = useState("");
  const [other, setOther] = useState("");
  const [text, setText] = useState("");
  const [err, setErr] = useState("");
  const [over, setOver] = useState(false);
  const inputRef = useRef();

  const build = () => {
    const blocks = text.trim().split(/\n\s*\n/).map((b) => b.trim()).filter(Boolean);
    const sections = blocks.map((b) => ({ h: "", p: [b] }));
    onLoad({
      title: title.trim() || "Agreement",
      intro: "",
      sections,
      closing: "ACCEPTED AND AGREED TO BY THE AUTHORIZED REPRESENTATIVE OF EACH PARTY AS OF THE LAST DATE SET FORTH BELOW.",
      counterparty: { org: other.trim() || "\u00A0" },
    });
  };

  const handleFile = (f) => {
    if (!f) return;
    const ext = (f.name.split(".").pop() || "").toLowerCase();
    const kind = ext === "pdf" ? "pdf" : ext === "docx" ? "docx" : null;
    if (!kind) {
      setErr(ext === "doc"
        ? "Old .doc files aren’t supported — re-save as .docx and try again."
        : "Please choose a PDF or a Word (.docx) file.");
      return;
    }
    setErr("");
    const reader = new FileReader();
    reader.onload = () => onLoadFile({ name: f.name, kind, dataUrl: reader.result });
    reader.readAsDataURL(f);
  };

  return (
    <div className="modal-scrim no-print" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <h2>Add a document</h2>
            <p>Upload your own PDF or Word file and sign it as-is — or paste plain text.</p>
          </div>
          <button className="x-btn" onClick={onClose}><X /></button>
        </div>
        <div className="modal-body">
          <div className="seg" style={{ marginBottom: 18 }}>
            <button className={tab === "upload" ? "on" : ""} onClick={() => setTab("upload")}>Upload file</button>
            <button className={tab === "paste" ? "on" : ""} onClick={() => setTab("paste")}>Paste text</button>
          </div>

          {tab === "upload" ? (
            <>
              <div
                className={"dropzone" + (over ? " over" : "")}
                onClick={() => inputRef.current.click()}
                onDragOver={(e) => { e.preventDefault(); setOver(true); }}
                onDragLeave={() => setOver(false)}
                onDrop={(e) => { e.preventDefault(); setOver(false); handleFile(e.dataTransfer.files[0]); }}
              >
                <div className="dz-ic">
                  <svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M12 16V5m0 0 4 4m-4-4-4 4M5 19h14" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/></svg>
                </div>
                <div className="dz-t">Drop a file here, or click to browse</div>
                <div className="dz-s">Your document renders exactly as it is — nothing is recreated.</div>
                <div className="dz-formats"><span>PDF</span><span>DOCX</span></div>
                <input ref={inputRef} type="file" accept=".pdf,.docx,application/pdf" style={{ display: "none" }}
                  onChange={(e) => handleFile(e.target.files[0])} />
              </div>
              {err && <p style={{ color: "#9a3434", fontSize: 12.5, marginTop: 12, fontWeight: 600 }}>{err}</p>}
            </>
          ) : (
            <>
              <div className="field"><p className="field-label">Document title</p><input className="input" value={title} onChange={(e) => setTitle(e.target.value)} placeholder="e.g. Mutual Non-Disclosure Agreement" /></div>
              <div className="field"><p className="field-label">Counterparty (the other signer)</p><input className="input" value={other} onChange={(e) => setOther(e.target.value)} placeholder="e.g. Acme Inc." /></div>
              <p className="field-label">Agreement text</p>
              <textarea className="ta" value={text} onChange={(e) => setText(e.target.value)} placeholder="Paste the body of the agreement here. Separate paragraphs with a blank line." />
            </>
          )}
        </div>
        <div className="modal-foot">
          <button className="btn ghost" onClick={onClose}>Cancel</button>
          {tab === "paste" && <button className="btn primary" disabled={!text.trim()} onClick={build}><Check /> Load document</button>}
        </div>
      </div>
    </div>
  );
}

/* ---------- app ---------- */
function App() {
  const [profile, setProfile] = useState(() => load("signet.profile", DEFAULT_PROFILE));
  const [doc, setDoc] = useState(() => load("signet.doc", window.NDA_DOC));
  const [signed, setSigned] = useState(() => load("signet.signed", null));
  const [justSigned, setJustSigned] = useState(false);
  const [sheet, setSheet] = useState(false);
  const [signMode, setSignMode] = useState(() => load("signet.signMode", "panel"));
  const [profileOpen, setProfileOpen] = useState(false);
  const [newOpen, setNewOpen] = useState(false);
  // uploaded-file mode
  const [source, setSource] = useState(() => load("signet.source", "structured"));
  const [file, setFile] = useState(() => load("signet.file", null));
  const [stamps, setStamps] = useState(() => {
    const s = load("signet.stamps", []);
    // legacy stamps (pre page-anchoring) used a different coordinate system — drop them
    return Array.isArray(s) && s.every((x) => typeof x.page === "number") ? s : [];
  });

  useEffect(() => save("signet.profile", profile), [profile]);
  useEffect(() => save("signet.doc", doc), [doc]);
  useEffect(() => save("signet.signed", signed), [signed]);
  useEffect(() => save("signet.signMode", signMode), [signMode]);
  useEffect(() => save("signet.source", source), [source]);
  useEffect(() => { try { save("signet.file", file); } catch (e) {} }, [file]);
  useEffect(() => save("signet.stamps", stamps), [stamps]);

  const scrollToSig = () => {
    const c = document.querySelector(".doc-scroll");
    const g = document.querySelector(".sig-grid");
    if (c && g) c.scrollTo({ top: c.scrollTop + g.getBoundingClientRect().top - c.getBoundingClientRect().top - 110, behavior: "smooth" });
  };

  const doSign = (f) => {
    setSigned(f);
    setSheet(false);
    setJustSigned(true);
    setTimeout(scrollToSig, 90);
    setTimeout(() => setJustSigned(false), 1400);
  };

  const inplaceSign = () => doSign({
    name: profile.name, title: profile.title, company: profile.company,
    email: profile.email, sigFont: profile.sigFont, date: todayStr(),
  });

  const jumpToSig = () => scrollToSig();

  const loadDoc = (d) => {
    setSource("structured");
    setFile(null);
    setDoc(d);
    setSigned(null);
    setNewOpen(false);
    setTimeout(() => { const s = document.querySelector(".doc-scroll"); if (s) s.scrollTo({ top: 0, behavior: "smooth" }); }, 60);
  };

  const loadFile = (f) => {
    setSource("file");
    setFile(f);
    setStamps([]);
    setNewOpen(false);
  };

  const FIELD_DEFS = [
    { kind: "sig",   label: "Signature", size: 42 },
    { kind: "name",  label: "Name",      size: 16 },
    { kind: "title", label: "Title",     size: 16 },
    { kind: "email", label: "Email",     size: 16 },
    { kind: "date",  label: "Date",      size: 16 },
    { kind: "text",  label: "Text",      size: 16 },
  ];

  const addField = (kind) => {
    const pages = window.signetPageNodes(document.querySelector(".filedoc-stage"));
    const scroll = document.querySelector(".filedoc-scroll");
    let page = 0, xPct = 0.3, yPct = 0.3;
    if (pages.length && scroll) {
      const cr = scroll.getBoundingClientRect();
      const cy = cr.top + scroll.clientHeight * 0.45;
      const cx = cr.left + scroll.clientWidth / 2;
      // page under the viewport-center line (else nearest)
      let best = 0, bestDist = Infinity;
      pages.forEach((p, i) => {
        const r = p.getBoundingClientRect();
        if (cy >= r.top && cy <= r.bottom) { best = i; bestDist = -1; }
        else if (bestDist !== -1) {
          const d = Math.min(Math.abs(cy - r.top), Math.abs(cy - r.bottom));
          if (d < bestDist) { bestDist = d; best = i; }
        }
      });
      page = best;
      const r = pages[page].getBoundingClientRect();
      xPct = clampNum((cx - r.left) / r.width, 0.05, 0.9);
      yPct = clampNum((cy - r.top) / r.height, 0.03, 0.95);
    }
    yPct = clampNum(yPct + (stamps.length % 5) * 0.022, 0.02, 0.97);
    const def = FIELD_DEFS.find((d) => d.kind === kind);
    const textFor = {
      sig: profile.name, name: profile.name, title: profile.title,
      email: profile.email || "name@company.com", date: todayStr(), text: "Text",
    };
    const realKind = kind === "sig" ? "sig" : "text";
    setStamps((s) => [...s, {
      id: Date.now() + "" + Math.round(Math.random() * 1e4),
      kind: realKind, text: textFor[kind], page, xPct, yPct, size: def.size,
    }]);
  };

  const openSampleNda = () => { setSource("structured"); setFile(null); setDoc(window.NDA_DOC); setSigned(null); };

  const unsign = () => { setSigned(null); };

  const fileMode = source === "file" && file;

  return (
    <div className="app">
      <header className="topbar no-print">
        <div className="brand">
          <span className="brand-mark"><Nib /></span>
          <span className="brand-name">Signet</span>
        </div>
        <div className="topbar-doc">
          <span className="t">{fileMode ? file.name : doc.title}</span>
          <span className="s">
            {fileMode
              ? (stamps.length ? stamps.length + " field" + (stamps.length > 1 ? "s" : "") + " placed · drag to adjust" : "Your document — add fields below")
              : (doc.counterparty?.org && doc.counterparty.org.trim() ? "with " + doc.counterparty.org : "Awaiting signature")}
          </span>
        </div>
        <div className="topbar-right">
          {!fileMode && !signed && (
            <div className="seg" role="tablist" aria-label="Signing mode">
              <button className={signMode === "panel" ? "on" : ""} onClick={() => setSignMode("panel")} title="Adopt your signature in a panel, then apply it">Guided</button>
              <button className={signMode === "inplace" ? "on" : ""} onClick={() => setSignMode("inplace")} title="Insert your signature directly on the document">On document</button>
            </div>
          )}
          {fileMode && (
            <button className="btn sm ghost" onClick={openSampleNda} title="Back to the sample NDA">Sample NDA</button>
          )}
          <button className="btn sm" onClick={() => setNewOpen(true)}><Plus /> New</button>
          <button className="profile-chip" onClick={() => setProfileOpen(true)} title="Edit your signing profile">
            <span className="avatar">{initials(profile.name)}</span>
            <span className="chip-name">{profile.name.split(" ")[0]}</span>
          </button>
        </div>
      </header>

      {fileMode ? (
        <>
          <div className="field-bar no-print">
            <span className="fb-label">Add to document</span>
            <div className="fb-chips">
              {FIELD_DEFS.map((d) => (
                <button key={d.kind} className={"fb-chip" + (d.kind === "sig" ? " sig" : "")} onClick={() => addField(d.kind)}>
                  <span className="fb-ic">{d.kind === "sig" ? <Pen s={14} /> : <Plus s={13} />}</span>
                  {d.label}
                </button>
              ))}
            </div>
          </div>
          <FileDocView file={file} profile={profile} stamps={stamps} setStamps={setStamps} />
        </>
      ) : (
        <DocumentView doc={doc} signed={signed} justSigned={justSigned} signMode={signMode} onInplaceSign={inplaceSign} />
      )}

      <div className="actionbar no-print">
        <div className="actionbar-inner">
          <span className={"ab-dot" + ((signed || (fileMode && stamps.length)) ? " done" : "")}></span>
          {fileMode ? (
            stamps.length ? (
              <>
                <span className="ab-text"><b>{stamps.length} field{stamps.length > 1 ? "s" : ""}</b> placed — <span className="ab-sub">drag to adjust</span></span>
                <button className="btn sm ghost" style={{ color: "var(--paper)" }} onClick={() => setStamps([])}>Clear</button>
                <button className="btn sm" onClick={() => window.print()}><Download /> Download PDF</button>
              </>
            ) : (
              <>
                <span className="ab-text">Add fields from the bar above, then drag them into place</span>
                <button className="btn accent sm" style={{ height: 38, padding: "0 16px" }} onClick={() => addField("sig")}><Pen /> Add signature</button>
              </>
            )
          ) : signed ? (
            <>
              <span className="ab-text"><b>Signed</b> · <span className="ab-sub">{signed.date}</span></span>
              <button className="btn sm ghost" style={{ color: "var(--paper)" }} onClick={unsign}>Re-sign</button>
              <button className="btn sm" onClick={() => window.print()}><Download /> Download PDF</button>
            </>
          ) : signMode === "inplace" ? (
            <>
              <span className="ab-text">Click <b>Sign here</b> on the document to insert your signature</span>
              <button className="btn accent sm" style={{ height: 38, padding: "0 16px" }} onClick={jumpToSig}>Go to signature</button>
            </>
          ) : (
            <>
              <span className="ab-text"><b>1 signature</b> required — yours</span>
              <button className="btn accent sm" style={{ height: 38, padding: "0 18px" }} onClick={() => setSheet(true)}><Pen /> Sign document</button>
            </>
          )}
        </div>
      </div>

      {sheet && <SignSheet profile={profile} onClose={() => setSheet(false)} onSign={doSign} />}
      {profileOpen && <ProfileModal profile={profile} onClose={() => setProfileOpen(false)} onSave={(p) => { setProfile(p); setProfileOpen(false); }} />}
      {newOpen && <NewAgreementModal onClose={() => setNewOpen(false)} onLoad={loadDoc} onLoadFile={loadFile} />}
    </div>
  );
}

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