/* ============================================================
   primitives.jsx — Edit-mode context + editable cells + link
   ============================================================ */
const { createContext, useContext, useState, useEffect, useRef, useMemo, useCallback } = React;
/* ---------------- Edit-mode context ---------------- */
const EditContext = createContext({ editing: false, setEditing: () => {} });
const useEditMode = () => useContext(EditContext);

function EditProvider({ children }) {
  const [editing, setEditing] = useState(() => {
    try { return localStorage.getItem("__mj_edit__") === "1"; } catch { return false; }
  });
  useEffect(() => {
    try { localStorage.setItem("__mj_edit__", editing ? "1" : "0"); } catch {}
  }, [editing]);
  return (
    <EditContext.Provider value={{ editing, setEditing }}>
      {children}
    </EditContext.Provider>
  );
}

/* ---------------- localStorage table store ----------------
   Each table is keyed by an id. Returns [rows, ops].
   ops: setCell(rowId, field, value), addRow(template), removeRow(rowId)
   ------------------------------------------------------------ */
function useTable(key, seed) {
  const storageKey = `__mj_tbl_${key}__`;
  const [rows, setRows] = useState(() => {
    try {
      const raw = localStorage.getItem(storageKey);
      if (raw) return JSON.parse(raw);
    } catch {}
    return seed;
  });
  useEffect(() => {
    try { localStorage.setItem(storageKey, JSON.stringify(rows)); } catch {}
  }, [rows, storageKey]);

  const setCell = useCallback((rowId, field, value) => {
    setRows(prev => prev.map(r => r.id === rowId ? { ...r, [field]: value } : r));
  }, []);
  const addRow = useCallback((template) => {
    setRows(prev => [...prev, { ...template, id: `new-${Date.now()}-${Math.random().toString(36).slice(2,6)}` }]);
  }, []);
  const removeRow = useCallback((rowId) => {
    if (!confirm("确认删除这一行?此操作不可撤销。")) return;
    setRows(prev => prev.filter(r => r.id !== rowId));
  }, []);
  const reset = useCallback(() => {
    if (!confirm("确认重置为初始数据?所有修改将丢失。")) return;
    setRows(seed);
  }, [seed]);
  return [rows, { setCell, addRow, removeRow, reset }];
}

/* ---------------- URL detection ---------------- */
const URL_RE = /(https?:\/\/[^\s]+)/g;
function isUrl(s) {
  return typeof s === "string" && /^https?:\/\//i.test(s.trim());
}
/* render text — if contains URL(s), make them clickable; otherwise render as-is */
function renderText(text) {
  if (text == null || text === "") return null;
  const str = String(text);
  if (!URL_RE.test(str)) return str;
  URL_RE.lastIndex = 0;
  const parts = [];
  let last = 0, m, i = 0;
  while ((m = URL_RE.exec(str)) !== null) {
    if (m.index > last) parts.push(str.slice(last, m.index));
    parts.push(
      <a key={`l-${i++}`} className="link" href={m[0]} target="_blank" rel="noreferrer">
        {prettyUrl(m[0])}<span className="arrow">↗</span>
      </a>
    );
    last = m.index + m[0].length;
  }
  if (last < str.length) parts.push(str.slice(last));
  return parts;
}
function prettyUrl(u) {
  try {
    const url = new URL(u);
    const host = url.hostname.replace(/^www\./, "");
    const path = url.pathname.length > 1 ? url.pathname : "";
    const full = host + path;
    return full.length > 60 ? full.slice(0, 58) + "…" : full;
  } catch { return u; }
}

/* ---------------- EditableCell ----------------
   Click → edit when global edit mode is on.
   On blur or Enter (Cmd/Ctrl) commit.
   Auto-detects URL and renders as link in view mode.
   ------------------------------------------------------------ */
function EditableCell({
  value, onChange,
  multiline = false,
  numeric = false,
  align = "left",
  placeholder = "—",
  className = "",
  readOnly = false,
}) {
  const { editing: globalEditing } = useEditMode();
  const [active, setActive] = useState(false);
  const [draft, setDraft] = useState(value ?? "");
  const inputRef = useRef(null);

  useEffect(() => { setDraft(value ?? ""); }, [value]);

  const canEdit = globalEditing && !readOnly;

  const commit = () => {
    let v = draft;
    if (numeric) {
      const n = v === "" || v == null ? null : Number(v);
      v = Number.isFinite(n) ? n : null;
    } else {
      v = typeof v === "string" ? v.trim() : v;
    }
    if (v !== value) onChange(v);
    setActive(false);
  };
  const cancel = () => { setDraft(value ?? ""); setActive(false); };

  useEffect(() => {
    if (active && inputRef.current) {
      inputRef.current.focus();
      if (inputRef.current.select) inputRef.current.select();
    }
  }, [active]);

  const onKey = (e) => {
    if (e.key === "Escape") { e.preventDefault(); cancel(); }
    else if (e.key === "Enter" && (!multiline || e.metaKey || e.ctrlKey)) {
      e.preventDefault(); commit();
    }
  };

  const isEmpty = value == null || value === "";
  const cellClass = [
    "cell",
    canEdit && "is-editable",
    active && "is-editing",
    align === "center" && "center",
    isEmpty && "empty",
    className,
  ].filter(Boolean).join(" ");

  if (active) {
    return (
      <div className={cellClass}>
        {multiline ? (
          <textarea
            ref={inputRef}
            value={draft ?? ""}
            rows={Math.max(1, String(draft || "").split("\n").length)}
            onChange={(e) => setDraft(e.target.value)}
            onBlur={commit}
            onKeyDown={onKey}
            placeholder={placeholder}
          />
        ) : (
          <input
            ref={inputRef}
            value={draft ?? ""}
            type={numeric ? "number" : "text"}
            onChange={(e) => setDraft(e.target.value)}
            onBlur={commit}
            onKeyDown={onKey}
            placeholder={placeholder}
          />
        )}
      </div>
    );
  }

  return (
    <div
      className={cellClass}
      onClick={canEdit ? () => setActive(true) : undefined}
      title={canEdit ? "点击编辑" : (typeof value === "string" && value ? value : undefined)}
    >
      {isEmpty
        ? <span className="muted">{canEdit ? (placeholder || "点击填写") : "—"}</span>
        : (numeric ? value : renderText(value))}
    </div>
  );
}

/* ---------------- StatusBadge ---------------- */
const STATUS_MAP = {
  "已签约":   "ok",
  "正常":     "ok",
  "已通过":   "ok",
  "试合作":   "info",
  "试运营":   "info",
  "进行中":   "warn",
  "待审":     "warn",
  "待签约":   "warn",
  "暂停合作": "stop",
  "停用":     "stop",
  "驳回":     "stop",
  "下架":     "stop",
};
function StatusBadge({ value, onChange, options }) {
  const { editing } = useEditMode();
  const cls = STATUS_MAP[value] || "mute";
  if (editing && options) {
    return (
      <select
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className={`status status--${cls}`}
        style={{ border: "none", appearance: "menulist", padding: "2px 8px", cursor: "pointer" }}
      >
        {options.map(o => <option key={o} value={o}>{o}</option>)}
      </select>
    );
  }
  return <span className={`status status--${cls}`}>{value}</span>;
}

/* ---------------- AddRow / DeleteRow controls ---------------- */
function AddRowBar({ onAdd, label = "新增一行" }) {
  const { editing } = useEditMode();
  if (!editing) return null;
  return (
    <div className="tbl-foot">
      <button className="btn-add" onClick={onAdd}>＋ {label}</button>
      <span className="muted" style={{ fontSize: 11.5 }}>编辑模式 · 点击单元格直接修改,粘贴 URL 自动识别</span>
    </div>
  );
}
function DeleteBtn({ onClick }) {
  const { editing } = useEditMode();
  if (!editing) return null;
  return <button className="btn-del" onClick={onClick} title="删除该行">删除</button>;
}

/* expose to window for other files */
Object.assign(window, {
  EditContext, EditProvider, useEditMode,
  useTable,
  EditableCell, StatusBadge, AddRowBar, DeleteBtn,
  renderText, isUrl,
});
