// /admin — the admin home base.
//
// Topics 12 and 13 both expanded the admin's repertoire without giving
// it a centralized home. Slice 7 consolidates them: role management,
// the §6.2 app-wide write-mute, the audit-log viewer, the
// graduation-readiness queue, and a read of the permission-events log
// — five thin sub-surfaces behind a left-rail menu.
//
// The page is admin-only; the App.jsx route mounts it only when the
// viewer's role is owner or admin, and every /api/admin/* endpoint
// guards independently.

import { useEffect, useMemo, useState } from 'react'
import { Routes, Route, NavLink, Link } from 'react-router-dom'
import {
  listAdminUsers,
  setUserRole,
  setUserMute,
  listAuditLog,
  listPermissionEvents,
  listGraduationQueue,
} from '../api.js'

const TABS = [
  { path: 'users', label: 'Users' },
  { path: 'graduation', label: 'Graduation queue' },
  { path: 'audit', label: 'Audit log' },
  { path: 'permissions', label: 'Permission events' },
]

export default function Admin({ viewer }) {
  return (
    <div className="admin-page">
      <nav className="admin-rail">
        <h2>Admin</h2>
        <ul>
          {TABS.map(t => (
            <li key={t.path}>
              <NavLink
                to={t.path}
                className={({ isActive }) => `admin-rail-link ${isActive ? 'active' : ''}`}
              >
                {t.label}
              </NavLink>
            </li>
          ))}
        </ul>
        <p className="admin-rail-note">
          Signed in as <strong>{viewer.display_name}</strong> ({viewer.role}).
          You can <Link to="/">return to the catalog</Link> at any time.
        </p>
      </nav>
      <div className="admin-content">
        <Routes>
          <Route index element={<UsersTab />} />
          <Route path="users" element={<UsersTab />} />
          <Route path="graduation" element={<GraduationTab />} />
          <Route path="audit" element={<AuditTab />} />
          <Route path="permissions" element={<PermissionsTab />} />
        </Routes>
      </div>
    </div>
  )
}

// ── Users + role + write-mute (§6.1 / §6.2) ────────────────────────────────

function UsersTab() {
  const [users, setUsers] = useState(null)
  const [busy, setBusy] = useState({})
  const [error, setError] = useState(null)

  async function refresh() {
    setError(null)
    try {
      const r = await listAdminUsers()
      setUsers(r.items || [])
    } catch (e) {
      setError(e.message)
    }
  }

  useEffect(() => { refresh() }, [])

  async function changeRole(userId, role) {
    setBusy(b => ({ ...b, [userId]: true }))
    setError(null)
    try {
      await setUserRole(userId, role)
      setUsers(prev => prev.map(u => u.id === userId ? { ...u, role } : u))
    } catch (e) {
      setError(e.message)
    } finally {
      setBusy(b => ({ ...b, [userId]: false }))
    }
  }

  async function toggleMute(userId, muted) {
    setBusy(b => ({ ...b, [userId]: true }))
    setError(null)
    try {
      await setUserMute(userId, muted)
      setUsers(prev => prev.map(u => u.id === userId ? { ...u, muted } : u))
    } catch (e) {
      setError(e.message)
    } finally {
      setBusy(b => ({ ...b, [userId]: false }))
    }
  }

  if (users == null) return <p className="muted">Loading users…</p>

  return (
    <div className="admin-tab">
      <header className="admin-tab-header">
        <h2>Users</h2>
        <p className="muted">
          Role changes write to <code>permission_events</code>. The §6.2
          write-mute applies to contributors only — promote to admin to
          remove a user's ability to write without silencing them.
        </p>
      </header>
      {error && <p className="settings-note warning">{error}</p>}
      <table className="admin-table">
        <thead>
          <tr>
            <th>User</th>
            <th>Role</th>
            <th>Write-muted</th>
            <th>Last seen</th>
          </tr>
        </thead>
        <tbody>
          {users.map(u => (
            <tr key={u.id}>
              <td>
                <div className="user-cell">
                  <span className="user-handle">@{u.gitea_login}</span>
                  <span className="muted">{u.display_name}</span>
                </div>
              </td>
              <td>
                <select
                  value={u.role}
                  onChange={e => changeRole(u.id, e.target.value)}
                  disabled={!!busy[u.id]}
                >
                  <option value="contributor">Contributor</option>
                  <option value="admin">Admin</option>
                  <option value="owner">Owner</option>
                </select>
              </td>
              <td>
                {u.role === 'contributor' ? (
                  <label className="mute-toggle">
                    <input
                      type="checkbox"
                      checked={!!u.muted}
                      onChange={e => toggleMute(u.id, e.target.checked)}
                      disabled={!!busy[u.id]}
                    />
                    {u.muted ? 'Muted' : 'Active'}
                  </label>
                ) : (
                  <span className="muted">N/A</span>
                )}
              </td>
              <td className="muted">{u.last_seen_at}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

// ── Graduation-readiness queue (§13.2) ─────────────────────────────────────

function GraduationTab() {
  const [data, setData] = useState(null)
  const [error, setError] = useState(null)

  useEffect(() => {
    listGraduationQueue()
      .then(setData)
      .catch(e => setError(e.message))
  }, [])

  if (error) return <p className="settings-note warning">{error}</p>
  if (data == null) return <p className="muted">Loading queue…</p>

  return (
    <div className="admin-tab">
      <header className="admin-tab-header">
        <h2>Graduation queue</h2>
        <p className="muted">
          Super-drafts with owners claimed and zero blocking body-edit PRs.
          Open one to run the §13.3 graduation sequence.
        </p>
      </header>

      <h3 className="admin-section-h">Ready ({data.ready.length})</h3>
      {data.ready.length === 0 && (
        <p className="muted">No super-drafts ready right now.</p>
      )}
      <ul className="grad-queue">
        {data.ready.map(item => (
          <li key={item.slug}>
            <Link to={`/rfc/${item.slug}`} className="grad-queue-link">
              <strong>{item.title}</strong>
              <span className="muted"> — owners: {item.owners.join(', ')}</span>
            </Link>
          </li>
        ))}
      </ul>

      <h3 className="admin-section-h">Blocked ({data.blocked.length})</h3>
      {data.blocked.length === 0 && (
        <p className="muted">No blocked super-drafts.</p>
      )}
      <ul className="grad-queue">
        {data.blocked.map(item => (
          <li key={item.slug}>
            <Link to={`/rfc/${item.slug}`} className="grad-queue-link">
              <strong>{item.title}</strong>
              <span className="muted">
                {' — '}
                {!item.owners_set && 'no owners yet'}
                {!item.owners_set && item.blocking_prs > 0 && '; '}
                {item.blocking_prs > 0 && `${item.blocking_prs} open body-edit PR${item.blocking_prs === 1 ? '' : 's'}`}
              </span>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

// ── Audit log (`actions`) — filter chips + paging ──────────────────────────

function AuditTab() {
  const [data, setData] = useState(null)
  const [filters, setFilters] = useState({ actionKind: '', actorUserId: '', rfcSlug: '' })
  const [error, setError] = useState(null)

  async function load(beforeId = null) {
    setError(null)
    try {
      const r = await listAuditLog({
        actionKind: filters.actionKind || undefined,
        actorUserId: filters.actorUserId ? Number(filters.actorUserId) : undefined,
        rfcSlug: filters.rfcSlug || undefined,
        beforeId,
        limit: 100,
      })
      setData(r)
    } catch (e) {
      setError(e.message)
    }
  }

  useEffect(() => { load() }, [filters])

  const kinds = useMemo(() => data?.action_kinds || [], [data])

  return (
    <div className="admin-tab">
      <header className="admin-tab-header">
        <h2>Audit log</h2>
        <p className="muted">
          Every bot-mediated write lands here. The most recent rows show first;
          filter to narrow to one kind, one actor, or one RFC.
        </p>
      </header>

      <div className="audit-filters">
        <select
          value={filters.actionKind}
          onChange={e => setFilters(f => ({ ...f, actionKind: e.target.value }))}
        >
          <option value="">All action kinds</option>
          {kinds.map(k => <option key={k} value={k}>{k}</option>)}
        </select>
        <input
          type="text"
          placeholder="RFC slug…"
          value={filters.rfcSlug}
          onChange={e => setFilters(f => ({ ...f, rfcSlug: e.target.value }))}
        />
        <input
          type="number"
          placeholder="Actor user_id…"
          value={filters.actorUserId}
          onChange={e => setFilters(f => ({ ...f, actorUserId: e.target.value }))}
        />
      </div>

      {error && <p className="settings-note warning">{error}</p>}
      {data == null && <p className="muted">Loading…</p>}
      {data?.items?.length === 0 && (
        <p className="muted">No rows match this filter.</p>
      )}
      {data?.items?.length > 0 && (
        <table className="admin-table audit-table">
          <thead>
            <tr>
              <th>When</th>
              <th>Action</th>
              <th>Actor</th>
              <th>On behalf of</th>
              <th>RFC</th>
              <th>PR / branch</th>
            </tr>
          </thead>
          <tbody>
            {data.items.map(row => (
              <tr key={row.id}>
                <td className="muted">{row.created_at}</td>
                <td><code>{row.action_kind}</code></td>
                <td>{row.actor_display || row.actor_login || '—'}</td>
                <td>{row.on_behalf_of}</td>
                <td>{row.rfc_slug || '—'}</td>
                <td>
                  {row.pr_number != null && <span>#{row.pr_number} </span>}
                  {row.branch_name && <code>{row.branch_name}</code>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
      {data?.has_more && (
        <button
          className="btn-link-muted"
          onClick={() => load(data.items[data.items.length - 1].id)}
        >
          Load older →
        </button>
      )}
    </div>
  )
}

// ── Permission events (`permission_events`) ────────────────────────────────

function PermissionsTab() {
  const [data, setData] = useState(null)
  const [error, setError] = useState(null)

  useEffect(() => {
    listPermissionEvents({ limit: 100 })
      .then(setData)
      .catch(e => setError(e.message))
  }, [])

  if (error) return <p className="settings-note warning">{error}</p>
  if (data == null) return <p className="muted">Loading…</p>

  return (
    <div className="admin-tab">
      <header className="admin-tab-header">
        <h2>Permission events</h2>
        <p className="muted">
          Every role change and write-mute toggle. The companion to the
          audit log, scoped to authorization changes.
        </p>
      </header>
      {data.items.length === 0 && (
        <p className="muted">No permission events yet.</p>
      )}
      {data.items.length > 0 && (
        <table className="admin-table">
          <thead>
            <tr>
              <th>When</th>
              <th>Event</th>
              <th>Actor</th>
              <th>Subject</th>
              <th>Details</th>
            </tr>
          </thead>
          <tbody>
            {data.items.map(r => (
              <tr key={r.id}>
                <td className="muted">{r.created_at}</td>
                <td><code>{r.event_kind}</code></td>
                <td>{r.actor_display || r.actor_login || '—'}</td>
                <td>{r.subject_display || r.subject_login || '—'}</td>
                <td className="muted">
                  {r.details ? formatDetails(r.details) : ''}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </div>
  )
}

function formatDetails(details) {
  if (!details || typeof details !== 'object') return String(details ?? '')
  if (details.before != null && details.after != null) {
    return `${String(details.before)} → ${String(details.after)}`
  }
  return JSON.stringify(details)
}
