/* global React, PR */
const { useState, useEffect, useRef, useCallback } = React;
const { I, Avatar } = PR;

const USER_COLORS = [
  "#7C8BA1","#A37BC8","#5BA89E","#C8895B",
  "#5B7BC8","#B85B7B","#5BA860","#C8B45B",
];

// ── Shared helpers ─────────────────────────────────────────────────────────

async function api(url, opts = {}) {
  const resp = await fetch(url, {
    headers: { "Content-Type": "application/json" },
    ...opts,
  });
  if (!resp.ok) {
    const err = await resp.json().catch(() => ({}));
    throw new Error(err.detail || `HTTP ${resp.status}`);
  }
  return resp.json();
}

// ── Cover image picker ────────────────────────────────────────────────────

function CoverImagePicker({ value, onChange }) {
  const fileInputRef = useRef(null);
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState(null);
  const [dragOver, setDragOver] = useState(false);

  const uploadFile = async (file) => {
    if (!file || !file.type.startsWith("image/")) {
      setError("Only images are allowed");
      return;
    }
    setUploading(true);
    setError(null);
    try {
      const form = new FormData();
      form.append("file", file);
      const resp = await fetch("/api/upload", { method: "POST", body: form });
      if (!resp.ok) {
        const err = await resp.json().catch(() => ({}));
        throw new Error(err.detail || "Upload failed");
      }
      const { url } = await resp.json();
      onChange(url);
    } catch (e) {
      setError(e.message);
    } finally {
      setUploading(false);
    }
  };

  const handlePaste = useCallback((e) => {
    const items = e.clipboardData?.items;
    if (!items) return;
    for (const item of items) {
      if (item.type.startsWith("image/")) {
        e.preventDefault();
        uploadFile(item.getAsFile());
        return;
      }
    }
  }, []);

  useEffect(() => {
    document.addEventListener("paste", handlePaste);
    return () => document.removeEventListener("paste", handlePaste);
  }, [handlePaste]);

  const handleDrop = (e) => {
    e.preventDefault();
    setDragOver(false);
    const file = e.dataTransfer.files[0];
    if (file) uploadFile(file);
  };

  return (
    <div className="cover-picker">
      {value ? (
        <div className="cover-preview">
          <img src={value} alt="Cover" onError={(e) => { e.target.style.display = "none"; }} />
          <button type="button" className="cover-clear" onClick={() => onChange("")}>✕</button>
        </div>
      ) : (
        <div
          className={"cover-drop-zone" + (dragOver ? " drag-over" : "") + (uploading ? " uploading" : "")}
          onClick={() => !uploading && fileInputRef.current?.click()}
          onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
          onDragLeave={() => setDragOver(false)}
          onDrop={handleDrop}
        >
          {uploading ? (
            <span>Uploading…</span>
          ) : (
            <>
              <span className="cover-drop-icon">{I.plus}</span>
              <span>Click to upload · drag & drop · Ctrl+V to paste</span>
            </>
          )}
        </div>
      )}
      <input
        ref={fileInputRef}
        type="file"
        accept="image/*"
        style={{ display: "none" }}
        onChange={(e) => { const f = e.target.files[0]; if (f) uploadFile(f); e.target.value = ""; }}
      />
      {error && <div style={{ color: "var(--kill)", fontSize: 11, marginTop: 5 }}>{error}</div>}
    </div>
  );
}

// ── Overlay ────────────────────────────────────────────────────────────────

function Overlay({ onClose, children, wide }) {
  const ref = useRef(null);

  useEffect(() => {
    const handler = (e) => e.key === "Escape" && onClose();
    document.addEventListener("keydown", handler);
    return () => document.removeEventListener("keydown", handler);
  }, [onClose]);

  return (
    <div
      className="modal-overlay"
      onMouseDown={(e) => e.target === ref.current && onClose()}
      ref={ref}
    >
      <div className={"modal-box" + (wide ? " modal-box-wide" : "")}>{children}</div>
    </div>
  );
}

function ModalHead({ title, onClose }) {
  return (
    <div className="modal-head">
      <h2>{title}</h2>
      <button className="btn btn-ghost" style={{ padding: "0 8px", minWidth: 28 }} onClick={onClose}>✕</button>
    </div>
  );
}

function ModalFoot({ onClose, submitLabel, submitting, danger }) {
  return (
    <div className="modal-foot">
      <button type="button" className="btn btn-ghost" onClick={onClose} disabled={submitting}>Cancel</button>
      <button
        type="submit"
        className="btn btn-primary"
        disabled={submitting}
        style={danger ? { background: "var(--kill)", borderColor: "var(--kill)" } : {}}
      >
        {submitting ? "Saving…" : submitLabel}
      </button>
    </div>
  );
}

function ErrorBanner({ msg }) {
  if (!msg) return null;
  return (
    <div style={{
      background: "color-mix(in oklch, var(--kill) 12%, transparent)",
      border: "1px solid color-mix(in oklch, var(--kill) 30%, var(--border))",
      color: "var(--kill)", borderRadius: "var(--radius)", padding: "10px 12px",
      fontSize: 12, marginBottom: 16,
    }}>{msg}</div>
  );
}

// ── Tag selector ───────────────────────────────────────────────────────────

function TagSelector({ selected, options, onChange }) {
  const toggle = (tag) =>
    onChange(selected.includes(tag) ? selected.filter(t => t !== tag) : [...selected, tag]);
  return (
    <div className="tags-wrap">
      {selected.map(t => (
        <span key={t} className="tag-chip tag-chip-selected">
          {t}
          <span style={{ cursor: "pointer", marginLeft: 3, opacity: 0.7 }} onClick={() => toggle(t)}>×</span>
        </span>
      ))}
      {options.filter(t => !selected.includes(t)).map(t => (
        <span key={t} className="tag-chip" onClick={() => toggle(t)}>{t}</span>
      ))}
    </div>
  );
}

// ── New Hypothesis modal ───────────────────────────────────────────────────

function NewHypothesisModal({ data, user, onClose, onSuccess }) {
  const [form, setForm] = useState({
    title: "", core_loop: "", tags: [],
    key_metric: "", target: "", risk: "med",
    summary: "", cover_url: "", author_id: user?.id || "",
  });
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const submit = async (e) => {
    e.preventDefault();
    if (!form.title.trim()) { setError("Title is required"); return; }
    setSubmitting(true); setError(null);
    try {
      const h = await api("/api/hypotheses", {
        method: "POST",
        body: JSON.stringify({ ...form, author_id: parseInt(form.author_id) || user?.id }),
      });
      onSuccess(h.id);
    } catch (err) {
      setError(err.message);
      setSubmitting(false);
    }
  };

  return (
    <Overlay onClose={onClose}>
      <ModalHead title="New hypothesis" onClose={onClose} />
      <form onSubmit={submit}>
        <div className="modal-body">
          <ErrorBanner msg={error} />
          <div className="form-group">
            <label className="form-label">Title *</label>
            <input className="form-input" value={form.title}
              onChange={e => set("title", e.target.value)}
              placeholder="e.g. Merge Dungeon — auto-battle variant" autoFocus />
          </div>
          <div className="form-group">
            <label className="form-label">Core loop</label>
            <textarea className="form-textarea" value={form.core_loop}
              onChange={e => set("core_loop", e.target.value)}
              placeholder="Player does X → gets Y → enables Z" rows={3} />
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Key metric</label>
              <input className="form-input" value={form.key_metric}
                onChange={e => set("key_metric", e.target.value)}
                placeholder="D1 Retention" />
            </div>
            <div className="form-group">
              <label className="form-label">Target</label>
              <input className="form-input" value={form.target}
                onChange={e => set("target", e.target.value)}
                placeholder="≥ 35%" />
            </div>
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Risk</label>
              <select className="form-select" value={form.risk} onChange={e => set("risk", e.target.value)}>
                <option value="low">Low</option>
                <option value="med">Medium</option>
                <option value="high">High</option>
              </select>
            </div>
            <div className="form-group">
              <label className="form-label">Author</label>
              <select className="form-select" value={form.author_id}
                onChange={e => set("author_id", e.target.value)}>
                {data.authors.map(a => (
                  <option key={a.id} value={a.id}>{a.name}</option>
                ))}
              </select>
            </div>
          </div>
          <div className="form-group">
            <label className="form-label">Genre tags</label>
            <TagSelector selected={form.tags} options={data.tags} onChange={v => set("tags", v)} />
          </div>
          <div className="form-group">
            <label className="form-label">Summary</label>
            <textarea className="form-textarea" value={form.summary}
              onChange={e => set("summary", e.target.value)}
              placeholder="One-paragraph description of the concept" rows={2} />
          </div>
          <div className="form-group" style={{ marginBottom: 0 }}>
            <label className="form-label">Cover image</label>
            <CoverImagePicker value={form.cover_url} onChange={v => set("cover_url", v)} />
          </div>
        </div>
        <ModalFoot onClose={onClose} submitLabel="Create hypothesis" submitting={submitting} />
      </form>
    </Overlay>
  );
}

// ── Edit Hypothesis modal ──────────────────────────────────────────────────

function EditHypothesisModal({ rndId, data, user, onClose, onSuccess }) {
  const h = data.hypotheses.find(x => x.id === rndId);
  const [form, setForm] = useState(() => ({
    title: h?.title || "",
    core_loop: h?.coreLoop || "",
    tags: h?.tags || [],
    key_metric: h?.keyMetric !== "TBD" ? (h?.keyMetric || "") : "",
    target: h?.target !== "—" ? (h?.target || "") : "",
    current_value: h?.current !== "—" ? (h?.current || "") : "",
    risk: h?.risk || "med",
    summary: h?.summary || "",
    cover_url: h?.coverUrl || "",
    author_id: h?.author || (user?.id ? String(user.id) : ""),
  }));
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);

  if (!h) return null;
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const submit = async (e) => {
    e.preventDefault();
    setSubmitting(true); setError(null);
    try {
      await api(`/api/hypotheses/${rndId}`, {
        method: "PUT",
        body: JSON.stringify({ ...form, author_id: parseInt(form.author_id) || undefined }),
      });
      onSuccess();
    } catch (err) {
      setError(err.message);
      setSubmitting(false);
    }
  };

  return (
    <Overlay onClose={onClose}>
      <ModalHead title={`Edit ${rndId}`} onClose={onClose} />
      <form onSubmit={submit}>
        <div className="modal-body">
          <ErrorBanner msg={error} />
          <div className="form-group">
            <label className="form-label">Title</label>
            <input className="form-input" value={form.title}
              onChange={e => set("title", e.target.value)} autoFocus />
          </div>
          <div className="form-group">
            <label className="form-label">Core loop</label>
            <textarea className="form-textarea" value={form.core_loop}
              onChange={e => set("core_loop", e.target.value)} rows={3} />
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Key metric</label>
              <input className="form-input" value={form.key_metric}
                onChange={e => set("key_metric", e.target.value)} placeholder="D1 Retention" />
            </div>
            <div className="form-group">
              <label className="form-label">Target</label>
              <input className="form-input" value={form.target}
                onChange={e => set("target", e.target.value)} placeholder="≥ 35%" />
            </div>
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Current value</label>
              <input className="form-input" value={form.current_value}
                onChange={e => set("current_value", e.target.value)} placeholder="18%" />
            </div>
            <div className="form-group">
              <label className="form-label">Risk</label>
              <select className="form-select" value={form.risk} onChange={e => set("risk", e.target.value)}>
                <option value="low">Low</option>
                <option value="med">Medium</option>
                <option value="high">High</option>
              </select>
            </div>
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Author</label>
              <select className="form-select" value={form.author_id}
                onChange={e => set("author_id", e.target.value)}>
                {data.authors.map(a => (
                  <option key={a.id} value={a.id}>{a.name}</option>
                ))}
              </select>
            </div>
            <div style={{}}>{/* spacer */}</div>
          </div>
          <div className="form-group">
            <label className="form-label">Genre tags</label>
            <TagSelector selected={form.tags} options={data.tags} onChange={v => set("tags", v)} />
          </div>
          <div className="form-group">
            <label className="form-label">Summary</label>
            <textarea className="form-textarea" value={form.summary}
              onChange={e => set("summary", e.target.value)} rows={2} />
          </div>
          <div className="form-group" style={{ marginBottom: 0 }}>
            <label className="form-label">Cover image</label>
            <CoverImagePicker value={form.cover_url} onChange={v => set("cover_url", v)} />
          </div>
        </div>
        <ModalFoot onClose={onClose} submitLabel="Save changes" submitting={submitting} />
      </form>
    </Overlay>
  );
}

// ── Decision modal (Kill / Pivot / Scale) ──────────────────────────────────

function DecisionModal({ rndId, data, user, onClose, onSuccess }) {
  const h = data.hypotheses.find(x => x.id === rndId);
  const [decision, setDecision] = useState(null);
  const [reason, setReason] = useState("");
  const [pivotTitle, setPivotTitle] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);

  if (!h) return null;

  const submit = async (e) => {
    e.preventDefault();
    if (!decision) { setError("Select a decision"); return; }
    if (decision === "pivot" && !pivotTitle.trim()) { setError("Provide a title for the pivot hypothesis"); return; }
    setSubmitting(true); setError(null);
    try {
      const result = await api(`/api/hypotheses/${rndId}/decide`, {
        method: "POST",
        body: JSON.stringify({ decision, reason: reason || null, pivot_title: pivotTitle || null }),
      });
      onSuccess(result.pivotCreated?.id || null);
    } catch (err) {
      setError(err.message);
      setSubmitting(false);
    }
  };

  const opts = [
    {
      key: "kill",
      label: "Kill",
      desc: "Archive this hypothesis. Learnings are preserved.",
      color: "var(--kill)",
    },
    {
      key: "pivot",
      label: "Pivot",
      desc: "Create a new hypothesis that branches from this one.",
      color: "var(--pivot)",
    },
    {
      key: "scale",
      label: "Scale →",
      desc: "Hand off to production. Triggers R&D Passport package.",
      color: "var(--scale-c)",
    },
  ];

  return (
    <Overlay onClose={onClose}>
      <ModalHead title={`Decision · ${rndId}`} onClose={onClose} />
      <form onSubmit={submit}>
        <div className="modal-body">
          <ErrorBanner msg={error} />
          <p style={{ margin: "0 0 16px", fontSize: 13, color: "var(--text-2)", lineHeight: 1.5 }}>
            <strong>{h.title}</strong> is in Cold Test.
            Choose a decision — this is permanent and triggers downstream actions.
          </p>

          <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 16 }}>
            {opts.map(o => (
              <label
                key={o.key}
                style={{
                  display: "flex", alignItems: "flex-start", gap: 12,
                  padding: "12px 14px", borderRadius: "var(--radius)",
                  border: `1px solid ${decision === o.key ? o.color : "var(--border)"}`,
                  background: decision === o.key ? `color-mix(in oklch, ${o.color} 8%, var(--surface))` : "var(--surface)",
                  cursor: "pointer", transition: "all 0.1s",
                }}
                onClick={() => setDecision(o.key)}
              >
                <input type="radio" name="decision" value={o.key} checked={decision === o.key}
                  onChange={() => setDecision(o.key)} style={{ marginTop: 3 }} />
                <div>
                  <div style={{ fontWeight: 600, fontSize: 13, color: o.color }}>{o.label}</div>
                  <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 2 }}>{o.desc}</div>
                </div>
              </label>
            ))}
          </div>

          {decision === "pivot" && (
            <div className="form-group">
              <label className="form-label">New hypothesis title *</label>
              <input className="form-input" value={pivotTitle}
                onChange={e => setPivotTitle(e.target.value)}
                placeholder="e.g. Merge Dungeon — auto-battle variant" autoFocus />
            </div>
          )}

          <div className="form-group" style={{ marginBottom: 0 }}>
            <label className="form-label">Reason / notes</label>
            <textarea className="form-textarea" value={reason}
              onChange={e => setReason(e.target.value)}
              placeholder="What drove this decision?" rows={3} />
          </div>
        </div>
        <ModalFoot onClose={onClose} submitLabel="Confirm decision" submitting={submitting}
          danger={decision === "kill"} />
      </form>
    </Overlay>
  );
}

// ── Advance modal ──────────────────────────────────────────────────────────

function AdvanceModal({ rndId, data, onAdvance, onClose }) {
  const h = data.hypotheses.find(x => x.id === rndId);
  const [notes, setNotes] = useState("");
  const [submitting, setSubmitting] = useState(false);

  const STAGE_ORDER = ["idea", "greybox", "prototype", "coldtest", "decision"];
  const idx = h ? STAGE_ORDER.indexOf(h.stage) : -1;
  const nextStage = idx >= 0 && idx < STAGE_ORDER.length - 1 ? data.stages.find(s => s.id === STAGE_ORDER[idx + 1]) : null;

  if (!h || !nextStage) return null;

  const submit = async (e) => {
    e.preventDefault();
    setSubmitting(true);
    await onAdvance(rndId, notes);
    onClose();
  };

  return (
    <Overlay onClose={onClose}>
      <ModalHead title={`Advance ${rndId}`} onClose={onClose} />
      <form onSubmit={submit}>
        <div className="modal-body">
          <p style={{ margin: "0 0 16px", fontSize: 13, color: "var(--text-2)" }}>
            Move <strong>{h.title}</strong> from{" "}
            <span style={{ fontFamily: "var(--font-mono)", fontWeight: 500 }}>{h.stage}</span>
            {" → "}
            <span style={{ fontFamily: "var(--font-mono)", fontWeight: 500, color: "var(--accent-text)" }}>
              {nextStage.label}
            </span>
          </p>
          <div className="form-group" style={{ marginBottom: 0 }}>
            <label className="form-label">Gate notes (optional)</label>
            <textarea className="form-textarea" value={notes}
              onChange={e => setNotes(e.target.value)}
              placeholder={`Evidence for moving to ${nextStage.label}…`} rows={3} autoFocus />
          </div>
        </div>
        <ModalFoot onClose={onClose} submitLabel={`Move to ${nextStage.label}`} submitting={submitting} />
      </form>
    </Overlay>
  );
}

// ── User modal (admin) ─────────────────────────────────────────────────────

function UserModal({ editUser, currentUser, onClose, onSuccess }) {
  const isNew = !editUser;
  const [form, setForm] = useState({
    username:  editUser?.username  || "",
    email:     editUser?.email     || "",
    full_name: editUser?.full_name || "",
    password:  "",
    color:     editUser?.color     || USER_COLORS[0],
    role:      editUser?.role      || "core",
  });
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const submit = async (e) => {
    e.preventDefault();
    setSubmitting(true); setError(null);
    try {
      if (isNew) {
        if (!form.password) throw new Error("Password is required");
        await api("/api/users", { method: "POST", body: JSON.stringify(form) });
      } else {
        const payload = { ...form };
        if (!payload.password) delete payload.password;
        await api(`/api/users/${editUser.id}`, { method: "PUT", body: JSON.stringify(payload) });
      }
      onSuccess();
    } catch (err) {
      setError(err.message);
      setSubmitting(false);
    }
  };

  return (
    <Overlay onClose={onClose}>
      <ModalHead title={isNew ? "Add team member" : `Edit ${editUser.username}`} onClose={onClose} />
      <form onSubmit={submit}>
        <div className="modal-body">
          <ErrorBanner msg={error} />
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Username</label>
              <input className="form-input" value={form.username}
                onChange={e => set("username", e.target.value)}
                disabled={!isNew} required autoFocus />
            </div>
            <div className="form-group">
              <label className="form-label">Full name</label>
              <input className="form-input" value={form.full_name}
                onChange={e => set("full_name", e.target.value)}
                placeholder="A. Novikova" />
            </div>
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Email</label>
              <input className="form-input" type="email" value={form.email}
                onChange={e => set("email", e.target.value)} required />
            </div>
            <div className="form-group">
              <label className="form-label">{isNew ? "Password" : "New password"}</label>
              <input className="form-input" type="password" value={form.password}
                onChange={e => set("password", e.target.value)}
                placeholder={isNew ? "min 8 chars" : "leave blank to keep"}
                required={isNew} />
            </div>
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Role</label>
              <select className="form-select" value={form.role} onChange={e => set("role", e.target.value)}>
                <option value="orbit">Orbit (contributor)</option>
                <option value="core">Core</option>
                <option value="lead">R&D Lead</option>
                <option value="admin">Admin</option>
              </select>
            </div>
            <div className="form-group">
              <label className="form-label">Avatar colour</label>
              <div className="color-swatches">
                {USER_COLORS.map(c => (
                  <div
                    key={c}
                    className={"color-swatch" + (form.color === c ? " active" : "")}
                    style={{ background: c }}
                    onClick={() => set("color", c)}
                  />
                ))}
              </div>
            </div>
          </div>
        </div>
        <ModalFoot onClose={onClose} submitLabel={isNew ? "Add member" : "Save changes"} submitting={submitting} />
      </form>
    </Overlay>
  );
}

// ── Asset modal ────────────────────────────────────────────────────────────

function AssetModal({ rndId, onClose, onSuccess }) {
  const [form, setForm] = useState({ name: "", url: "", asset_type: "other", notes: "" });
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const submit = async (e) => {
    e.preventDefault();
    if (!form.name.trim()) { setError("Name is required"); return; }
    setSubmitting(true); setError(null);
    try {
      await api(`/api/hypotheses/${rndId}/assets`, {
        method: "POST", body: JSON.stringify(form),
      });
      onSuccess();
    } catch (err) {
      setError(err.message);
      setSubmitting(false);
    }
  };

  return (
    <Overlay onClose={onClose}>
      <ModalHead title="Add asset" onClose={onClose} />
      <form onSubmit={submit}>
        <div className="modal-body">
          <ErrorBanner msg={error} />
          <div className="form-group">
            <label className="form-label">Name *</label>
            <input className="form-input" value={form.name}
              onChange={e => set("name", e.target.value)}
              placeholder="Prompt library v3" autoFocus />
          </div>
          <div className="form-group">
            <label className="form-label">URL</label>
            <input className="form-input" value={form.url}
              onChange={e => set("url", e.target.value)}
              placeholder="https://..." type="url" />
          </div>
          <div className="form-row-2">
            <div className="form-group">
              <label className="form-label">Type</label>
              <select className="form-select" value={form.asset_type}
                onChange={e => set("asset_type", e.target.value)}>
                <option value="prompt">Prompt</option>
                <option value="code">Code / repo</option>
                <option value="apk">APK / build</option>
                <option value="analytics">Analytics</option>
                <option value="mockup">Mockup / art</option>
                <option value="doc">Document</option>
                <option value="other">Other</option>
              </select>
            </div>
            <div className="form-group">
              <label className="form-label">Notes</label>
              <input className="form-input" value={form.notes}
                onChange={e => set("notes", e.target.value)}
                placeholder="Optional note" />
            </div>
          </div>
        </div>
        <ModalFoot onClose={onClose} submitLabel="Add asset" submitting={submitting} />
      </form>
    </Overlay>
  );
}

// ── Router ─────────────────────────────────────────────────────────────────

function ModalRouter({ modal, data, user, onClose, onSuccess }) {
  if (modal.type === "new")     return <NewHypothesisModal data={data} user={user} onClose={onClose} onSuccess={onSuccess} />;
  if (modal.type === "edit")    return <EditHypothesisModal rndId={modal.rndId} data={data} user={user} onClose={onClose} onSuccess={onSuccess} />;
  if (modal.type === "decide")  return <DecisionModal rndId={modal.rndId} data={data} user={user} onClose={onClose} onSuccess={onSuccess} />;
  if (modal.type === "advance") return <AdvanceModal rndId={modal.rndId} data={data} onAdvance={modal.onAdvance} onClose={onClose} />;
  if (modal.type === "user")    return <UserModal editUser={modal.editUser} currentUser={user} onClose={onClose} onSuccess={onSuccess} />;
  if (modal.type === "asset")   return <AssetModal rndId={modal.rndId} onClose={onClose} onSuccess={onSuccess} />;
  return null;
}

window.PRModal = { ModalRouter };
