// Vanday DAM — Wave 2: trust & governance
//   • PermissionsModal — FT-17 per-folder permissions
//   • ShareModal       — GP-02 create a branded share portal
//   • SharePortalPage  — GP-02 the external-facing portal view
//   • AuditLogSection  — GP-11 activity audit log
//   • ExpiryField      — FT-15 expiration block for asset preview
//
// All of these are designed to play with the existing Vanday palette
// (warm off-white, orange accent, mono captions) and use the same
// component vocabulary as the rest of the app.

const ROLE_DESCRIPTIONS = {
  Owner:       "Full control · can change permissions and billing",
  Admin:       "Manage folder + invite people",
  Editor:      "Upload, edit, delete, publish",
  Contributor: "Upload + edit own assets",
  Commenter:   "View + leave comments",
  Viewer:      "Read-only access",
};

function RoleSelect({ value, onChange, options = ["Owner", "Admin", "Editor", "Contributor", "Commenter", "Viewer"], disabled }) {
  return (
    <select
      className="role-select"
      value={value}
      disabled={disabled}
      onChange={(e) => onChange && onChange(e.target.value)}
      onClick={(e) => e.stopPropagation()}
    >
      {options.map((r) => {
        const val = typeof r === "string" ? r : r.value;
        const label = typeof r === "string" ? r : (r.label || r.value);
        return <option key={val} value={val}>{label}</option>;
      })}
    </select>
  );
}

// ============================================================
// PermissionsModal — FT-17
// ============================================================
function PermissionsModal({ folder, onClose }) {
  const initial = FOLDER_PERMS[folder.id] || { members: [], link: "workspace" };
  const [members, setMembers] = React.useState(
    initial.members.map(([uid, role]) => ({ userId: uid, role }))
  );
  const [link, setLink] = React.useState(initial.link);
  const [inviteEmail, setInviteEmail] = React.useState("");
  const [inviteRole, setInviteRole] = React.useState("Editor");

  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [onClose]);

  const userById = (id) => USERS.find((u) => u.id === id);
  const changeRole = (uid, role) => setMembers((ms) => ms.map((m) => m.userId === uid ? { ...m, role } : m));
  const removeMember = (uid) => setMembers((ms) => ms.filter((m) => m.userId !== uid));
  const sendInvite = () => {
    if (!inviteEmail) return;
    const newId = `pending-${Date.now()}`;
    setMembers((ms) => [...ms, { userId: newId, role: inviteRole, pending: true, email: inviteEmail }]);
    setInviteEmail("");
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal perm-modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <div style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 11, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--text-faint)", fontWeight: 500, marginBottom: 4 }}>
              <IcShield size={11} /> Permissions
            </div>
            <h2 className="modal-title">{folder.name}</h2>
            <div style={{ fontSize: 12.5, color: "var(--text-muted)", marginTop: 4 }}>
              Restrict who can see, edit, and publish assets in this folder. Changes apply immediately.
            </div>
          </div>
          <button className="btn ghost sm" onClick={onClose}><IcClose size={14} /></button>
        </div>

        <div className="perm-body">
          {/* Invite row — hidden during free beta. Team workspaces are a paid feature
              we haven't shipped yet; the row will return when plans launch. */}
          <div className="perm-section" style={{ opacity: 0.55 }}>
            <div className="perm-h">Invite people · coming soon</div>
            <div style={{ fontSize: 12.5, color: "var(--text-muted)", marginTop: 4 }}>
              Team workspaces aren't available on the free beta plan yet. We'll
              email you the moment invites unlock.
            </div>
          </div>

          {/* Members list */}
          <div className="perm-section">
            <div className="perm-h-row">
              <div className="perm-h">Members</div>
              <span className="perm-count">{members.length} people</span>
            </div>
            <div className="perm-list">
              {members.map((m) => {
                const u = userById(m.userId);
                const isOwner = m.role === "Owner";
                return (
                  <div className="perm-row" key={m.userId}>
                    <span className="pill-user" style={{ background: "transparent", padding: 0 }}>
                      <span className="av" style={{
                        background: u?.color || "var(--surface-sunken)",
                        width: 28, height: 28, fontSize: 11,
                      }}>
                        {u ? u.name.split(" ").map((s) => s[0]).join("") : (m.email || "?")[0].toUpperCase()}
                      </span>
                    </span>
                    <div className="perm-row-main">
                      <div className="perm-row-name">
                        {u ? u.name : (m.email || "Pending invite")}
                        {m.pending && <span className="perm-pending">Pending</span>}
                      </div>
                      <div className="perm-row-email">{u ? u.email : m.email}</div>
                    </div>
                    <div className="perm-row-role" title={ROLE_DESCRIPTIONS[m.role]}>
                      <RoleSelect
                        value={m.role}
                        onChange={(r) => changeRole(m.userId, r)}
                        disabled={isOwner}
                      />
                    </div>
                    <button
                      className="perm-row-remove"
                      onClick={() => removeMember(m.userId)}
                      disabled={isOwner}
                      title={isOwner ? "Owner can't be removed" : "Remove access"}
                    >
                      <IcClose size={13} />
                    </button>
                  </div>
                );
              })}
            </div>
          </div>

          {/* Link sharing */}
          <div className="perm-section">
            <div className="perm-h">General access</div>
            <div className="perm-access">
              {[
                { id: "restricted", title: "Restricted",       sub: "Only invited people can find this folder",  icon: <IcShield size={15} /> },
                { id: "workspace",  title: "Workspace",        sub: "Everyone in Vanday Studio can find it",   icon: <IcUsers size={15} /> },
                { id: "anyone",     title: "Anyone with link", sub: "External link share — no account needed",  icon: <IcExternal size={15} /> },
              ].map((opt) => (
                <button
                  key={opt.id}
                  className={`perm-access-row ${link === opt.id ? "is-on" : ""}`}
                  onClick={() => setLink(opt.id)}
                >
                  <span className="perm-access-ic">{opt.icon}</span>
                  <span style={{ flex: 1, minWidth: 0 }}>
                    <span className="perm-access-title">{opt.title}</span>
                    <span className="perm-access-sub">{opt.sub}</span>
                  </span>
                  {link === opt.id && <IcCheck size={14} style={{ color: "var(--accent)" }} />}
                </button>
              ))}
            </div>
          </div>

          {/* Inheritance hint */}
          <div className="perm-section perm-inherit">
            <IcLink size={12} />
            Inherits from <strong>Vanday Studio · Library</strong>. Sub-folders inside <strong>{folder.name}</strong> will inherit these permissions unless overridden.
          </div>
        </div>

        <div className="modal-foot perm-foot">
          <div style={{ fontSize: 12, color: "var(--text-faint)" }}>
            <IcInfo size={11} style={{ verticalAlign: "middle", marginRight: 4 }} />
            Permission changes are recorded in the activity audit log.
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <button className="btn" onClick={onClose}>Done</button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ============================================================
// ShareModal — GP-02
// ============================================================
function ShareModal({ folder, asset, onClose, onOpenPortal }) {
  // Determine the candidate assets and default selection.
  // When invoked from a single asset preview, candidates = the asset + its related links.
  // When invoked from a folder, candidates = all assets in that folder.
  const candidates = React.useMemo(() => {
    if (asset) {
      const relatedIds = (_relatedStore[asset.id] || getRelated(asset.id)).map((r) => r.id);
      const relatedAssets = relatedIds
        .map((id) => ASSETS.find((a) => a.id === id))
        .filter(Boolean);
      return [asset, ...relatedAssets];
    }
    return ASSETS.filter((a) => !folder || a.folder === folder.id);
  }, [asset, folder]);

  // Default: include the source asset AND all related (user can uncheck what they don't want).
  const [picked, setPicked] = React.useState(
    () => new Set(candidates.map((a) => a.id))
  );
  const togglePick = (id) => setPicked((s) => {
    const n = new Set(s);
    n.has(id) ? n.delete(id) : n.add(id);
    return n;
  });
  const pickAll = () => setPicked(new Set(candidates.map((a) => a.id)));
  const pickNone = () => setPicked(new Set(asset ? [asset.id] : []));

  const [name, setName] = React.useState(
    asset ? `${asset.name.replace(/\.[^.]+$/, "")} — review`
          : (folder ? `${folder.name} — client review` : "Share portal")
  );
  const [password, setPassword] = React.useState(true);
  const [passwordVal, setPasswordVal] = React.useState("");
  const [expiry, setExpiry] = React.useState("2026-06-12");
  const [allowDownload, setAllowDownload] = React.useState(true);
  const [watermark, setWatermark] = React.useState(false);
  const [brandColor, setBrandColor] = React.useState("oklch(0.58 0.16 32)");

  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [onClose]);

  // Real portal URL — gets replaced with the server-issued one after Create.
  const [createdShare, setCreatedShare] = React.useState(null);
  const portalUrl = createdShare
    ? `${window.location.host}${createdShare.url}`
    : `vanday.com/p/${name.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 28)}-${Math.random().toString(36).slice(2, 6)}`;

  const confirm = async () => {
    if (createdShare) {
      window.open(createdShare.url, "_blank", "noopener");
      return;
    }
    const pickedAssets = Array.from(picked)
      .map((id) => candidates.find((a) => a.id === id))
      .filter((a) => a && a.isServer && !a.isServerVariant);
    if (pickedAssets.length === 0) {
      window.alert("Pick at least one uploaded asset — sample images can't be shared via real portal links.");
      return;
    }
    const expiryDays = Math.max(
      1,
      Math.ceil((new Date(expiry).getTime() - Date.now()) / (24 * 60 * 60 * 1000)),
    );
    try {
      const r = await VandayAPI.createShare({
        name,
        assetIds: pickedAssets.map((a) => a.id),
        password: password ? passwordVal : "",
        expiryDays,
        allowDownload,
        watermark,
        brandColor,
      });
      setCreatedShare(r);
      // Open the real portal in a new tab so the user can see what visitors see.
      window.open(r.url, "_blank", "noopener");
    } catch (err) {
      window.alert("Could not create portal: " + err.message);
    }
  };

  const copyUrl = async () => {
    if (!createdShare) return;
    const full = `${window.location.origin}${createdShare.url}`;
    try { await navigator.clipboard.writeText(full); } catch {}
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal share-modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <div style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 11, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--text-faint)", fontWeight: 500, marginBottom: 4 }}>
              <IcExternal size={11} /> Share portal
            </div>
            <h2 className="modal-title">Create a portal</h2>
            <div style={{ fontSize: 12.5, color: "var(--text-muted)", marginTop: 4 }}>
              A branded, password-protected page for sharing with people outside your workspace.
            </div>
          </div>
          <button className="btn ghost sm" onClick={onClose}><IcClose size={14} /></button>
        </div>

        <div className="share-body">
          {/* Left: settings */}
          <div className="share-settings">
            <div className="share-kv">
              <label>Portal name</label>
              <input
                className="up-text"
                value={name}
                onChange={(e) => setName(e.target.value)}
              />
            </div>

            <div className="share-kv">
              <label>Public URL</label>
              <div className="share-url">
                <span>{createdShare ? `http://${portalUrl}` : `https://${portalUrl}`}</span>
                <button className="btn sm" onClick={copyUrl} disabled={!createdShare}>
                  {createdShare ? "Copy" : "Copy (after create)"}
                </button>
              </div>
            </div>

            <div className="share-section-h">Access</div>
            <button className="share-toggle-row" onClick={() => setPassword((v) => !v)}>
              <div>
                <div className="share-toggle-h"><IcShield size={12} /> Password protect</div>
                <div className="share-toggle-sub">Require a password to view the portal</div>
              </div>
              <span className={`toggle ${password ? "on" : ""}`} />
            </button>
            {password && (
              <input
                className="up-text"
                style={{ marginTop: -4, marginBottom: 12 }}
                placeholder="Set a password"
                value={passwordVal}
                onChange={(e) => setPasswordVal(e.target.value)}
              />
            )}
            <div className="share-kv">
              <label><IcCalendar size={11} /> Expires on</label>
              <input
                className="up-text"
                type="date"
                value={expiry}
                onChange={(e) => setExpiry(e.target.value)}
              />
            </div>

            <div className="share-section-h">Asset behavior</div>
            <button className="share-toggle-row" onClick={() => setAllowDownload((v) => !v)}>
              <div>
                <div className="share-toggle-h"><IcDownload size={12} /> Allow downloads</div>
                <div className="share-toggle-sub">Visitors can download originals</div>
              </div>
              <span className={`toggle ${allowDownload ? "on" : ""}`} />
            </button>
            <button className="share-toggle-row" onClick={() => setWatermark((v) => !v)}>
              <div>
                <div className="share-toggle-h"><IcImage size={12} /> Watermark previews</div>
                <div className="share-toggle-sub">Diagonal watermark on view-only previews</div>
              </div>
              <span className={`toggle ${watermark ? "on" : ""}`} />
            </button>

            <div className="share-section-h">Branding</div>
            <div className="share-kv">
              <label>Logo</label>
              <button className="btn sm" style={{ alignSelf: "flex-start" }}>
                <IcPlus size={12} /> Upload SVG or PNG
              </button>
            </div>
            <div className="share-kv">
              <label>Accent color</label>
              <div className="share-swatches">
                {[
                  "oklch(0.58 0.16 32)",
                  "oklch(0.42 0.13 240)",
                  "oklch(0.55 0.14 155)",
                  "oklch(0.55 0.14 290)",
                  "oklch(0.22 0.04 200)",
                  "oklch(0.5 0.18 24)",
                ].map((c) => (
                  <button
                    key={c}
                    className={`share-swatch ${brandColor === c ? "is-on" : ""}`}
                    style={{ background: c }}
                    onClick={() => setBrandColor(c)}
                    title={c}
                  />
                ))}
              </div>
            </div>
          </div>

          {/* Right: preview — cards in here are the selection surface */}
          <div className="share-preview">
            <div className="share-preview-tabs">
              <div className="share-pick-summary">
                <div>
                  <div className="share-pick-h">Assets in this portal</div>
                  <div className="share-pick-sub">
                    Click a card to {asset ? "include / exclude" : "deselect"} it.{asset ? " Source asset is always included." : ""}
                  </div>
                </div>
                <div className="share-pick-actions">
                  <span className="share-pick-count">
                    <strong>{picked.size}</strong> of {candidates.length}
                  </span>
                  <button className="btn sm" onClick={pickAll}>All</button>
                  <button className="btn sm" onClick={pickNone}>{asset ? "Only this" : "None"}</button>
                </div>
              </div>
            </div>
            <div className="share-preview-shell" style={{ "--portal-accent": brandColor }}>
              <div className="share-preview-frame">
                <div className="portal-chrome-mini">
                  <div className="portal-chrome-dot" />
                  <div className="portal-chrome-dot" />
                  <div className="portal-chrome-dot" />
                  <div className="portal-chrome-url">{portalUrl}</div>
                </div>
                <div className="portal-mini">
                  <div className="portal-mini-head">
                    <div className="portal-mini-logo" style={{ background: brandColor }}>A</div>
                    <div>
                      <div className="portal-mini-h">{name}</div>
                      <div className="portal-mini-sub">
                        {picked.size} asset{picked.size === 1 ? "" : "s"} · expires {new Date(expiry).toLocaleDateString("en-US", { month: "short", day: "numeric" })}
                      </div>
                    </div>
                  </div>
                  <div className="portal-mini-grid">
                    {candidates.length === 0 && (
                      <div style={{ gridColumn: "1 / -1", padding: 20, textAlign: "center", fontSize: 11, color: "var(--text-faint)" }}>
                        Nothing to share.
                      </div>
                    )}
                    {candidates.map((a) => {
                      const isSource = asset && a.id === asset.id;
                      const on = picked.has(a.id);
                      return (
                        <button
                          type="button"
                          key={a.id}
                          className={`portal-mini-card share-pick-card ${on ? "is-on" : "is-off"} ${isSource ? "is-source" : ""}`}
                          onClick={() => !isSource && togglePick(a.id)}
                          disabled={isSource}
                          title={isSource ? "Source asset — always included" : (on ? "Click to exclude" : "Click to include")}
                        >
                          <div className="portal-mini-thumb" style={{ backgroundImage: `url(${a.url})` }}>
                            {watermark && on && <div className="portal-watermark-mini">VANDAY · PREVIEW</div>}
                            <span className={`share-pick-check ${on ? "is-on" : ""}`}>
                              {on && <IcCheck size={11} />}
                            </span>
                            {isSource && <span className="share-pick-source-tag">Source</span>}
                            {!on && !isSource && <div className="share-pick-overlay" />}
                          </div>
                        </button>
                      );
                    })}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div className="modal-foot">
          <div style={{ fontSize: 12, color: "var(--text-muted)" }}>
            <IcInfo size={11} style={{ verticalAlign: "middle", marginRight: 4 }} />
            All visitor activity is recorded in the audit log.
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <button className="btn" onClick={onClose}>Cancel</button>
            <button className="btn accent" onClick={confirm} disabled={picked.size === 0}>
              {createdShare ? "Open portal" : "Create portal"}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ============================================================
// SharePortalPage — GP-02 external view
// ============================================================
function SharePortalPage({ portal, onClose }) {
  // Respect explicit assetIds (single-asset share) over folder selection.
  const assets = portal.assetIds && portal.assetIds.length
    ? portal.assetIds.map((id) => ASSETS.find((a) => a.id === id)).filter(Boolean)
    : ASSETS.filter((a) => !portal.folder || a.folder === portal.folder).slice(0, 12);

  return (
    <div className="portal-shell" style={{ "--portal-accent": portal.brandColor }}>
      <header className="portal-topbar">
        <div className="portal-brand">
          <div className="portal-logo">A</div>
          <span>Vanday Studio</span>
        </div>
        <div className="portal-meta">
          <span><IcShield size={11} /> Password protected</span>
          <span className="dot" />
          <span><IcCalendar size={11} /> Expires {new Date(portal.expiry).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}</span>
          <span className="dot" />
          <button className="btn sm" onClick={onClose}>
            <IcClose size={12} /> Close preview
          </button>
        </div>
      </header>

      <main className="portal-main">
        <section className="portal-hero">
          <div>
            <div className="portal-pill">Shared with you</div>
            <h1 className="portal-h">{portal.name}</h1>
            <p className="portal-sub">
              {assets.length} asset{assets.length === 1 ? "" : "s"} shared by {(window.VandaySession.getActiveUser() || { name: "Vanday user" }).name} from Vanday Studio.
              {portal.download ? " Click any image to view full size, or download the originals below." : " Click any image to view full size."}
            </p>
          </div>
          <div className="portal-progress">
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5, color: "var(--text-muted)" }}>
                <span>Assets</span>
                <strong style={{ color: "var(--text)", fontFamily: "var(--font-mono)" }}>{assets.length}</strong>
              </div>
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5, color: "var(--text-muted)" }}>
                <span>Expires</span>
                <strong style={{ color: "var(--text)", fontFamily: "var(--font-mono)" }}>
                  {new Date(portal.expiry).toLocaleDateString("en-US", { month: "short", day: "numeric" })}
                </strong>
              </div>
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5, color: "var(--text-muted)" }}>
                <span>Downloads</span>
                <strong style={{ color: "var(--text)", fontFamily: "var(--font-mono)" }}>
                  {portal.download ? "Allowed" : "Disabled"}
                </strong>
              </div>
            </div>
            {portal.download && (
              <button className="btn portal-btn" style={{ marginTop: 14 }}>
                <IcDownload size={13} /> Download all (.zip)
              </button>
            )}
          </div>
        </section>

        <section className="portal-grid">
          {assets.map((a) => (
            <article key={a.id} className="portal-card">
              <div className="portal-card-thumb">
                <img src={a.url} alt={a.name} loading="lazy" />
                {portal.watermark && (
                  <>
                    <div className="portal-watermark">VANDAY STUDIO · PREVIEW</div>
                    <div className="portal-watermark wm-2">VANDAY STUDIO · PREVIEW</div>
                  </>
                )}
              </div>
              <div className="portal-card-body">
                <div className="portal-card-name">{a.name}</div>
                <div className="portal-card-meta">
                  {a.tags.slice(0, 3).map((t) => <span key={t} className="portal-tag">{t}</span>)}
                </div>
                {portal.download && (
                  <div className="portal-card-actions">
                    <button className="portal-action"><IcDownload size={12} /> Download original</button>
                  </div>
                )}
              </div>
            </article>
          ))}
        </section>
      </main>

      <footer className="portal-foot">
        <span>Powered by <strong>Vanday</strong></span>
        <span>This portal is private. Don't share the link.</span>
      </footer>
    </div>
  );
}

// ============================================================
// AuditLogSection — GP-11
// ============================================================
const ACTION_META = {
  "login":         { label: "Signed in",            color: "oklch(0.6 0.005 80)",  icon: <IcUsers size={12} /> },
  "upload":        { label: "Uploaded",              color: "oklch(0.62 0.16 235)",  icon: <IcUpload size={12} /> },
  "publish":       { label: "Published",             color: "oklch(0.62 0.15 145)",  icon: <IcSend size={12} /> },
  "publish.fail":  { label: "Publish failed",        color: "oklch(0.55 0.2 24)",    icon: <IcSend size={12} /> },
  "permission":    { label: "Permission change",     color: "oklch(0.55 0.14 290)",  icon: <IcShield size={12} /> },
  "delete":        { label: "Deleted",                color: "oklch(0.55 0.2 24)",   icon: <IcTrash size={12} /> },
  "restore":       { label: "Restored",               color: "oklch(0.62 0.15 145)", icon: <IcCheck size={12} /> },
  "share.create":  { label: "Share portal created",   color: "oklch(0.58 0.16 32)",  icon: <IcExternal size={12} /> },
  "share.view":    { label: "Portal viewed",          color: "oklch(0.66 0.06 80)",  icon: <IcEye size={12} /> },
  "plan.change":   { label: "Plan changed",           color: "oklch(0.55 0.16 70)",  icon: <IcCard size={12} /> },
  "integration":   { label: "Integration",            color: "oklch(0.55 0.14 220)", icon: <IcLink size={12} /> },
  "expire.set":    { label: "Expiry set",             color: "oklch(0.62 0.14 80)",  icon: <IcCalendar size={12} /> },
  "invite.accept": { label: "Joined workspace",       color: "oklch(0.55 0.14 155)", icon: <IcPlus size={12} /> },
};

function AuditLogSection() {
  const [actor, setActor] = React.useState("all");
  const [action, setAction] = React.useState("all");
  const [range, setRange] = React.useState("7d");
  const [query, setQuery] = React.useState("");

  let rows = AUDIT_LOG;
  if (actor !== "all") rows = rows.filter((r) => r.actor === actor);
  if (action !== "all") rows = rows.filter((r) => r.action === action);
  if (query) {
    const q = query.toLowerCase();
    rows = rows.filter((r) =>
      (r.target || "").toLowerCase().includes(q) ||
      (USERS.find((u) => u.id === r.actor)?.name || "").toLowerCase().includes(q) ||
      r.action.toLowerCase().includes(q)
    );
  }

  return (
    <>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end" }}>
        <div>
          <h1 className="settings-h1">Audit log</h1>
          <p className="settings-sub">
            Every meaningful action in this workspace. Retained for 1 year on Team plan, unlimited on Business.
          </p>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn"><IcDownload size={13} /> Export CSV</button>
        </div>
      </div>

      <div className="section-card" style={{ padding: 0, overflow: "hidden" }}>
        <div className="audit-toolbar">
          <div className="search" style={{ width: 280, background: "var(--surface-soft)" }}>
            <IcSearch size={14} />
            <input
              placeholder="Search by actor, target, or action…"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
            />
          </div>
          <select className="role-select audit-select" value={actor} onChange={(e) => setActor(e.target.value)}>
            <option value="all">All actors</option>
            {USERS.map((u) => <option key={u.id} value={u.id}>{u.name}</option>)}
          </select>
          <select className="role-select audit-select" value={action} onChange={(e) => setAction(e.target.value)}>
            <option value="all">All actions</option>
            {Object.entries(ACTION_META).map(([id, m]) => <option key={id} value={id}>{m.label}</option>)}
          </select>
          <select className="role-select audit-select" value={range} onChange={(e) => setRange(e.target.value)}>
            <option value="24h">Last 24 hours</option>
            <option value="7d">Last 7 days</option>
            <option value="30d">Last 30 days</option>
            <option value="all">All time</option>
          </select>
          <span style={{ marginLeft: "auto", fontSize: 12, color: "var(--text-muted)" }}>
            {rows.length} event{rows.length === 1 ? "" : "s"}
          </span>
        </div>

        <div className="audit-list">
          {rows.map((r) => {
            const u = USERS.find((x) => x.id === r.actor);
            const meta = ACTION_META[r.action] || { label: r.action, color: "var(--text-muted)", icon: <IcInfo size={12} /> };
            return (
              <div className="audit-row" key={r.id}>
                <div className="audit-time">{r.at}</div>
                <div className="audit-actor">
                  <span className="av" style={{
                    background: u?.color || "var(--surface-sunken)",
                    width: 24, height: 24, fontSize: 10,
                    borderRadius: "50%", color: "white",
                    display: "inline-grid", placeItems: "center", fontWeight: 600,
                  }}>
                    {u ? u.name.split(" ").map((s) => s[0]).join("") : "?"}
                  </span>
                  <div>
                    <div className="audit-actor-name">{u?.name || "Unknown"}</div>
                    <div className="audit-actor-email">{u?.email}</div>
                  </div>
                </div>
                <div className="audit-action">
                  <span className="audit-pill" style={{ color: meta.color, borderColor: "currentColor", background: "transparent" }}>
                    {meta.icon}
                    {meta.label}
                  </span>
                </div>
                <div className="audit-target">{r.target || <span style={{ color: "var(--text-faint)" }}>—</span>}</div>
                <div className="audit-ip">
                  <div style={{ fontFamily: "var(--font-mono)" }}>{r.ip}</div>
                  <div style={{ fontSize: 11, color: "var(--text-faint)" }}>{r.device}</div>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </>
  );
}

// ============================================================
// ExpiryField — FT-15 inline block for asset preview
// ============================================================
function ExpiryField({ asset }) {
  const e = asset.expiry;
  const [editing, setEditing] = React.useState(false);

  if (!e && !editing) {
    return (
      <div className="field-block">
        <div className="field-label">
          <IcCalendar size={11} /> Expiration
        </div>
        <button
          className="btn sm"
          style={{ borderStyle: "dashed", color: "var(--text-muted)" }}
          onClick={() => setEditing(true)}
        >
          <IcPlus size={11} /> Set expiry date
        </button>
      </div>
    );
  }

  return (
    <div className="field-block">
      <div className="field-label">
        <IcCalendar size={11} /> Expiration
        <span className="tag" style={{ marginLeft: "auto", fontSize: 9.5,
          background: e?.status === "expired" ? "oklch(0.95 0.04 24)" : e?.status === "soon" ? "oklch(0.95 0.06 80)" : "var(--surface-sunken)",
          color:      e?.status === "expired" ? "oklch(0.5 0.2 24)" : e?.status === "soon" ? "oklch(0.5 0.16 80)" : "var(--text-muted)",
        }}>
          {e?.status === "expired" ? "EXPIRED" : e?.status === "soon" ? `${e.daysLeft}d LEFT` : "OK"}
        </span>
      </div>
      <div className="expiry-block">
        <div className="expiry-row">
          <span style={{ color: "var(--text-muted)", fontSize: 12 }}>Expires</span>
          <span style={{ fontFamily: "var(--font-mono)", fontSize: 12.5 }}>{e?.date || "Not set"}</span>
        </div>
        <div className="expiry-row">
          <span style={{ color: "var(--text-muted)", fontSize: 12 }}>License</span>
          <span style={{ fontSize: 12.5 }}>{e?.license || "Not set"}</span>
        </div>
        <div className="expiry-row">
          <span style={{ color: "var(--text-muted)", fontSize: 12 }}>Take down on expiry</span>
          <span className={`toggle ${e?.takedown ? "on" : ""}`} />
        </div>
        {e?.status === "expired" && (
          <div className="expiry-note is-err">
            <IcInfo size={11} />
            This asset has expired. New publishes are blocked and active posts will be taken down on supported channels.
          </div>
        )}
        {e?.status === "soon" && (
          <div className="expiry-note">
            <IcInfo size={11} />
            Notifies the owner 14, 7, and 1 days before expiry. Active posts will be taken down automatically.
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, {
  PermissionsModal,
  RoleSelect,
  ShareModal,
  SharePortalPage,
  AuditLogSection,
  ExpiryField,
});
