/* Transfers — "Send Files" admin view.
   Shows every customer artwork transfer. Staff can see the file list, copy the
   shareable link, and delete. Data: GET /api/admin/transfers, DELETE /api/admin/transfers/:id */
const { useState: useTfState, useEffect: useTfEffect, useRef: useTfRef } = React;

const TF_STATUSES = [
  { key: "",         label: "All" },
  { key: "uploading", label: "Uploading" },
  { key: "ready",    label: "Ready" },
  { key: "aborted",  label: "Aborted" },
];

const TF_STATUS_META = {
  uploading: { label: "Uploading",  cls: "badge--blue" },
  ready:     { label: "Ready",      cls: "badge--mint" },
  pending:   { label: "Pending",    cls: "badge--grey" },
  aborted:   { label: "Aborted",    cls: "badge--grey" },
};

function tfFmtDate(s) {
  if (!s) return "—";
  try {
    const d = new Date(s);
    return d.toLocaleDateString(undefined, { day: "2-digit", month: "short", year: "numeric" }) +
      " " + d.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit" });
  } catch { return String(s).slice(0, 16); }
}

function tfFmtBytes(n) {
  if (!n) return "0 B";
  const k = 1024, units = ["B", "KB", "MB", "GB", "TB"];
  const i = Math.floor(Math.log(n) / Math.log(k));
  return (n / Math.pow(k, i)).toFixed(i ? 1 : 0) + " " + units[i];
}

function tfExpiry(t) {
  if (!t.expiresAt) return null;
  const ms = new Date(t.expiresAt) - Date.now();
  if (ms <= 0) return "Expired";
  const h = Math.floor(ms / 3600000);
  if (h < 1) return "< 1 h";
  if (h < 24) return h + "h";
  return Math.floor(h / 24) + "d " + (h % 24) + "h";
}

// Modal: full transfer details (message + file list + share link)
function TransferModal({ transfer, onClose }) {
  const [detail, setDetail] = useTfState(null);
  const [loading, setLoading] = useTfState(true);
  const [err, setErr] = useTfState("");
  const [deleting, setDeleting] = useTfState(false);
  const [copied, setCopied] = useTfState(false);

  useTfEffect(() => {
    let alive = true;
    fetch("/api/admin/transfers/" + transfer.id)
      .then((r) => r.ok ? r.json() : r.json().then((j) => Promise.reject(new Error(j.error || ("HTTP " + r.status)))))
      .then((j) => { if (alive) { setDetail(j); setLoading(false); } })
      .catch((e) => { if (alive) { setErr(e.message || String(e)); setLoading(false); } });
    return () => { alive = false; };
  }, [transfer.id]);

  function copyLink() {
    const url = transfer.shareUrl;
    if (!url) return;
    try {
      navigator.clipboard.writeText(url).then(() => { setCopied(true); setTimeout(() => setCopied(false), 1600); }, () => window.prompt("Share URL:", url));
    } catch { window.prompt("Share URL:", url); }
  }

  async function del() {
    if (!confirm("Delete this transfer and all its S3 files? This cannot be undone.")) return;
    setDeleting(true);
    try {
      const r = await fetch("/api/admin/transfers/" + transfer.id, { method: "DELETE" });
      if (!r.ok) { const j = await r.json(); throw new Error(j.error || ("HTTP " + r.status)); }
      onClose(true); // true = refresh list
    } catch (e) { alert("Delete failed: " + e.message); setDeleting(false); }
  }

  const files = detail ? (detail.files || []) : [];
  const expiryStr = tfExpiry(transfer);
  const expired = transfer.expired || (expiryStr === "Expired");
  const st = TF_STATUS_META[transfer.status] || { label: transfer.status || "—", cls: "badge--grey" };

  return (
    <div className="modal-backdrop" onClick={(e) => { if (e.target === e.currentTarget) onClose(false); }}>
      <div className="modal" style={{ maxWidth: 620, width: "100%" }}>
        <div className="modal__head">
          <div style={{ display: "flex", alignItems: "center", gap: 10, flex: 1, minWidth: 0 }}>
            <h2 style={{ margin: 0, fontSize: 16, fontWeight: 700 }}>Transfer</h2>
            <span className={"badge " + st.cls}>{st.label}</span>
            {expired && <span className="badge badge--grey">Expired</span>}
          </div>
          <button className="icon-btn" onClick={() => onClose(false)} title="Close"><Icon name="x" /></button>
        </div>
        <div className="modal__body" style={{ padding: "16px 20px", display: "flex", flexDirection: "column", gap: 14 }}>
          <dl className="kv" style={{ marginBottom: 0 }}>
            <dt>ID</dt><dd className="mono" style={{ fontSize: 11 }}>{transfer.id}</dd>
            <dt>Customer</dt><dd>{transfer.customerName || "—"}{transfer.customerEmail ? <span className="dim" style={{ marginLeft: 6, fontSize: 12 }}>{transfer.customerEmail}</span> : null}</dd>
            <dt>Created</dt><dd>{tfFmtDate(transfer.createdAt)}</dd>
            {transfer.expiresAt && <><dt>Expires</dt><dd>{tfFmtDate(transfer.expiresAt)} {expiryStr && !expired && <span className="dim" style={{ fontSize: 12 }}>({expiryStr} left)</span>}{expired && <span className="badge badge--grey" style={{ marginLeft: 6 }}>Expired</span>}</dd></>}
            <dt>Files</dt><dd>{transfer.fileCount} &mdash; {tfFmtBytes(transfer.totalBytes)}</dd>
          </dl>

          {transfer.message && (
            <div style={{ background: "var(--bg-2,#f7f8fa)", borderRadius: 8, padding: "10px 12px", fontSize: 13 }}>
              <div className="dim" style={{ fontSize: 11, marginBottom: 4 }}>Message from customer</div>
              <div style={{ whiteSpace: "pre-wrap", wordBreak: "break-word" }}>{transfer.message}</div>
            </div>
          )}

          {transfer.shareUrl && (
            <div style={{ display: "flex", alignItems: "center", gap: 8, background: "var(--bg-2,#f7f8fa)", borderRadius: 8, padding: "8px 12px" }}>
              <span className="mono dim" style={{ fontSize: 11, flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{transfer.shareUrl}</span>
              <button className="btn btn--sm btn--ghost" onClick={copyLink}>{copied ? <Icon name="check" /> : <Icon name="copy" />} {copied ? "Copied" : "Copy"}</button>
              <a className="btn btn--sm btn--ghost" href={transfer.shareUrl} target="_blank" rel="noopener noreferrer"><Icon name="send" /> Open</a>
            </div>
          )}

          <div>
            <div className="kick" style={{ marginBottom: 8 }}>Files</div>
            {loading ? (
              <div className="dim" style={{ fontSize: 13 }}>Loading…</div>
            ) : err ? (
              <div className="warn-banner"><Icon name="spark" /> {err}</div>
            ) : files.length === 0 ? (
              <div className="dim" style={{ fontSize: 13 }}>No files.</div>
            ) : (
              <div className="tbl-wrap" style={{ maxHeight: 260, overflowY: "auto" }}>
                <table className="tbl" style={{ fontSize: 12.5 }}>
                  <thead>
                    <tr>
                      <th>Filename</th><th>Size</th><th>Type</th><th>Status</th>
                    </tr>
                  </thead>
                  <tbody>
                    {files.map((f) => (
                      <tr key={f.id}>
                        <td style={{ fontWeight: 500, wordBreak: "break-all" }}>{f.filename}</td>
                        <td style={{ whiteSpace: "nowrap" }}>{tfFmtBytes(f.size)}</td>
                        <td className="mono" style={{ fontSize: 11, color: "var(--txt-2)" }}>{f.mime || "—"}</td>
                        <td><span className={"badge " + (f.status === "uploaded" ? "badge--mint" : "badge--grey")}>{f.status || "pending"}</span></td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        </div>
        <div className="modal__foot" style={{ padding: "12px 20px", display: "flex", gap: 8, justifyContent: "flex-end" }}>
          <button className="btn btn--sm btn--ghost" style={{ color: "var(--c-red,#b91c1c)", borderColor: "var(--c-red,#b91c1c)" }}
                  onClick={del} disabled={deleting}>
            {deleting ? <span className="spin" /> : <Icon name="trash" />} {deleting ? "Deleting…" : "Delete"}
          </button>
          <button className="btn btn--sm btn--primary" onClick={() => onClose(false)}>Close</button>
        </div>
      </div>
    </div>
  );
}

function TransfersView({ go }) {
  const [statusFilter, setStatusFilter] = useTfState("");
  const [data, setData] = useTfState(null);     // { transfers: [] }
  const [loading, setLoading] = useTfState(true);
  const [err, setErr] = useTfState("");
  const [selected, setSelected] = useTfState(null); // transfer for modal

  function load() {
    setLoading(true); setErr("");
    const params = new URLSearchParams();
    if (statusFilter) params.set("status", statusFilter);
    fetch("/api/admin/transfers?" + params.toString())
      .then((r) => r.ok ? r.json() : r.json().then((j) => Promise.reject(new Error(j.error || ("HTTP " + r.status)))))
      .then((j) => { setData(j); setLoading(false); })
      .catch((e) => { setErr(e.message || String(e)); setLoading(false); });
  }

  useTfEffect(() => { load(); }, [statusFilter]);

  const rows = (data && data.transfers) || [];
  const now = Date.now();

  return (
    <div className="board">
      {selected && (
        <TransferModal
          transfer={selected}
          onClose={(refresh) => { setSelected(null); if (refresh) load(); }}
        />
      )}

      <div className="toolbar">
        <div className="seg">
          {TF_STATUSES.map((s) => (
            <button key={s.key || "all"} className={statusFilter === s.key ? "is-active" : ""} onClick={() => setStatusFilter(s.key)}>
              {s.label}
            </button>
          ))}
        </div>
        <button className="btn btn--sm btn--ghost" style={{ marginLeft: "auto" }} onClick={load}>
          <Icon name="refresh" /> Refresh
        </button>
      </div>

      {err && <div className="warn-banner" style={{ marginBottom: 12 }}><Icon name="spark" /> Couldn't load transfers — {err}</div>}

      <div className="tbl-wrap">
        <table className="tbl">
          <thead>
            <tr>
              <th>Date</th>
              <th>Customer</th>
              <th style={{ textAlign: "right" }}>Files</th>
              <th style={{ textAlign: "right" }}>Size</th>
              <th>Status</th>
              <th>Expires</th>
              <th>Message</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {loading
              ? Array.from({ length: 6 }).map((_, i) => (
                  <tr key={"sk" + i}>
                    <td colSpan={8} style={{ padding: "10px 12px" }}>
                      <div className="skel skel-bar" style={{ height: 18, opacity: Math.max(0.3, 1 - i * 0.1) }} />
                    </td>
                  </tr>
                ))
              : rows.length === 0
                ? (
                  <tr>
                    <td colSpan={8}>
                      <div className="empty" style={{ padding: "32px 12px" }}>
                        <Icon name="doc" />
                        <div className="t">No transfers yet</div>
                        <div className="m">{statusFilter ? "No transfers with this status." : "Customer artwork uploads will appear here."}</div>
                      </div>
                    </td>
                  </tr>
                )
                : rows.map((t) => {
                    const st = TF_STATUS_META[t.status] || { label: t.status || "—", cls: "badge--grey" };
                    const expired = t.expired || (t.expiresAt && new Date(t.expiresAt) < new Date());
                    const expiryStr = tfExpiry(t);
                    return (
                      <tr key={t.id} style={{ cursor: "pointer" }} onClick={() => setSelected(t)}>
                        <td style={{ whiteSpace: "nowrap", fontSize: 12.5 }}>{tfFmtDate(t.createdAt)}</td>
                        <td>
                          <div style={{ fontWeight: 500 }}>{t.customerName || "—"}</div>
                          {t.customerEmail && <div className="dim" style={{ fontSize: 11 }}>{t.customerEmail}</div>}
                        </td>
                        <td style={{ textAlign: "right" }}>{t.fileCount || 0}</td>
                        <td style={{ textAlign: "right", whiteSpace: "nowrap" }}>{tfFmtBytes(t.totalBytes)}</td>
                        <td>
                          <span className={"badge " + st.cls}>{st.label}</span>
                          {expired && <span className="badge badge--grey" style={{ marginLeft: 4 }}>Expired</span>}
                        </td>
                        <td style={{ whiteSpace: "nowrap", fontSize: 12.5, color: expired ? "var(--c-red,#b91c1c)" : undefined }}>
                          {expiryStr || "—"}
                        </td>
                        <td style={{ maxWidth: 220, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 12.5, color: "var(--txt-2)" }}>
                          {t.message || ""}
                        </td>
                        <td onClick={(e) => e.stopPropagation()}>
                          {t.shareUrl && (
                            <a className="btn btn--xs btn--ghost" href={t.shareUrl} target="_blank" rel="noopener noreferrer" title="Open share page">
                              <Icon name="send" />
                            </a>
                          )}
                        </td>
                      </tr>
                    );
                  })}
          </tbody>
        </table>
      </div>
      {rows.length > 0 && (
        <div className="toolbar" style={{ marginTop: 8 }}>
          <span className="kick">{rows.length} transfer{rows.length === 1 ? "" : "s"}</span>
        </div>
      )}
    </div>
  );
}
