/* Cloud-backed diagrams library + recents + initial empty-state CTA. */
{
  const { useEffect, useMemo, useRef, useState } = React;

  function fmtAgo(then) {
    if (!then) return "";
    const s = Math.max(0, Math.round((Date.now() - then) / 1000));
    if (s < 60) return "just now";
    const m = Math.round(s / 60); if (m < 60) return `${m}m ago`;
    const h = Math.round(m / 60); if (h < 24) return `${h}h ago`;
    const d = Math.round(h / 24); if (d < 14) return `${d}d ago`;
    return new Date(then).toLocaleDateString();
  }

  function tsToMillis(t) {
    if (!t) return 0;
    if (typeof t.toMillis === "function") return t.toMillis();
    if (typeof t.seconds === "number") return t.seconds * 1000;
    return 0;
  }

  function buildShareLink(id) {
    const u = new URL(location.href);
    u.search = `?id=${encodeURIComponent(id)}`;
    u.hash = "";
    return u.toString();
  }

  const UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;

  /* Accept any of: raw UUID, "?id=<uuid>" URL, full share link, or any string
     containing a UUID-shaped substring. Returns null if no UUID is found. */
  function extractDiagramId(input) {
    const s = (input || "").trim();
    if (!s) return null;
    try {
      const u = new URL(s);
      const q = u.searchParams.get("id");
      if (q && UUID_RE.test(q)) return q.toLowerCase();
    } catch { /* not a URL — fall through */ }
    const m = s.match(UUID_RE);
    return m ? m[0].toLowerCase() : null;
  }

  function OpenLinkInput({ onOpened, currentId }) {
    const [value, setValue] = useState("");
    const [busy, setBusy] = useState(false);
    const [error, setError] = useState("");

    async function handleSubmit() {
      setError("");
      const id = extractDiagramId(value);
      if (!id) {
        setError("Paste a share link or diagram ID.");
        return;
      }
      if (id === currentId) {
        setError("Already open.");
        return;
      }
      setBusy(true);
      try {
        const exists = window.CloudLibrary && await window.CloudLibrary.getDiagramOnce(id);
        if (!exists) {
          setError("No diagram found at that link.");
          setBusy(false);
          return;
        }
        // Optimistically record as a recent before navigating so the UI updates instantly.
        window.Recents && window.Recents.recordRecent({
          id,
          name: exists.name,
          lastEditorName: exists.lastEditorName,
        });
        onOpened(id);
        setValue("");
      } catch (e) {
        setError(e.message || "Failed to load.");
      } finally {
        setBusy(false);
      }
    }

    return (
      <div className="open-link">
        <div className="open-link-row">
          <span className="open-link-icon"><Icon.share /></span>
          <input
            type="text"
            placeholder="Paste a share link or diagram ID"
            value={value}
            onChange={(e) => { setValue(e.target.value); if (error) setError(""); }}
            onKeyDown={(e) => { if (e.key === "Enter") handleSubmit(); }}
            disabled={busy}
            spellCheck={false}
          />
          <button
            className="btn primary"
            onClick={handleSubmit}
            disabled={busy || !value.trim()}
          >
            {busy ? <><Icon.spinner /> Opening…</> : <>Open</>}
          </button>
        </div>
        {error && <div className="open-link-error">{error}</div>}
      </div>
    );
  }

  function RecentList({ recents, currentId, onOpen, onClose, onRemove, onCopyLink, linkCopiedId }) {
    if (!recents || recents.length === 0) return null;
    return (
      <div className="lib-section">
        <div className="lib-section-h">
          <Icon.history />
          <span>Recently opened</span>
          <span className="count">{recents.length}</span>
        </div>
        <ul className="lib-list">
          {recents.map(r => {
            const isCurrent = r.id === currentId;
            return (
              <li key={r.id} className={`lib-item ${isCurrent ? "current" : ""}`}>
                <div className="lib-item-main">
                  <button
                    className="lib-name"
                    onClick={() => { onOpen(r.id); onClose(); }}
                    title="Open this diagram"
                  >
                    {r.name || r.id.slice(0, 8)}
                    {isCurrent && <span className="lib-current-pill">open</span>}
                  </button>
                  <div className="lib-meta">
                    last opened {fmtAgo(r.lastOpenedAt)}
                    {r.lastEditorName && <> · last edited by {r.lastEditorName}</>}
                  </div>
                </div>
                <div className="lib-actions">
                  <button
                    className="iconbtn"
                    title={linkCopiedId === r.id ? "Link copied!" : "Copy share link"}
                    onClick={() => onCopyLink(r.id)}
                  >
                    {linkCopiedId === r.id ? <Icon.check /> : <Icon.share />}
                  </button>
                  <button
                    className="iconbtn"
                    title="Remove from recents"
                    onClick={() => onRemove(r.id)}
                  ><Icon.close /></button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }

  function LibraryModal({
    open, onClose,
    user, onSignIn,
    diagrams, loading,
    currentId,
    recents,
    onRemoveRecent,
    onLoad, onCreate, onRename, onDelete,
    onMigrate, onDeclineMigration, legacyCount,
  }) {
    const [text, setText] = useState("");
    const [name, setName] = useState("");
    const [mode, setMode] = useState("library"); // library | new
    const [renamingId, setRenamingId] = useState(null);
    const [renameDraft, setRenameDraft] = useState("");
    const [busy, setBusy] = useState(false);
    const [linkCopiedId, setLinkCopiedId] = useState(null);
    const [confirmDeleteId, setConfirmDeleteId] = useState(null);
    const fileRef = useRef(null);

    // Recents filtered to those not in the owned library (signed-in case).
    const recentsToShow = useMemo(() => {
      if (!recents || recents.length === 0) return [];
      if (!user) return recents;
      const ownedIds = new Set((diagrams || []).map(d => d.id));
      return recents.filter(r => !ownedIds.has(r.id));
    }, [recents, diagrams, user]);

    useEffect(() => {
      if (open) {
        setText("");
        setName("");
        setRenamingId(null);
        setConfirmDeleteId(null);
        setBusy(false);
        const hasContent = (diagrams && diagrams.length > 0) || recentsToShow.length > 0;
        setMode(hasContent ? "library" : "new");
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [open]);

    if (!open) return null;

    async function handleCreate() {
      const src = text.trim();
      if (!user) return;
      const finalName = (name.trim() || (typeof suggestName === "function" ? suggestName(src) : "")) || "Untitled diagram";
      setBusy(true);
      try {
        await onCreate({ name: finalName.slice(0, 200), content: src });
      } finally {
        setBusy(false);
      }
    }

    function handleFile(e) {
      const file = e.target.files?.[0];
      if (!file) return;
      const reader = new FileReader();
      reader.onload = () => {
        const src = String(reader.result || "");
        setText(src);
        if (!name) setName(file.name.replace(/\.(puml|plantuml|txt)$/i, ""));
        setMode("new");
      };
      reader.readAsText(file);
    }

    function commitRename(id) {
      const n = renameDraft.trim();
      if (n) onRename(id, n.slice(0, 200));
      setRenamingId(null);
    }

    async function handleCopyLink(id) {
      const link = buildShareLink(id);
      try {
        await navigator.clipboard.writeText(link);
      } catch {
        const ta = document.createElement("textarea");
        ta.value = link;
        document.body.appendChild(ta); ta.select();
        try { document.execCommand("copy"); } catch {}
        document.body.removeChild(ta);
      }
      setLinkCopiedId(id);
      setTimeout(() => setLinkCopiedId(prev => prev === id ? null : prev), 1600);
    }

    const offerMigration = !!user && legacyCount > 0;

    const handleOpenedFromLink = (id) => { onLoad(id); onClose(); };

    const openLinkBlock = (
      <OpenLinkInput onOpened={handleOpenedFromLink} currentId={currentId} />
    );

    const recentsBlock = (
      <RecentList
        recents={recentsToShow}
        currentId={currentId}
        onOpen={onLoad}
        onClose={onClose}
        onRemove={onRemoveRecent}
        onCopyLink={handleCopyLink}
        linkCopiedId={linkCopiedId}
      />
    );

    const pendingDelete = (diagrams || []).find(d => d.id === confirmDeleteId) || null;

    return (
      <>
      <div className="modal-backdrop" onClick={onClose}>
        <div className="modal lib-modal" onClick={(e) => e.stopPropagation()}>
          <div className="modal-head">
            <Icon.upload />
            <h3>PlantUML diagrams</h3>
            <button className="close iconbtn" onClick={onClose}><Icon.close /></button>
          </div>

          {!user ? (
            <div className="modal-body">
              {openLinkBlock}
              {recentsBlock}
              <div className="lib-cta">
                <Icon.googleG />
                <p><strong>Sign in to create and edit diagrams.</strong></p>
                <p>Your diagrams are stored in the Lab900 cloud so you can open them from any browser and see who edited what.</p>
                <button className="btn primary" onClick={onSignIn}>
                  <Icon.googleG /> Sign in with Google
                </button>
                <p className="hint" style={{ marginTop: 12 }}>
                  Recently opened diagrams above are bookmarked in this browser.
                </p>
              </div>
            </div>
          ) : (
            <>
              <div className="lib-tabs">
                <button
                  className={`lib-tab ${mode === "library" ? "active" : ""}`}
                  onClick={() => setMode("library")}
                >
                  My library <span className="count">{diagrams.length}</span>
                </button>
                <button
                  className={`lib-tab ${mode === "new" ? "active" : ""}`}
                  onClick={() => setMode("new")}
                >
                  <Icon.plus /> New diagram
                </button>
              </div>
              <div className="modal-body">
                {offerMigration && (
                  <div className="share-banner" style={{ marginBottom: 12 }}>
                    <Icon.upload />
                    <span>
                      <span className="label">{legacyCount} local diagram{legacyCount === 1 ? "" : "s"} found.</span>
                      {" "}Import to your cloud library?
                    </span>
                    <button className="btn primary" onClick={onMigrate} disabled={busy}>Import</button>
                    <button className="btn" onClick={onDeclineMigration}>Dismiss</button>
                  </div>
                )}

                {mode === "library" && (
                  <>
                    {openLinkBlock}
                    {recentsBlock}
                    <div className="lib-section">
                      {recentsToShow.length > 0 && (
                        <div className="lib-section-h">
                          <Icon.upload />
                          <span>My library</span>
                          <span className="count">{diagrams.length}</span>
                        </div>
                      )}
                      {loading ? (
                        <div className="lib-empty"><Icon.spinner /> loading library…</div>
                      ) : diagrams.length === 0 ? (
                        <div className="lib-empty">
                          <p>You haven't created any diagrams yet.</p>
                          <button className="btn primary" onClick={() => setMode("new")}>
                            <Icon.plus /> New diagram
                          </button>
                        </div>
                      ) : (
                        <ul className="lib-list">
                          {diagrams.map(d => {
                            const updatedAt = tsToMillis(d.updatedAt);
                            const isCurrent = d.id === currentId;
                            return (
                              <li key={d.id} className={`lib-item ${isCurrent ? "current" : ""}`}>
                                <div className="lib-item-main">
                                  {renamingId === d.id ? (
                                    <input
                                      className="lib-rename-input"
                                      value={renameDraft}
                                      autoFocus
                                      onChange={(e) => setRenameDraft(e.target.value)}
                                      onKeyDown={(e) => {
                                        if (e.key === "Enter") commitRename(d.id);
                                        else if (e.key === "Escape") setRenamingId(null);
                                      }}
                                      onBlur={() => commitRename(d.id)}
                                    />
                                  ) : (
                                    <button
                                      className="lib-name"
                                      onClick={() => { onLoad(d.id); onClose(); }}
                                      title="Open this diagram"
                                    >
                                      {d.name}
                                      {isCurrent && <span className="lib-current-pill">open</span>}
                                    </button>
                                  )}
                                  <div className="lib-meta">
                                    {d.currentContent ? `${Math.max(1, Math.round(d.currentContent.length / 1024))} KB` : "empty"}
                                    {updatedAt > 0 && <> · updated {fmtAgo(updatedAt)}</>}
                                    {d.lastEditorName && <> · by {d.lastEditorName}</>}
                                  </div>
                                </div>
                                <div className="lib-actions">
                                  <button
                                    className="iconbtn"
                                    title={linkCopiedId === d.id ? "Link copied!" : "Copy share link"}
                                    onClick={() => handleCopyLink(d.id)}
                                  >
                                    {linkCopiedId === d.id ? <Icon.check /> : <Icon.share />}
                                  </button>
                                  <button
                                    className="iconbtn"
                                    title="Rename"
                                    onClick={() => { setRenamingId(d.id); setRenameDraft(d.name); }}
                                  ><Icon.edit /></button>
                                  <button
                                    className="iconbtn lib-delete"
                                    title="Delete diagram"
                                    onClick={() => setConfirmDeleteId(d.id)}
                                  ><Icon.trash /></button>
                                </div>
                              </li>
                            );
                          })}
                        </ul>
                      )}
                    </div>
                  </>
                )}

                {mode === "new" && (
                  <div className="lib-new">
                    <label className="lib-field">
                      <span>Name</span>
                      <input
                        type="text"
                        value={name}
                        onChange={(e) => setName(e.target.value)}
                        placeholder={text && typeof suggestName === "function" ? suggestName(text) : "My data model"}
                        maxLength={200}
                      />
                    </label>
                    <label className="lib-field">
                      <span>PUML source (optional — you can paste later)</span>
                      <textarea
                        value={text}
                        onChange={(e) => setText(e.target.value)}
                        placeholder={"@startuml\nclass Foo {\n  - bar : Baz\n}\nFoo --> Baz\n@enduml"}
                        spellCheck={false}
                      />
                    </label>
                    <div className="lib-new-actions">
                      <input
                        ref={fileRef}
                        type="file"
                        accept=".puml,.plantuml,.txt,text/plain"
                        style={{ display: "none" }}
                        onChange={handleFile}
                      />
                      <button className="btn" onClick={() => fileRef.current?.click()}>
                        <Icon.upload /> Upload file
                      </button>
                      <span className="hint">Stored in your Lab900 cloud library. Share via link.</span>
                    </div>
                  </div>
                )}
              </div>
              <div className="modal-foot">
                {mode === "new" ? (
                  <>
                    <span className="hint">A new diagram is created in your library.</span>
                    <button className="btn" onClick={() => { setText(""); setName(""); }} disabled={busy}>Clear</button>
                    <button className="btn primary" onClick={handleCreate} disabled={busy}>
                      {busy ? <><Icon.spinner /> Creating…</> : <><Icon.plus /> Create</>}
                    </button>
                  </>
                ) : (
                  <>
                    <span className="hint">Click a diagram to open it.</span>
                    <button className="btn" onClick={onClose}>Close</button>
                  </>
                )}
              </div>
            </>
          )}
        </div>
      </div>
      <ConfirmDialog
        open={!!pendingDelete}
        danger
        title="Delete diagram?"
        message={pendingDelete
          ? `"${pendingDelete.name || pendingDelete.id.slice(0, 8)}" will be permanently deleted, along with its version history. This can't be undone.`
          : ""}
        confirmLabel="Delete"
        onCancel={() => setConfirmDeleteId(null)}
        onConfirm={async () => {
          const id = confirmDeleteId;
          setConfirmDeleteId(null);
          if (onDelete) await onDelete(id);
        }}
      />
      </>
    );
  }

  function EmptyState({ onOpen, signedIn, onSignIn }) {
    return (
      <div className="empty-state">
        <div className="empty-state-card">
          <Icon.graph />
          <h2>No diagram loaded</h2>
          {signedIn ? (
            <>
              <p>Create a new PlantUML class diagram or open one from your library.</p>
              <button className="btn primary" onClick={onOpen}>
                <Icon.upload /> Open library
              </button>
            </>
          ) : (
            <>
              <p>Sign in to create diagrams, or open a recently viewed diagram.</p>
              <button className="btn primary" onClick={onSignIn}>
                <Icon.googleG /> Sign in with Google
              </button>
              <button className="btn" onClick={onOpen} style={{ marginTop: 8 }}>
                <Icon.history /> Recently opened
              </button>
            </>
          )}
          <p className="hint">Diagrams are stored in the Lab900 cloud — share by link, versioned automatically.</p>
        </div>
      </div>
    );
  }

  function suggestName(src) {
    const m = /class\s+([A-Za-z_][\w]*)/.exec(src || "");
    if (m) return m[1];
    return "Untitled diagram";
  }

  window.LibraryModal = LibraryModal;
  window.EmptyState = EmptyState;
  window.suggestName = suggestName;
}
