// Content: Title Data and Title News, like Game Manager's Content section. Public keys are sent to
// every game at login and pushed live when they change; private keys stay on the server (quest
// config, reward rules, the name blocklist).

const LAR_KNOWN_KEYS = {
  QuestConfig: "Quest boards, tracks and rewards (exported from Unity: LethalApeR > Quests > Export Quest Config).",
  QuestWeeklyBonus: "Weekly bonus cosmetic schedule.",
  STAT_RULES: 'Stats the game may count: { "BTM_Wins": { "minSeconds": 60, "dailyCap": 50 } }',
  APEGAMES_REWARD: "Ape Games win payout: minPlayers, maxPlayers, cooldownSeconds, curve, dailyCap.",
  REPORT_RULES: "Report consensus and auto-ban settings.",
  NAME_BLOCKLIST: "Comma-separated words players cannot use in names.",
  KICK_WHITELIST: "Built from staff roles automatically; edit KICK_WHITELIST_MANUAL instead.",
  KICK_WHITELIST_MANUAL: "Extra ids allowed to send admin RPCs (merged into KICK_WHITELIST).",
};

function larJsonProblem(text) {
  const t = text.trim();
  if (!t || !(t.startsWith("{") || t.startsWith("["))) return null;
  try { JSON.parse(t); return null; } catch (e) { return e.message; }
}

function LarConfigEditor({ entry, isNew, onClose, onSaved }) {
  const [key, setKey] = React.useState(entry?.key || "");
  const [value, setValue] = React.useState(entry?.value || "");
  const [isPublic, setIsPublic] = React.useState(entry ? entry.public : true);
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState(null);
  const problem = larJsonProblem(value);

  const pretty = () => { try { setValue(JSON.stringify(JSON.parse(value), null, 2)); } catch { /* not JSON */ } };

  const save = async () => {
    setBusy(true); setError(null);
    try {
      const res = await larApi(`config/${encodeURIComponent(key.trim())}`, { method: "PUT", body: { value, public: isPublic } });
      onSaved(res);
    } catch (e) { setError(e.message); setBusy(false); }
  };

  const remove = async () => {
    if (!confirm(`Delete ${key}?`)) return;
    setBusy(true);
    try { onSaved(await larApi(`config/${encodeURIComponent(key)}`, { method: "DELETE" })); }
    catch (e) { setError(e.message); setBusy(false); }
  };

  return (
    <>
      <div className="scrim" onClick={onClose}/>
      <div className="drawer" style={{width:"min(720px, 100vw)"}}>
        <div className="drawer-head">
          <div><div style={{fontWeight:600, fontSize:13.5}}>{isNew ? "New key" : key}</div><div className="tiny muted">{LAR_KNOWN_KEYS[key] || (isNew ? "Title data value" : "")}</div></div>
          <button className="icon-btn" onClick={onClose}><Icon name="close" size={14}/></button>
        </div>
        <div className="drawer-body">
          {isNew && <div className="field"><label>Key</label><input className="input mono" value={key} onChange={e => setKey(e.target.value)} placeholder="EVENT_DOUBLE_GOLD"/></div>}
          <div className="field mt-12">
            <div className="spread"><label>Value</label><button className="btn btn-sm btn-ghost" onClick={pretty}>Format JSON</button></div>
            <textarea className="input" style={{minHeight:360}} value={value} onChange={e => setValue(e.target.value)} spellCheck={false}/>
          </div>
          {problem && <div className="tiny mt-4" style={{color:"var(--warn)"}}>Looks like JSON but does not parse: {problem}</div>}
          <label className="lar-check mt-12"><input type="checkbox" checked={isPublic} onChange={e => setIsPublic(e.target.checked)}/> Public: sent to every game and pushed live on change</label>
          <LarError error={error}/>
        </div>
        <div className="drawer-foot">
          <button className="btn btn-sm btn-accent" disabled={busy || !key.trim() || !!problem} onClick={save}>Save</button>
          {!isNew && <button className="btn btn-sm btn-danger" disabled={busy} onClick={remove}>Delete</button>}
          <span className="tiny muted">{fmt.num(value.length)} characters</span>
        </div>
      </div>
    </>
  );
}

function LarTitleData() {
  const { data, error, loading, reload } = useLarLoad(() => larApi("config"), []);
  const [editing, setEditing] = React.useState(null);
  const [notice, setNotice] = React.useState(null);

  return (
    <div className="card card-flush">
      <div className="toolbar">
        <span className="tiny muted">{data ? `${data.items.length} keys · version ${data.version}` : ""}</span>
        <div style={{flex:1}}/>
        <button className="btn btn-sm btn-accent" onClick={() => setEditing({ entry: null, isNew: true })}><Icon name="plus" size={12}/> New key</button>
      </div>
      {notice && <div style={{padding:"0 16px"}}><LarDelivered result={notice}/></div>}
      {error && <div className="tiny" style={{color:"var(--danger)", padding:"0 16px 12px"}}>{error}</div>}
      <table className="tbl">
        <thead><tr><th>Key</th><th>Visibility</th><th style={{textAlign:"right"}}>Size</th><th>Updated</th><th>By</th></tr></thead>
        <tbody>
          {(data?.items || []).map(it => (
            <tr key={it.key} className="lar-row-click" onClick={() => setEditing({ entry: it, isNew: false })}>
              <td><div className="mono" style={{fontWeight:600}}>{it.key}</div>{LAR_KNOWN_KEYS[it.key] && <div className="tiny muted">{LAR_KNOWN_KEYS[it.key]}</div>}</td>
              <td>{it.public ? <span className="tag tag-info">Public</span> : <span className="tag">Server only</span>}</td>
              <td className="mono tiny" style={{textAlign:"right"}}>{fmt.num(it.bytes)} B</td>
              <td className="tiny muted">{timeSince(larIso(it.updatedAt))}</td>
              <td className="tiny muted">{it.updatedBy}</td>
            </tr>
          ))}
          {data && !data.items.length && <tr><td colSpan={5}><div className="empty"><h3>No title data</h3><p>Import it from PlayFab on the Migration page, or add a key.</p></div></td></tr>}
          {loading && <tr><td colSpan={5}><div className="empty"><h3>Loading…</h3></div></td></tr>}
        </tbody>
      </table>
      {editing && <LarConfigEditor entry={editing.entry} isNew={editing.isNew} onClose={() => setEditing(null)} onSaved={(res) => { setEditing(null); setNotice(res); reload(); }}/>}
    </div>
  );
}

function LarNews() {
  const { data, error, reload } = useLarLoad(() => larApi("news"), []);
  const [raw, setRaw] = React.useState(false);
  const [title, setTitle] = React.useState("");
  const [version, setVersion] = React.useState("");
  const [log, setLog] = React.useState("");
  const [body, setBody] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [result, setResult] = React.useState(null);

  // The game's update board reads bodies shaped {"version", "update_log"} (UpdateBoard.cs).
  const composed = raw ? body : JSON.stringify({ version: version.trim(), update_log: log });

  const post = async () => {
    setBusy(true); setErr(null);
    try {
      setResult(await larApi("news", { method: "POST", body: { title: title.trim() || `Update ${version.trim()}`, body: composed } }));
      setTitle(""); setVersion(""); setLog(""); setBody(""); reload();
    } catch (e) { setErr(e.message); }
    setBusy(false);
  };

  const remove = async (id) => {
    if (!confirm("Delete this news item?")) return;
    try { await larApi(`news/${id}`, { method: "DELETE" }); reload(); } catch (e) { alert(e.message); }
  };

  return (
    <div className="row row-1-1">
      <div className="card card-pad">
        <div className="card-head"><div><div className="card-title">Post news</div><div className="card-sub">Shows on the in-game update board; posting refreshes it live</div></div></div>
        <div className="h-stack gap-6 mb-8">
          <button className="filter-pill" data-active={!raw} onClick={() => setRaw(false)}>Update log</button>
          <button className="filter-pill" data-active={raw} onClick={() => setRaw(true)}>Raw body</button>
        </div>
        <div className="field"><label>Title</label><input className="input" value={title} onChange={e => setTitle(e.target.value)} placeholder="Halloween update"/></div>
        {!raw ? (
          <>
            <div className="field mt-8"><label>Version (must be part of the build's version to show)</label><input className="input mono" value={version} onChange={e => setVersion(e.target.value)} placeholder="1.4.2"/></div>
            <div className="field mt-8"><label>Update log</label><textarea className="input" value={log} onChange={e => setLog(e.target.value)} placeholder={"- New monster\n- Fixed the shop"}/></div>
          </>
        ) : (
          <div className="field mt-8"><label>Body</label><textarea className="input" value={body} onChange={e => setBody(e.target.value)}/></div>
        )}
        <button className="btn btn-sm btn-accent mt-8" disabled={busy || (!raw && !version.trim()) || (raw && !body.trim())} onClick={post}><Icon name="publish" size={12}/> Post</button>
        <LarError error={err}/><LarDelivered result={result}/>
      </div>
      <div className="card card-pad">
        <div className="card-head"><div><div className="card-title">Posted</div><div className="card-sub">newest first</div></div></div>
        {error && <LarError error={error}/>}
        <div className="stack gap-8 mt-8">
          {(data?.news || []).map(n => (
            <div key={n.id} className="card card-pad-tight">
              <div className="spread"><strong style={{fontSize:12.5}}>{n.title}</strong><span className="h-stack gap-6"><span className="tiny muted">{timeSince(larIso(n.at))}</span><button className="btn btn-sm btn-ghost" onClick={() => remove(n.id)}><Icon name="close" size={12}/></button></span></div>
              <div className="mt-8"><LarJson value={n.body} max={160}/></div>
            </div>
          ))}
          {data && !data.news.length && <div className="empty"><h3>No news</h3><p>Nothing posted yet.</p></div>}
        </div>
      </div>
    </div>
  );
}

function LarContentPage() {
  const [tab, setTab] = React.useState("data");
  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1 className="page-title">Content</h1>
          <p className="page-subtitle">Title data and title news. Changes reach running games within a second.</p>
        </div>
      </div>
      <div className="tabs" style={{marginBottom:14}}>
        <button className="tab" data-active={tab === "data"} onClick={() => setTab("data")}>Title Data</button>
        <button className="tab" data-active={tab === "news"} onClick={() => setTab("news")}>Title News</button>
      </div>
      {tab === "data" ? <LarTitleData/> : <LarNews/>}
    </div>
  );
}

window.LarContentPage = LarContentPage;
