// Audit-log viewer — admin/mod surface. Read-only; the entries
// themselves are written by the action sites (force-accept, delete,
// block etc) so this screen just renders what's there.
//
// Defaults to "last 200 events", with a quick-filter chip row for
// common actions. Auto-refreshes every 30 s so an admin tab open
// during an incident shows new events without manually reloading.

const ACTION_FILTERS = [
  { id: '',                          label: 'Alle' },
  { id: 'auth.login',                label: 'Logins' },
  { id: 'auth.login-failure',        label: 'Login-Fehler' },
  { id: 'submission.force-accept',   label: 'Veröffentlicht' },
  { id: 'submission.force-reject',   label: 'Abgelehnt' },
  { id: 'submission.delete',         label: 'Gelöscht' },
  { id: 'submission.status-override',label: 'Status-Override' },
  { id: 'submission.block-user',     label: 'User gesperrt (Submission)' },
  { id: 'block.add',                 label: 'Sperre hinzugefügt' },
  { id: 'block.remove',              label: 'Sperre aufgehoben' },
  { id: 'report.dismiss',            label: 'Meldung verworfen' },
  { id: 'report.force-delete',       label: 'Meldung → delisted' },
];

function AuditScreen({ me, dark }) {
  const [list, setList] = React.useState(null);
  const [filter, setFilter] = React.useState('');

  const refresh = React.useCallback(async () => {
    try {
      setList(await Api.audit.list({ limit: 200, action: filter || undefined }));
    } catch (e) {
      toast.error('Audit-Log laden fehlgeschlagen: ' + e.message);
    }
  }, [filter]);

  React.useEffect(() => { refresh(); }, [refresh]);

  React.useEffect(() => {
    const id = setInterval(refresh, 30_000);
    return () => clearInterval(id);
  }, [refresh]);

  return (
    <div style={{ padding: '28px 32px', maxWidth: 1100, margin: '0 auto' }}>
      <div style={{ marginBottom: 18 }}>
        <div style={{ fontSize: 12, opacity: 0.55, letterSpacing: 1.4, textTransform: 'uppercase', fontWeight: 700, marginBottom: 4 }}>
          {list ? `${list.length} Einträge` : 'lädt…'}
        </div>
        <h1 style={{ fontSize: 32, fontWeight: 800, letterSpacing: -0.7, margin: 0 }}>Audit-Log</h1>
        <p style={{ fontSize: 14, opacity: 0.6, marginTop: 6, maxWidth: 720 }}>
          Jede Admin- oder Mod-Aktion gegen Tracks, Sperren oder Meldungen ist hier protokolliert.
          Read-only — Einträge können nicht gelöscht oder geändert werden.
        </p>
      </div>

      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 18 }}>
        {ACTION_FILTERS.map((f) => {
          const active = filter === f.id;
          return (
            <button
              key={f.id}
              onClick={() => setFilter(f.id)}
              style={{
                padding: '6px 12px', borderRadius: 100, fontSize: 12, fontWeight: 600, cursor: 'pointer',
                background: active ? 'rgba(255,77,141,0.18)' : (dark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.04)'),
                color: active ? '#ff4d8d' : 'inherit',
                border: active ? '1px solid rgba(255,77,141,0.4)' : (dark ? '1px solid rgba(255,255,255,0.10)' : '1px solid rgba(0,0,0,0.06)'),
              }}
            >
              {f.label}
            </button>
          );
        })}
      </div>

      {list === null ? (
        <ApGlass dark={dark} radius={20} padding={32} style={{ textAlign: 'center', opacity: 0.6 }}>
          Lädt…
        </ApGlass>
      ) : list.length === 0 ? (
        <ApGlass dark={dark} radius={20} padding={36} style={{ textAlign: 'center' }}>
          <div style={{ fontSize: 14, opacity: 0.7 }}>Keine Einträge mit diesem Filter.</div>
        </ApGlass>
      ) : (
        <ApGlass dark={dark} radius={20} padding={6}>
          {list.map((e, i) => (
            <AuditRow key={e.id} entry={e} dark={dark}
              border={i < list.length - 1}/>
          ))}
        </ApGlass>
      )}
    </div>
  );
}

function AuditRow({ entry, dark, border }) {
  const actor = playerByIdent(entry.actor);
  const when = new Date(entry.ts).toLocaleString('de-DE');
  return (
    <div style={{
      display: 'flex', alignItems: 'flex-start', gap: 14, padding: '12px 14px',
      borderBottom: border ? (dark ? '1px solid rgba(255,255,255,0.05)' : '1px solid rgba(0,0,0,0.04)') : 'none',
    }}>
      <div style={{
        flex: '0 0 160px', fontSize: 11.5, opacity: 0.65,
        fontFamily: 'ui-monospace, SFMono-Regular, monospace',
      }}>
        {when}
      </div>

      {/* Actor column: 180px hard-clipped. The actor field is often
          a 64-char fivem identifier hex which would otherwise spill
          into the action column and visually overlap it. Both branches
          (matched roster player + raw-identifier fallback) get
          ellipsis truncation. */}
      <div style={{ flex: '0 0 180px', minWidth: 0, overflow: 'hidden' }}>
        {actor ? (
          <ApPlayerName player={actor} size={12.5} opacity={1}
            style={{ display: 'flex', maxWidth: '100%' }}/>
        ) : (
          <div style={{
            fontSize: 12, opacity: 0.5, fontStyle: 'italic',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }} title={entry.actor || 'system'}>
            {entry.actor || 'system'}
          </div>
        )}
        {entry.actorGroup && (
          <div style={{
            fontSize: 10, opacity: 0.5, marginTop: 1,
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }}>
            {entry.actorGroup}
          </div>
        )}
      </div>

      <div style={{ flex: 1, minWidth: 0, overflow: 'hidden' }}>
        <div style={{
          fontSize: 12.5, fontWeight: 700, color: actionColor(entry.action),
          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
        }}>
          {entry.action}
        </div>
        {entry.target && (
          <div style={{
            fontSize: 11, opacity: 0.6, marginTop: 2,
            fontFamily: 'ui-monospace, SFMono-Regular, monospace',
            whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
          }} title={entry.target}>
            → {entry.target}
          </div>
        )}
        {entry.details && (
          <div style={{
            fontSize: 11, opacity: 0.55, marginTop: 4, lineHeight: 1.45,
            wordBreak: 'break-word',
          }}>
            {detailsAsText(entry.details)}
          </div>
        )}
      </div>

      <div style={{
        flex: '0 0 110px', textAlign: 'right',
        fontSize: 10.5, opacity: 0.45,
        fontFamily: 'ui-monospace, SFMono-Regular, monospace',
      }}>
        {entry.ip || '—'}
      </div>
    </div>
  );
}

// Simple key:value flattening — keeps the row compact while still
// surfacing the most useful fields. Unknown shapes fall through to
// JSON.stringify for "tell me everything I logged".
function detailsAsText(d) {
  if (!d || typeof d !== 'object') return String(d || '');
  const parts = [];
  for (const k of Object.keys(d)) {
    const v = d[k];
    if (v == null) continue;
    if (typeof v === 'object') parts.push(`${k}=${JSON.stringify(v)}`);
    else                       parts.push(`${k}=${v}`);
  }
  return parts.join(' · ');
}

function actionColor(action) {
  if (action.includes('failure'))      return '#f87171';
  if (action.includes('delete'))       return '#f87171';
  if (action.includes('force-accept')) return '#34d399';
  if (action.includes('force-reject')) return '#fbbf24';
  if (action.includes('block'))        return '#fb923c';
  if (action.includes('login'))        return '#3eb8ff';
  return '#a78bfa';
}

window.AuditScreen = AuditScreen;
