// Access: who can use the dashboard with which role, and what each role may do. Owner only.

const GAME_ROLES = ["developer", "manager", "moderator"];

const PERM_LABELS = {
  "stats.view":       "Dashboard and leaderboards",
  "players.view":     "View players and the audit log",
  "players.rename":   "Rename players",
  "players.kick":     "Kick players",
  "players.ban":      "Ban and unban",
  "currency.edit":    "Change gold",
  "inventory.grant":  "Grant items",
  "inventory.revoke": "Revoke items",
  "catalog.view":     "View the catalog",
  "catalog.edit":     "Edit the catalog",
  "content.edit":     "Title data and news",
  "events.send":      "Send live events",
  "staff.manage":     "Set in-game staff roles",
  "migration.run":    "Migration and PlayFab imports",
};

const roleSelectStyle = {
  border: "1px solid var(--border)", background: "var(--surface)", borderRadius: 6,
  padding: "3px 8px", fontSize: 12, textTransform: "capitalize", color: "var(--ink)",
};

function MemberManager({ game, onChanged }) {
  const [discordId, setDiscordId] = React.useState("");
  const [handle, setHandle] = React.useState("");
  const [role, setRole] = React.useState("moderator");
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState(null);
  const members = game.members || [];

  const setMember = async (id, r) => {
    setBusy(true);
    setError(null);
    try {
      await api("/api/game/members", { method: "POST", body: { discordId: id, role: r, handle: handle.trim() || undefined } });
      setDiscordId("");
      setHandle("");
      onChanged();
    } catch (e) {
      setError(e.message);
    } finally {
      setBusy(false);
    }
  };

  const removeMember = async (id) => {
    setBusy(true);
    try {
      await api(`/api/game/members/${id}`, { method: "DELETE" });
      onChanged();
    } catch (e) {
      setError(e.message);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={{padding:"4px 0"}}>
      {members.map(m => (
        <div key={m.discordId} className="h-stack gap-8" style={{marginBottom:6}}>
          <PAvatar name={m.handle} img={m.avatar} seed={m.discordId} size={22}/>
          <div style={{flex:1, minWidth:0}}>
            <div className="tiny" style={{fontWeight:500}}>{m.handle}</div>
            <div className="tiny muted mono">{m.discordId}</div>
          </div>
          <select value={m.role} disabled={busy} onChange={e => setMember(m.discordId, e.target.value)} style={roleSelectStyle}>
            {GAME_ROLES.map(r => <option key={r} value={r}>{r}</option>)}
          </select>
          <button className="btn btn-sm btn-ghost" disabled={busy} title="Remove access" onClick={() => removeMember(m.discordId)}><Icon name="close" size={12}/></button>
        </div>
      ))}
      {!members.length && <div className="tiny muted" style={{marginBottom:8}}>Only you so far.</div>}

      <div className="h-stack gap-8" style={{marginTop:12, alignItems:"flex-end"}}>
        <div className="field" style={{flex:1.4}}>
          <label className="tiny">Discord user ID</label>
          <input className="input mono" value={discordId} onChange={e => setDiscordId(e.target.value)} placeholder="1222335336219414560"/>
        </div>
        <div className="field" style={{flex:1}}>
          <label className="tiny">Name (optional)</label>
          <input className="input" value={handle} onChange={e => setHandle(e.target.value)} placeholder="their name"/>
        </div>
        <select value={role} onChange={e => setRole(e.target.value)} style={{...roleSelectStyle, padding:"6px 8px"}}>
          {GAME_ROLES.map(r => <option key={r} value={r}>{r}</option>)}
        </select>
        <button className="btn btn-sm btn-accent" disabled={busy || !/^\d{15,21}$/.test(discordId.trim())} onClick={() => setMember(discordId.trim(), role)}>
          <Icon name="plus" size={12}/> Grant
        </button>
      </div>
      <div className="tiny muted mt-8">Anyone listed here can sign in with Discord. Removing someone ends their access.</div>
      {error && <div className="tiny mt-8" style={{color:"var(--danger)", fontWeight:600}}>{error}</div>}
    </div>
  );
}

function PermissionsEditor({ game, onChanged }) {
  const [matrix, setMatrix] = React.useState(game.rolePerms || {});
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState(null);

  const toggle = async (role, perm) => {
    const current = matrix[role] || [];
    const next = current.includes(perm) ? current.filter(p => p !== perm) : [...current, perm];
    const previous = matrix;
    setMatrix({ ...matrix, [role]: next });
    setBusy(true);
    setError(null);
    try {
      await api("/api/game", { method: "PATCH", body: { rolePerms: { [role]: next } } });
      onChanged?.();
    } catch (e) {
      setError(e.message);
      setMatrix(previous);
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={{padding:"4px 0"}}>
      <div className="tiny muted" style={{marginBottom:8}}>Click a dot to toggle. The owner always has everything. Checked on every request, not just hidden in the menu.</div>
      <table className="perm-matrix">
        <thead>
          <tr><th></th>{GAME_ROLES.map(r => <th key={r} style={{textTransform:"capitalize"}}>{r}</th>)}</tr>
        </thead>
        <tbody>
          {Object.entries(PERM_LABELS).map(([perm, label]) => (
            <tr key={perm}>
              <td>{label}</td>
              {GAME_ROLES.map(role => (
                <td key={role}>
                  <button type="button" className="dot-perm" disabled={busy}
                    data-on={(matrix[role] || []).includes(perm)}
                    style={{cursor:"pointer", padding:0}}
                    title={`${role}: ${label}`}
                    onClick={() => toggle(role, perm)}/>
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
      {error && <div className="tiny mt-8" style={{color:"var(--danger)", fontWeight:600}}>{error}</div>}
    </div>
  );
}

function AccessPage() {
  const [, bump] = React.useReducer(x => x + 1, 0);
  const game = window.APP_GAME_INFO;
  const reload = async () => { await window.appReloadGame?.(); bump(); };

  if (!game?.canManage) {
    return <div className="page"><div className="empty"><h3>Not allowed</h3><p>Only the owner manages access.</p></div></div>;
  }

  return (
    <div className="page" style={{maxWidth: 760}}>
      <div className="page-head">
        <div>
          <h1 className="page-title">Access</h1>
          <p className="page-subtitle">Who can use the dashboard, and what each role is allowed to do.</p>
        </div>
      </div>

      <div className="card card-pad">
        <div className="card-head"><div><h3 className="card-title">Members</h3><p className="card-sub">Teammates and their role</p></div></div>
        <MemberManager game={game} onChanged={reload}/>
      </div>

      <div className="card card-pad section-gap" style={{marginTop:14}}>
        <div className="card-head"><div><h3 className="card-title">Role permissions</h3></div></div>
        <PermissionsEditor key={JSON.stringify(game.rolePerms)} game={game} onChanged={reload}/>
      </div>
    </div>
  );
}

window.AccessPage = AccessPage;
