import { useEffect, useMemo, useState, type FormEvent } from 'react'
import './App.css'
import {
  addMembership,
  approveNode,
  createControlPlane,
  createNetwork,
  createToken,
  createUser,
  deleteControlPlane,
  deleteMembership,
  deleteNetwork,
  getAcl,
  getKeyPolicy,
  getMe,
  getUser,
  listAdminAudit,
  listControlPlaneAudit,
  listControlPlanes,
  listNetworks,
  listNodes,
  listProviders,
  listRoles,
  listUsers,
  login,
  logout,
  nodeKeys,
  revokeNode,
  revokeToken,
  rotateNodeKeys,
  setUserPassword,
  updateAcl,
  updateControlPlane,
  updateKeyPolicy,
  updateUser,
  verifyControlPlane,
  type AdminAuditEntry,
  type AdminNodesResponse,
  type AuditLogResponse,
  type ControlPlaneSummary,
  type CreateTokenResponse,
  type EnrollmentToken,
  type KeyHistoryResponse,
  type KeyPolicyResponse,
  type NetworkSummary,
  type NodeInfo,
  type AuthSession,
  type AuthUserSummary,
  type ProviderSummary,
  type RoleSummary,
  type UserDetail,
  type UserSummary,
} from './api'

type SectionId =
  | 'overview'
  | 'control-planes'
  | 'networks'
  | 'nodes'
  | 'tokens'
  | 'acl'
  | 'key-policy'
  | 'users'
  | 'audit'

type BannerTone = 'info' | 'warning' | 'error' | 'success'

type BannerMessage = {
  tone: BannerTone
  text: string
}

const sections: { id: SectionId; label: string; hint: string }[] = [
  { id: 'overview', label: 'Overview', hint: 'Pulse & posture' },
  { id: 'control-planes', label: 'Control Planes', hint: 'Origins & routes' },
  { id: 'networks', label: 'Networks', hint: 'Provision & catalog' },
  { id: 'nodes', label: 'Nodes', hint: 'Approve & rotate' },
  { id: 'tokens', label: 'Tokens', hint: 'Invite securely' },
  { id: 'acl', label: 'ACL', hint: 'Policy canvas' },
  { id: 'key-policy', label: 'Key Policy', hint: 'Rotation cadence' },
  { id: 'users', label: 'Users', hint: 'Access graph' },
  { id: 'audit', label: 'Audit', hint: 'Trace every move' },
]

const DEFAULT_SCOPE = { scope_type: 'global', scope_id: 'global' }

function App() {
  const [authReady, setAuthReady] = useState(false)
  const [session, setSession] = useState<AuthSession | null>(null)

  useEffect(() => {
    getMe()
      .then((me) => setSession(me))
      .catch(() => setSession(null))
      .finally(() => setAuthReady(true))
  }, [])

  if (!authReady) {
    return (
      <div className="screen center">
        <div className="loader">Loading console...</div>
      </div>
    )
  }

  if (!session) {
    return <LoginScreen onAuthed={setSession} />
  }

  if (!session.console_access) {
    return (
      <div className="screen center">
        <div className="card" style={{ maxWidth: 560 }}>
          <h3>Console access is not granted</h3>
          <p className="muted">
            This account is authenticated, but it does not have the
            <code>console:access</code> permission.
          </p>
          <div className="button-row">
            <button
              className="ghost"
              onClick={async () => {
                await logout()
                setSession(null)
              }}
            >
              Sign out
            </button>
          </div>
        </div>
      </div>
    )
  }

  return (
    <AdminShell
      user={session.user}
      permissions={session.permissions}
      onLogout={() => setSession(null)}
      onSessionUpdated={setSession}
    />
  )
}

function LoginScreen({ onAuthed }: { onAuthed: (session: AuthSession) => void }) {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [providers, setProviders] = useState<ProviderSummary[]>([])
  const [error, setError] = useState<string | null>(null)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    listProviders()
      .then(setProviders)
      .catch(() => setProviders([]))
  }, [])

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault()
    setLoading(true)
    setError(null)
    try {
      const response = await login(email, password)
      onAuthed(response)
    } catch (err) {
      setError((err as Error).message)
    } finally {
      setLoading(false)
    }
  }

  return (
    <div className="screen">
      <div className="login-grid">
        <div className="login-panel">
          <div className="brand">
            <span className="brand-mark">LS</span>
            <div>
              <p className="brand-title">Lightscale Admin</p>
              <p className="brand-sub">Orchestrate control planes with intent.</p>
            </div>
          </div>

          <form onSubmit={handleSubmit} className="stack">
            <label>
              <span>Email</span>
              <input
                type="email"
                value={email}
                onChange={(event) => setEmail(event.target.value)}
                required
              />
            </label>
            <label>
              <span>Password</span>
              <input
                type="password"
                value={password}
                onChange={(event) => setPassword(event.target.value)}
                required
              />
            </label>
            {error && <div className="notice error">{error}</div>}
            <button type="submit" disabled={loading}>
              {loading ? 'Signing in...' : 'Sign in'}
            </button>
          </form>

          {providers.length > 0 && (
            <div className="oidc-block">
              <p className="section-title">Single sign-on</p>
              <div className="pill-row">
                {providers.map((provider) => (
                  <a
                    key={provider.id}
                    className="pill"
                    href={`/admin/api/auth/oidc/${provider.id}/login?next=/`}
                  >
                    {provider.name}
                  </a>
                ))}
              </div>
            </div>
          )}
        </div>
        <div className="login-hero">
          <div className="hero-card">
            <p className="hero-title">Zero single points of failure.</p>
            <p className="hero-copy">
              Build a multi-region control plane ledger backed by CockroachDB and manage it
              in one place.
            </p>
            <div className="hero-points">
              <div>
                <h4>Layered auth</h4>
                <p>Local accounts, OIDC, and scoped roles with audit trails.</p>
              </div>
              <div>
                <h4>Operational focus</h4>
                <p>Approve nodes, rotate keys, and author network policy rapidly.</p>
              </div>
              <div>
                <h4>Designed to scale</h4>
                <p>Aggregate multiple control planes without a monolith.</p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

function AdminShell({
  user,
  permissions,
  onLogout,
  onSessionUpdated,
}: {
  user: AuthUserSummary
  permissions: string[]
  onLogout: () => void
  onSessionUpdated: (session: AuthSession) => void
}) {
  const [active, setActive] = useState<SectionId>('overview')
  const [banner, setBanner] = useState<BannerMessage | null>(null)

  const [controlPlanes, setControlPlanes] = useState<ControlPlaneSummary[]>([])
  const [networks, setNetworks] = useState<NetworkSummary[]>([])
  const [roles, setRoles] = useState<RoleSummary[]>([])
  const [users, setUsers] = useState<UserSummary[]>([])
  const [selectedControlPlaneId, setSelectedControlPlaneId] = useState<string>('')
  const [selectedNetworkId, setSelectedNetworkId] = useState<string>('')
  const [selectedUser, setSelectedUser] = useState<UserDetail | null>(null)

  const [nodesResponse, setNodesResponse] = useState<AdminNodesResponse | null>(null)
  const [keyHistory, setKeyHistory] = useState<KeyHistoryResponse | null>(null)
  const [aclText, setAclText] = useState('')
  const [keyPolicy, setKeyPolicy] = useState<KeyPolicyResponse | null>(null)
  const [tokenResult, setTokenResult] = useState<CreateTokenResponse | null>(null)
  const [revokedToken, setRevokedToken] = useState<EnrollmentToken | null>(null)
  const [bootstrapToken, setBootstrapToken] = useState<EnrollmentToken | null>(null)

  const [adminAudit, setAdminAudit] = useState<AdminAuditEntry[]>([])
  const [controlPlaneAudit, setControlPlaneAudit] = useState<AuditLogResponse | null>(null)

  const selectedNetwork = useMemo(
    () => networks.find((network) => network.id === selectedNetworkId) || null,
    [networks, selectedNetworkId],
  )

  const selectedNodeCount = nodesResponse?.nodes.length ?? 0

  const permissionSet = useMemo(() => new Set(permissions), [permissions])
  const hasPermission = (permission: string) =>
    user.super_admin || permissionSet.has(permission)

  const canControlPlanesRead = hasPermission('control_planes:read')
  const canControlPlanesWrite = hasPermission('control_planes:write')
  const canNetworksRead = hasPermission('networks:read')
  const canNetworksWrite = hasPermission('networks:write')
  const canNodesRead = hasPermission('nodes:read')
  const canNodesWrite = hasPermission('nodes:write')
  const canTokensWrite = hasPermission('tokens:write')
  const canAclRead = hasPermission('acl:read')
  const canAclWrite = hasPermission('acl:write')
  const canKeyPolicyRead = hasPermission('key_policy:read')
  const canKeyPolicyWrite = hasPermission('key_policy:write')
  const canUsersRead = hasPermission('users:read')
  const canUsersWrite = hasPermission('users:write')
  const canRolesRead = hasPermission('roles:read')
  const canAuditRead = hasPermission('audit:read')

  const visibleSections = useMemo(
    () =>
      sections.filter((section) => {
        switch (section.id) {
          case 'overview':
            return true
          case 'control-planes':
            return canControlPlanesRead
          case 'networks':
            return canNetworksRead
          case 'nodes':
            return canNodesRead
          case 'tokens':
            return canTokensWrite
          case 'acl':
            return canAclRead
          case 'key-policy':
            return canKeyPolicyRead
          case 'users':
            return canUsersRead
          case 'audit':
            return canAuditRead
        }
      }),
    [
      canAclRead,
      canAuditRead,
      canControlPlanesRead,
      canKeyPolicyRead,
      canNetworksRead,
      canNodesRead,
      canTokensWrite,
      canUsersRead,
    ],
  )

  useEffect(() => {
    if (canControlPlanesRead) {
      refreshControlPlanes()
    }
    if (canNetworksRead) {
      refreshNetworks()
    }
    if (canRolesRead) {
      refreshRoles()
    }
    if (canUsersRead) {
      refreshUsers()
    }
  }, [canControlPlanesRead, canNetworksRead, canRolesRead, canUsersRead])

  useEffect(() => {
    if (visibleSections.some((section) => section.id === active)) {
      return
    }
    if (visibleSections.length > 0) {
      setActive(visibleSections[0].id)
    }
  }, [active, visibleSections])

  useEffect(() => {
    if (controlPlanes.length && !selectedControlPlaneId) {
      setSelectedControlPlaneId(controlPlanes[0].id)
    }
  }, [controlPlanes, selectedControlPlaneId])

  useEffect(() => {
    if (networks.length && !selectedNetworkId) {
      setSelectedNetworkId(networks[0].id)
    }
  }, [networks, selectedNetworkId])

  useEffect(() => {
    if (!selectedNetworkId) return
    if (canNodesRead) {
      listNodes(selectedNetworkId)
        .then(setNodesResponse)
        .catch((err) => handleError(err, 'error'))
    } else {
      setNodesResponse(null)
    }
    if (canAclRead) {
      getAcl(selectedNetworkId)
        .then((policy) => setAclText(JSON.stringify(policy, null, 2)))
        .catch(() => setAclText(''))
    } else {
      setAclText('')
    }
    if (canKeyPolicyRead) {
      getKeyPolicy(selectedNetworkId)
        .then(setKeyPolicy)
        .catch(() => setKeyPolicy(null))
    } else {
      setKeyPolicy(null)
    }
  }, [selectedNetworkId, canAclRead, canKeyPolicyRead, canNodesRead])

  useEffect(() => {
    if (active !== 'audit' || !canAuditRead) return
    listAdminAudit({ limit: 200 })
      .then(setAdminAudit)
      .catch((err) => handleError(err, 'error'))
  }, [active, canAuditRead])

  const refreshControlPlanes = async () => {
    try {
      const data = await listControlPlanes()
      setControlPlanes(data)
    } catch (err) {
      handleError(err, 'error')
    }
  }

  const refreshNetworks = async () => {
    try {
      const data = await listNetworks()
      setNetworks(data)
    } catch (err) {
      handleError(err, 'error')
    }
  }

  const refreshRoles = async () => {
    try {
      const data = await listRoles()
      setRoles(data)
    } catch (err) {
      handleError(err, 'error')
    }
  }

  const refreshUsers = async () => {
    try {
      const data = await listUsers()
      setUsers(data)
    } catch (err) {
      handleError(err, 'error')
    }
  }

  const handleError = (err: unknown, tone: BannerTone) => {
    setBanner({ tone, text: (err as Error).message })
    setTimeout(() => setBanner(null), 4000)
  }

  const handleLogout = async () => {
    try {
      await logout()
    } finally {
      onLogout()
    }
  }

  const handleSelectUser = async (userId: string) => {
    try {
      const detail = await getUser(userId)
      setSelectedUser(detail)
    } catch (err) {
      handleError(err, 'error')
    }
  }

  const handleUpdateCurrentUser = async () => {
    try {
      const refreshed = await getMe()
      if (!refreshed.console_access) {
        onLogout()
        return
      }
      onSessionUpdated(refreshed)
    } catch (err) {
      handleError(err, 'warning')
    }
  }

  const handleNodeAction = async (action: () => Promise<unknown>) => {
    try {
      await action()
      if (selectedNetworkId) {
        const updated = await listNodes(selectedNetworkId)
        setNodesResponse(updated)
      }
    } catch (err) {
      handleError(err, 'error')
    }
  }

  const handleAclSave = async () => {
    if (!selectedNetworkId) return
    try {
      const parsed = JSON.parse(aclText)
      await updateAcl(selectedNetworkId, parsed)
      handleError(new Error('ACL updated.'), 'success')
    } catch (err) {
      handleError(err, 'error')
    }
  }

  const handleKeyPolicySave = async (maxAge: number | null) => {
    if (!selectedNetworkId) return
    try {
      const updated = await updateKeyPolicy(selectedNetworkId, {
        max_age_seconds: maxAge || null,
      })
      setKeyPolicy(updated)
      handleError(new Error('Key policy updated.'), 'success')
    } catch (err) {
      handleError(err, 'error')
    }
  }

  return (
    <div className="app-shell">
      <aside className="sidebar">
        <div className="brand-mini">
          <span>LS</span>
          <div>
            <p>Lightscale</p>
            <small>Admin console</small>
          </div>
        </div>
        <nav className="nav">
          {visibleSections.map((section) => (
            <button
              key={section.id}
              className={active === section.id ? 'active' : ''}
              onClick={() => setActive(section.id)}
            >
              <span>{section.label}</span>
              <small>{section.hint}</small>
            </button>
          ))}
        </nav>
        <div className="sidebar-footer">
          <div>
            <p>{user.display_name || user.email}</p>
            <small>{user.super_admin ? 'Super admin' : 'Operator'}</small>
          </div>
          <button className="ghost" onClick={handleLogout}>
            Sign out
          </button>
        </div>
      </aside>

      <main className="main">
        <header className="topbar">
          <div>
            <h1>{visibleSections.find((section) => section.id === active)?.label || 'Overview'}</h1>
            <p>
              {selectedNetwork
                ? `${selectedNetwork.name} · ${selectedNetwork.control_plane_name}`
                : 'Select a network to unlock node actions.'}
            </p>
          </div>
          <div className="selector-row">
            <label>
              <span>Control plane</span>
              <select
                value={selectedControlPlaneId}
                onChange={(event) => setSelectedControlPlaneId(event.target.value)}
              >
                <option value="">Select</option>
                {controlPlanes.map((plane) => (
                  <option key={plane.id} value={plane.id}>
                    {plane.name}
                  </option>
                ))}
              </select>
            </label>
            <label>
              <span>Network</span>
              <select
                value={selectedNetworkId}
                onChange={(event) => setSelectedNetworkId(event.target.value)}
              >
                <option value="">Select</option>
                {networks.map((network) => (
                  <option key={network.id} value={network.id}>
                    {network.name}
                  </option>
                ))}
              </select>
            </label>
            <button className="ghost" onClick={handleUpdateCurrentUser}>
              Refresh
            </button>
          </div>
        </header>

        {banner && <div className={`banner ${banner.tone}`}>{banner.text}</div>}

        <section className="content">
          {active === 'overview' && (
            <div className="grid two">
              <div className="card highlight">
                <h3>Control plane mesh</h3>
                <p>{controlPlanes.length} control planes online.</p>
                <div className="metrics">
                  <div>
                    <span>Networks</span>
                    <strong>{networks.length}</strong>
                  </div>
                  <div>
                    <span>Nodes (selected)</span>
                    <strong>{selectedNodeCount}</strong>
                  </div>
                </div>
              </div>
              <div className="card">
                <h3>Active signals</h3>
                <p>Audit log for admin actions and control plane events.</p>
                {canAuditRead ? (
                  <button className="ghost" onClick={() => setActive('audit')}>
                    View audit timeline
                  </button>
                ) : (
                  <p className="muted">No audit permission.</p>
                )}
              </div>
              <div className="card">
                <h3>Role coverage</h3>
                <p>
                  {roles.length} roles configured. {users.length} users in
                  directory.
                </p>
                {canUsersRead ? (
                  <button className="ghost" onClick={() => setActive('users')}>
                    Manage access
                  </button>
                ) : (
                  <p className="muted">No user-directory permission.</p>
                )}
              </div>
              <div className="card">
                <h3>Network posture</h3>
                <p>Keep ACLs tight and key rotation moving.</p>
                {canAclRead ? (
                  <button className="ghost" onClick={() => setActive('acl')}>
                    Edit ACL
                  </button>
                ) : (
                  <p className="muted">No ACL permission.</p>
                )}
              </div>
            </div>
          )}

          {active === 'control-planes' && canControlPlanesRead && (
            <ControlPlaneSection
              controlPlanes={controlPlanes}
              canWrite={canControlPlanesWrite}
              onCreate={async (payload) => {
                const created = await createControlPlane(payload)
                setControlPlanes((prev) => [...prev, created])
              }}
              onUpdate={async (id, payload) => {
                const updated = await updateControlPlane(id, payload)
                setControlPlanes((prev) =>
                  prev.map((plane) => (plane.id === updated.id ? updated : plane)),
                )
              }}
              onVerify={async (id) => verifyControlPlane(id)}
              onDelete={async (id) => {
                await deleteControlPlane(id)
                setControlPlanes((prev) => prev.filter((plane) => plane.id !== id))
              }}
              onBanner={setBanner}
            />
          )}

          {active === 'networks' && canNetworksRead && (
            <NetworksSection
              controlPlanes={controlPlanes}
              networks={networks}
              canWrite={canNetworksWrite}
              onCreate={async (payload) => {
                const result = await createNetwork(payload)
                setNetworks((prev) => [...prev, result.network])
                setBootstrapToken(result.bootstrap_token || null)
                setSelectedNetworkId(result.network.id)
              }}
              onDelete={async (id) => {
                await deleteNetwork(id)
                setNetworks((prev) => prev.filter((network) => network.id !== id))
              }}
              onSelect={(id) => setSelectedNetworkId(id)}
              selectedNetworkId={selectedNetworkId}
              bootstrapToken={bootstrapToken}
            />
          )}

          {active === 'nodes' && canNodesRead && (
            <NodesSection
              network={selectedNetwork}
              nodes={nodesResponse?.nodes || []}
              keyHistory={keyHistory}
              canWrite={canNodesWrite}
              onApprove={(nodeId) =>
                handleNodeAction(() => approveNode(selectedNetworkId, nodeId))
              }
              onRevoke={(nodeId) =>
                handleNodeAction(() => revokeNode(selectedNetworkId, nodeId))
              }
              onRotate={(nodeId) =>
                handleNodeAction(() => rotateNodeKeys(selectedNetworkId, nodeId, {}))
              }
              onViewKeys={async (nodeId) => {
                if (!selectedNetworkId) return
                try {
                  const history = await nodeKeys(selectedNetworkId, nodeId)
                  setKeyHistory(history)
                } catch (err) {
                  handleError(err, 'error')
                }
              }}
            />
          )}

          {active === 'tokens' && canTokensWrite && (
            <TokensSection
              network={selectedNetwork}
              tokenResult={tokenResult}
              revokedToken={revokedToken}
              onCreate={async (payload) => {
                if (!selectedNetworkId) return
                const response = await createToken(selectedNetworkId, payload)
                setTokenResult(response)
                setRevokedToken(null)
              }}
              onRevoke={async (tokenId) => {
                if (!selectedNetworkId) return
                const response = await revokeToken(selectedNetworkId, tokenId)
                setRevokedToken(response)
              }}
            />
          )}

          {active === 'acl' && canAclRead && (
            <AclSection
              network={selectedNetwork}
              aclText={aclText}
              canWrite={canAclWrite}
              onChange={setAclText}
              onSave={handleAclSave}
            />
          )}

          {active === 'key-policy' && canKeyPolicyRead && (
            <KeyPolicySection
              network={selectedNetwork}
              policy={keyPolicy}
              canWrite={canKeyPolicyWrite}
              onSave={handleKeyPolicySave}
            />
          )}

          {active === 'users' && canUsersRead && (
            <UsersSection
              users={users}
              roles={roles}
              selectedUser={selectedUser}
              canWrite={canUsersWrite}
              onSelect={handleSelectUser}
              onCreate={async (payload) => {
                const created = await createUser(payload)
                setUsers((prev) => [created.user, ...prev])
                setSelectedUser(created)
              }}
              onUpdate={async (userId, payload) => {
                const updated = await updateUser(userId, payload)
                setUsers((prev) =>
                  prev.map((record) => (record.id === updated.id ? updated : record)),
                )
                if (selectedUser && selectedUser.user.id === updated.id) {
                  setSelectedUser({
                    ...selectedUser,
                    user: updated,
                  })
                }
              }}
              onSetPassword={async (userId, password) => {
                await setUserPassword(userId, password)
              }}
              onAddMembership={async (userId, payload) => {
                const membership = await addMembership(userId, payload)
                if (selectedUser && selectedUser.user.id === userId) {
                  setSelectedUser({
                    ...selectedUser,
                    memberships: [membership, ...selectedUser.memberships],
                  })
                }
              }}
              onDeleteMembership={async (userId, membershipId) => {
                await deleteMembership(userId, membershipId)
                if (selectedUser && selectedUser.user.id === userId) {
                  setSelectedUser({
                    ...selectedUser,
                    memberships: selectedUser.memberships.filter(
                      (membership) => membership.id !== membershipId,
                    ),
                  })
                }
              }}
            />
          )}

          {active === 'audit' && canAuditRead && (
            <AuditSection
              controlPlanes={controlPlanes}
              adminAudit={adminAudit}
              controlPlaneAudit={controlPlaneAudit}
              onRefreshAdmin={async () => {
                const entries = await listAdminAudit({ limit: 200 })
                setAdminAudit(entries)
              }}
              onFetchControlPlane={async (id, params) => {
                const response = await listControlPlaneAudit(id, params)
                setControlPlaneAudit(response)
              }}
            />
          )}
        </section>
      </main>
    </div>
  )
}

function ControlPlaneSection({
  controlPlanes,
  canWrite,
  onCreate,
  onUpdate,
  onVerify,
  onDelete,
  onBanner,
}: {
  controlPlanes: ControlPlaneSummary[]
  canWrite: boolean
  onCreate: (payload: {
    name: string
    base_url: string
    admin_token?: string
    region?: string
  }) => Promise<void>
  onUpdate: (
    id: string,
    payload: {
      name?: string
      base_url?: string
      admin_token?: string
      clear_admin_token?: boolean
      region?: string
    },
  ) => Promise<void>
  onVerify: (id: string) => Promise<{ ok: boolean; status?: number; body?: string }>
  onDelete: (id: string) => Promise<void>
  onBanner: (message: BannerMessage) => void
}) {
  const [form, setForm] = useState({
    id: '',
    name: '',
    base_url: '',
    admin_token: '',
    region: '',
    clear_admin_token: false,
  })
  const [loading, setLoading] = useState(false)

  const resetForm = () => {
    setForm({
      id: '',
      name: '',
      base_url: '',
      admin_token: '',
      region: '',
      clear_admin_token: false,
    })
  }

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault()
    if (!canWrite) return
    setLoading(true)
    try {
      if (form.id) {
        await onUpdate(form.id, {
          name: form.name,
          base_url: form.base_url,
          admin_token: form.admin_token || undefined,
          clear_admin_token: form.clear_admin_token,
          region: form.region || undefined,
        })
        onBanner({ tone: 'success', text: 'Control plane updated.' })
      } else {
        await onCreate({
          name: form.name,
          base_url: form.base_url,
          admin_token: form.admin_token || undefined,
          region: form.region || undefined,
        })
        onBanner({ tone: 'success', text: 'Control plane created.' })
      }
      resetForm()
    } catch (err) {
      onBanner({ tone: 'error', text: (err as Error).message })
    } finally {
      setLoading(false)
    }
  }

  return (
    <div className="grid two">
      <div className="card">
        <h3>Create or update control plane</h3>
        <form onSubmit={handleSubmit} className="stack">
          <label>
            <span>Name</span>
            <input
              value={form.name}
              onChange={(event) => setForm({ ...form, name: event.target.value })}
              required
            />
          </label>
          <label>
            <span>Base URL</span>
            <input
              value={form.base_url}
              onChange={(event) => setForm({ ...form, base_url: event.target.value })}
              placeholder="https://control-plane.example.com"
              required
            />
          </label>
          <label>
            <span>Admin token</span>
            <input
              value={form.admin_token}
              onChange={(event) => setForm({ ...form, admin_token: event.target.value })}
              placeholder={form.id ? 'Leave blank to keep current' : 'Optional'}
            />
          </label>
          {form.id && (
            <label className="toggle">
              <input
                type="checkbox"
                checked={form.clear_admin_token}
                onChange={(event) =>
                  setForm({ ...form, clear_admin_token: event.target.checked })
                }
              />
              <span>Clear stored token</span>
            </label>
          )}
          <label>
            <span>Region</span>
            <input
              value={form.region}
              onChange={(event) => setForm({ ...form, region: event.target.value })}
              placeholder="ap-northeast-1"
            />
          </label>
          <div className="button-row">
            <button type="submit" disabled={loading || !canWrite}>
              {loading ? 'Saving...' : form.id ? 'Update plane' : 'Create plane'}
            </button>
            {form.id && (
              <button type="button" className="ghost" onClick={resetForm}>
                Cancel
              </button>
            )}
          </div>
        </form>
      </div>
      <div className="card">
        <h3>Registered control planes</h3>
        <div className="list">
          {controlPlanes.map((plane) => (
            <div key={plane.id} className="list-row">
              <div>
                <strong>{plane.name}</strong>
                <p>{plane.base_url}</p>
                <span className="tag">{plane.region || 'unassigned'}</span>
                {plane.has_admin_token ? (
                  <span className="tag success">token stored</span>
                ) : (
                  <span className="tag">no token</span>
                )}
              </div>
              <div className="button-row">
                <button
                  className="ghost"
                  onClick={async () => {
                    const result = await onVerify(plane.id)
                    onBanner({
                      tone: result.ok ? 'success' : 'warning',
                      text: result.ok
                        ? 'Health check OK.'
                        : `Health check failed (${result.status ?? 'no status'}).`,
                    })
                  }}
                >
                  Verify
                </button>
                {canWrite && (
                  <>
                    <button
                      className="ghost"
                      onClick={() =>
                        setForm({
                          id: plane.id,
                          name: plane.name,
                          base_url: plane.base_url,
                          admin_token: '',
                          region: plane.region || '',
                          clear_admin_token: false,
                        })
                      }
                    >
                      Edit
                    </button>
                    <button
                      className="ghost danger"
                      onClick={() => {
                        if (window.confirm(`Delete control plane "${plane.name}"?`)) {
                          onDelete(plane.id)
                        }
                      }}
                    >
                      Delete
                    </button>
                  </>
                )}
              </div>
            </div>
          ))}
          {controlPlanes.length === 0 && (
            <p className="muted">No control planes yet.</p>
          )}
        </div>
      </div>
    </div>
  )
}

function NetworksSection({
  controlPlanes,
  networks,
  canWrite,
  onCreate,
  onDelete,
  onSelect,
  selectedNetworkId,
  bootstrapToken,
}: {
  controlPlanes: ControlPlaneSummary[]
  networks: NetworkSummary[]
  canWrite: boolean
  onCreate: (payload: {
    control_plane_id: string
    name: string
    overlay_v4?: string
    overlay_v6?: string
    dns_domain?: string
    requires_approval?: boolean
    key_rotation_max_age_seconds?: number
    bootstrap_token_ttl_seconds?: number
    bootstrap_token_uses?: number
    bootstrap_token_tags?: string[]
  }) => Promise<void>
  onDelete: (id: string) => Promise<void>
  onSelect: (id: string) => void
  selectedNetworkId: string
  bootstrapToken: EnrollmentToken | null
}) {
  const [form, setForm] = useState({
    control_plane_id: '',
    name: '',
    overlay_v4: '',
    overlay_v6: '',
    dns_domain: '',
    requires_approval: false,
    key_rotation_max_age_seconds: '',
    bootstrap_token_ttl_seconds: '',
    bootstrap_token_uses: '1',
    bootstrap_token_tags: '',
  })

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault()
    if (!canWrite) return
    if (!form.control_plane_id) return
    await onCreate({
      control_plane_id: form.control_plane_id,
      name: form.name,
      overlay_v4: form.overlay_v4 || undefined,
      overlay_v6: form.overlay_v6 || undefined,
      dns_domain: form.dns_domain || undefined,
      requires_approval: form.requires_approval,
      key_rotation_max_age_seconds: form.key_rotation_max_age_seconds
        ? Number(form.key_rotation_max_age_seconds)
        : undefined,
      bootstrap_token_ttl_seconds: form.bootstrap_token_ttl_seconds
        ? Number(form.bootstrap_token_ttl_seconds)
        : undefined,
      bootstrap_token_uses: form.bootstrap_token_uses
        ? Number(form.bootstrap_token_uses)
        : undefined,
      bootstrap_token_tags: form.bootstrap_token_tags
        ? form.bootstrap_token_tags.split(',').map((tag) => tag.trim())
        : undefined,
    })
    setForm({
      control_plane_id: form.control_plane_id,
      name: '',
      overlay_v4: '',
      overlay_v6: '',
      dns_domain: '',
      requires_approval: false,
      key_rotation_max_age_seconds: '',
      bootstrap_token_ttl_seconds: '',
      bootstrap_token_uses: '1',
      bootstrap_token_tags: '',
    })
  }

  return (
    <div className="grid two">
      <div className="card">
        <h3>Provision a network</h3>
        <form onSubmit={handleSubmit} className="stack">
          <label>
            <span>Control plane</span>
            <select
              value={form.control_plane_id}
              onChange={(event) =>
                setForm({ ...form, control_plane_id: event.target.value })
              }
              required
            >
              <option value="">Select</option>
              {controlPlanes.map((plane) => (
                <option key={plane.id} value={plane.id}>
                  {plane.name}
                </option>
              ))}
            </select>
          </label>
          <label>
            <span>Network name</span>
            <input
              value={form.name}
              onChange={(event) => setForm({ ...form, name: event.target.value })}
              required
            />
          </label>
          <div className="inline">
            <label>
              <span>Overlay IPv4 CIDR</span>
              <input
                value={form.overlay_v4}
                onChange={(event) =>
                  setForm({ ...form, overlay_v4: event.target.value })
                }
                placeholder="100.120.0.0/24"
              />
            </label>
            <label>
              <span>Overlay IPv6 CIDR</span>
              <input
                value={form.overlay_v6}
                onChange={(event) =>
                  setForm({ ...form, overlay_v6: event.target.value })
                }
                placeholder="fd42:120:0::/48"
              />
            </label>
          </div>
          <label>
            <span>DNS domain</span>
            <input
              value={form.dns_domain}
              onChange={(event) =>
                setForm({ ...form, dns_domain: event.target.value })
              }
              placeholder="optional"
            />
          </label>
          <label className="toggle">
            <input
              type="checkbox"
              checked={form.requires_approval}
              onChange={(event) =>
                setForm({ ...form, requires_approval: event.target.checked })
              }
            />
            <span>Requires approval</span>
          </label>
          <div className="inline">
            <label>
              <span>Key rotation (sec)</span>
              <input
                type="number"
                value={form.key_rotation_max_age_seconds}
                onChange={(event) =>
                  setForm({
                    ...form,
                    key_rotation_max_age_seconds: event.target.value,
                  })
                }
              />
            </label>
            <label>
              <span>Bootstrap TTL</span>
              <input
                type="number"
                value={form.bootstrap_token_ttl_seconds}
                onChange={(event) =>
                  setForm({
                    ...form,
                    bootstrap_token_ttl_seconds: event.target.value,
                  })
                }
              />
            </label>
          </div>
          <div className="inline">
            <label>
              <span>Bootstrap uses</span>
              <input
                type="number"
                value={form.bootstrap_token_uses}
                onChange={(event) =>
                  setForm({ ...form, bootstrap_token_uses: event.target.value })
                }
              />
            </label>
            <label>
              <span>Bootstrap tags</span>
              <input
                value={form.bootstrap_token_tags}
                onChange={(event) =>
                  setForm({ ...form, bootstrap_token_tags: event.target.value })
                }
                placeholder="tag1, tag2"
              />
            </label>
          </div>
          <button type="submit" disabled={!canWrite}>Create network</button>
        </form>

        {bootstrapToken && (
          <div className="callout">
            <p className="section-title">Bootstrap token</p>
            <code>{bootstrapToken.token}</code>
            <div className="meta">
              <span>Uses left: {bootstrapToken.uses_left}</span>
              <span>Expires: {formatEpoch(bootstrapToken.expires_at)}</span>
            </div>
          </div>
        )}
      </div>
      <div className="card">
        <h3>Known networks</h3>
        <div className="list">
          {networks.map((network, index) => (
            <div
              key={network.id}
              className={`list-row ${
                network.id === selectedNetworkId ? 'active' : ''
              }`}
              style={{ animationDelay: `${index * 40}ms` }}
            >
              <div
                className="selectable-area"
                onClick={() => onSelect(network.id)}
              >
                <strong>{network.name}</strong>
                <p>{network.network_id}</p>
                <span className="tag">{network.control_plane_name}</span>
                {network.requires_approval && (
                  <span className="tag warning">approval required</span>
                )}
              </div>
              <div className="mono">{network.overlay_v4 || '-'}</div>
              <div className="button-row">
                {canWrite && (
                  <button
                    className="ghost danger"
                    onClick={() => {
                      if (window.confirm(`Delete network "${network.name}"?`)) {
                        onDelete(network.id)
                      }
                    }}
                  >
                    Delete
                  </button>
                )}
              </div>
            </div>
          ))}
          {networks.length === 0 && <p className="muted">No networks yet.</p>}
        </div>
      </div>
    </div>
  )
}

function NodesSection({
  network,
  nodes,
  keyHistory,
  canWrite,
  onApprove,
  onRevoke,
  onRotate,
  onViewKeys,
}: {
  network: NetworkSummary | null
  nodes: NodeInfo[]
  keyHistory: KeyHistoryResponse | null
  canWrite: boolean
  onApprove: (nodeId: string) => void
  onRevoke: (nodeId: string) => void
  onRotate: (nodeId: string) => void
  onViewKeys: (nodeId: string) => void
}) {
  if (!network) {
    return <div className="card">Select a network to view nodes.</div>
  }

  return (
    <div className="grid two">
      <div className="card">
        <h3>Nodes in {network.name}</h3>
        <div className="list">
          {nodes.map((node) => (
            <div key={node.id} className="list-row">
              <div>
                <strong>{node.name}</strong>
                <p>{node.dns_name}</p>
                <div className="tag-row">
                  {node.approved ? (
                    <span className="tag success">approved</span>
                  ) : (
                    <span className="tag warning">pending</span>
                  )}
                  {node.owner_is_admin && <span className="tag">admin-issued</span>}
                  {node.revoked && <span className="tag danger">revoked</span>}
                  {node.key_rotation_required && (
                    <span className="tag warning">rotate keys</span>
                  )}
                </div>
                {node.owner_email && <small>Owner: {node.owner_email}</small>}
                <small>Last seen: {formatEpoch(node.last_seen)}</small>
              </div>
              <div className="button-row">
                {canWrite && !node.approved && !node.revoked && (
                  <button onClick={() => onApprove(node.id)}>Approve</button>
                )}
                {canWrite && !node.revoked && (
                  <button className="ghost" onClick={() => onRevoke(node.id)}>
                    Revoke
                  </button>
                )}
                {canWrite && (
                  <button className="ghost" onClick={() => onRotate(node.id)}>
                    Rotate keys
                  </button>
                )}
                <button className="ghost" onClick={() => onViewKeys(node.id)}>
                  View keys
                </button>
              </div>
            </div>
          ))}
          {nodes.length === 0 && <p className="muted">No nodes yet.</p>}
        </div>
      </div>
      <div className="card">
        <h3>Key history</h3>
        {keyHistory ? (
          <div className="list">
            {keyHistory.keys.map((key) => (
              <div key={`${key.key_type}-${key.created_at}`} className="list-row">
                <div>
                  <strong>{key.key_type}</strong>
                  <p className="mono">{key.public_key}</p>
                </div>
                <div>
                  <span className="tag">{formatEpoch(key.created_at)}</span>
                  {key.revoked_at && (
                    <span className="tag danger">
                      revoked {formatEpoch(key.revoked_at)}
                    </span>
                  )}
                </div>
              </div>
            ))}
          </div>
        ) : (
          <p className="muted">Select a node to view key history.</p>
        )}
      </div>
    </div>
  )
}

function TokensSection({
  network,
  tokenResult,
  revokedToken,
  onCreate,
  onRevoke,
}: {
  network: NetworkSummary | null
  tokenResult: CreateTokenResponse | null
  revokedToken: EnrollmentToken | null
  onCreate: (payload: { ttl_seconds: number; uses: number; tags: string[] }) => void
  onRevoke: (tokenId: string) => void
}) {
  const [form, setForm] = useState({ ttl_seconds: '3600', uses: '1', tags: '' })
  const [revokeId, setRevokeId] = useState('')

  if (!network) {
    return <div className="card">Select a network to manage tokens.</div>
  }

  return (
    <div className="grid two">
      <div className="card">
        <h3>Create enrollment token</h3>
        <form
          onSubmit={(event) => {
            event.preventDefault()
            onCreate({
              ttl_seconds: Number(form.ttl_seconds),
              uses: Number(form.uses),
              tags: form.tags
                ? form.tags.split(',').map((tag) => tag.trim())
                : [],
            })
          }}
          className="stack"
        >
          <label>
            <span>TTL seconds</span>
            <input
              type="number"
              value={form.ttl_seconds}
              onChange={(event) =>
                setForm({ ...form, ttl_seconds: event.target.value })
              }
            />
          </label>
          <label>
            <span>Uses</span>
            <input
              type="number"
              value={form.uses}
              onChange={(event) => setForm({ ...form, uses: event.target.value })}
            />
          </label>
          <label>
            <span>Tags</span>
            <input
              value={form.tags}
              onChange={(event) => setForm({ ...form, tags: event.target.value })}
              placeholder="tag1, tag2"
            />
          </label>
          <button type="submit">Generate token</button>
        </form>
        {tokenResult && (
          <div className="callout">
            <p className="section-title">Generated token</p>
            <code>{tokenResult.token.token}</code>
            <div className="meta">
              <span>Uses left: {tokenResult.token.uses_left}</span>
              <span>Expires: {formatEpoch(tokenResult.token.expires_at)}</span>
            </div>
            {(tokenResult.token.owner_email || tokenResult.token.owner_is_admin) && (
              <div className="meta">
                {tokenResult.token.owner_email && (
                  <span>Owner: {tokenResult.token.owner_email}</span>
                )}
                {tokenResult.token.owner_is_admin && <span>Privilege: admin</span>}
              </div>
            )}
          </div>
        )}
      </div>
      <div className="card">
        <h3>Revoke token</h3>
        <form
          onSubmit={(event) => {
            event.preventDefault()
            onRevoke(revokeId)
          }}
          className="stack"
        >
          <label>
            <span>Token ID</span>
            <input
              value={revokeId}
              onChange={(event) => setRevokeId(event.target.value)}
            />
          </label>
          <button type="submit" className="ghost">
            Revoke token
          </button>
        </form>
        {revokedToken && (
          <div className="callout">
            <p className="section-title">Revoked token</p>
            <code>{revokedToken.token}</code>
            <span className="tag danger">revoked</span>
          </div>
        )}
      </div>
    </div>
  )
}

function AclSection({
  network,
  aclText,
  canWrite,
  onChange,
  onSave,
}: {
  network: NetworkSummary | null
  aclText: string
  canWrite: boolean
  onChange: (value: string) => void
  onSave: () => void
}) {
  if (!network) {
    return <div className="card">Select a network to edit ACL.</div>
  }

  return (
    <div className="card">
      <h3>ACL policy for {network.name}</h3>
      <textarea
        value={aclText}
        onChange={(event) => onChange(event.target.value)}
        disabled={!canWrite}
      />
      <div className="button-row">
        <button onClick={onSave} disabled={!canWrite}>
          Save policy
        </button>
      </div>
    </div>
  )
}

function KeyPolicySection({
  network,
  policy,
  canWrite,
  onSave,
}: {
  network: NetworkSummary | null
  policy: KeyPolicyResponse | null
  canWrite: boolean
  onSave: (maxAge: number | null) => void
}) {
  const [maxAge, setMaxAge] = useState('')

  useEffect(() => {
    if (policy?.policy.max_age_seconds) {
      setMaxAge(String(policy.policy.max_age_seconds))
    } else {
      setMaxAge('')
    }
  }, [policy])

  if (!network) {
    return <div className="card">Select a network to edit key policy.</div>
  }

  return (
    <div className="card">
      <h3>Key rotation policy</h3>
      <label>
        <span>Max age (seconds)</span>
        <input
          type="number"
          value={maxAge}
          onChange={(event) => setMaxAge(event.target.value)}
          disabled={!canWrite}
        />
      </label>
      <div className="button-row">
        <button
          onClick={() => onSave(maxAge ? Number(maxAge) : null)}
          disabled={!canWrite}
        >
          Save policy
        </button>
      </div>
    </div>
  )
}

function UsersSection({
  users,
  roles,
  selectedUser,
  canWrite,
  onSelect,
  onCreate,
  onUpdate,
  onSetPassword,
  onAddMembership,
  onDeleteMembership,
}: {
  users: UserSummary[]
  roles: RoleSummary[]
  selectedUser: UserDetail | null
  canWrite: boolean
  onSelect: (id: string) => void
  onCreate: (payload: {
    email: string
    display_name?: string
    password: string
    role_id?: string
    super_admin?: boolean
  }) => Promise<void>
  onUpdate: (
    userId: string,
    payload: {
      display_name?: string | null
      disabled?: boolean
      super_admin?: boolean
    },
  ) => Promise<void>
  onSetPassword: (userId: string, password: string) => Promise<void>
  onAddMembership: (
    userId: string,
    payload: { role_id: string; scope_type: string; scope_id: string },
  ) => Promise<void>
  onDeleteMembership: (userId: string, membershipId: string) => Promise<void>
}) {
  const [createForm, setCreateForm] = useState({
    email: '',
    display_name: '',
    password: '',
    role_id: '',
    super_admin: false,
  })

  const [updateForm, setUpdateForm] = useState({
    display_name: '',
    disabled: false,
    super_admin: false,
  })

  const [password, setPassword] = useState('')

  const [membershipForm, setMembershipForm] = useState({
    role_id: '',
    scope_type: DEFAULT_SCOPE.scope_type,
    scope_id: DEFAULT_SCOPE.scope_id,
  })

  useEffect(() => {
    if (!selectedUser) return
    setUpdateForm({
      display_name: selectedUser.user.display_name || '',
      disabled: selectedUser.user.disabled,
      super_admin: selectedUser.user.super_admin,
    })
  }, [selectedUser])

  return (
    <div className="grid two">
      <div className="card">
        <h3>Create user</h3>
        <form
          onSubmit={(event) => {
            event.preventDefault()
            if (!canWrite) return
            onCreate({
              email: createForm.email,
              display_name: createForm.display_name || undefined,
              password: createForm.password,
              role_id: createForm.role_id || undefined,
              super_admin: createForm.super_admin,
            })
            setCreateForm({
              email: '',
              display_name: '',
              password: '',
              role_id: createForm.role_id,
              super_admin: false,
            })
          }}
          className="stack"
        >
          <label>
            <span>Email</span>
            <input
              value={createForm.email}
              onChange={(event) =>
                setCreateForm({ ...createForm, email: event.target.value })
              }
              required
            />
          </label>
          <label>
            <span>Display name</span>
            <input
              value={createForm.display_name}
              onChange={(event) =>
                setCreateForm({ ...createForm, display_name: event.target.value })
              }
            />
          </label>
          <label>
            <span>Password</span>
            <input
              type="password"
              value={createForm.password}
              onChange={(event) =>
                setCreateForm({ ...createForm, password: event.target.value })
              }
              required
            />
          </label>
          <label>
            <span>Role</span>
            <select
              value={createForm.role_id}
              onChange={(event) =>
                setCreateForm({ ...createForm, role_id: event.target.value })
              }
            >
              <option value="">Viewer (default)</option>
              {roles.map((role) => (
                <option key={role.id} value={role.id}>
                  {role.name}
                </option>
              ))}
            </select>
          </label>
          <label className="toggle">
            <input
              type="checkbox"
              checked={createForm.super_admin}
              onChange={(event) =>
                setCreateForm({ ...createForm, super_admin: event.target.checked })
              }
            />
            <span>Super admin</span>
          </label>
          <button type="submit" disabled={!canWrite}>Create user</button>
          {!canWrite && <p className="muted">Read-only.</p>}
        </form>
      </div>
      <div className="card">
        <h3>User directory</h3>
        <div className="list">
          {users.map((record) => (
            <button
              key={record.id}
              className={`list-row selectable ${
                selectedUser?.user.id === record.id ? 'active' : ''
              }`}
              onClick={() => onSelect(record.id)}
            >
              <div>
                <strong>{record.display_name || record.email}</strong>
                <p>{record.email}</p>
                <div className="tag-row">
                  {record.super_admin && <span className="tag">super admin</span>}
                  {record.disabled && <span className="tag danger">disabled</span>}
                </div>
              </div>
              <div className="meta">
                <span>{formatDate(record.created_at)}</span>
              </div>
            </button>
          ))}
          {users.length === 0 && <p className="muted">No users yet.</p>}
        </div>
      </div>
      <div className="card">
        <h3>User detail</h3>
        {selectedUser ? (
          <div className="stack">
            <label>
              <span>Display name</span>
              <input
                value={updateForm.display_name}
                onChange={(event) =>
                  setUpdateForm({ ...updateForm, display_name: event.target.value })
                }
              />
            </label>
            <label className="toggle">
              <input
                type="checkbox"
                checked={updateForm.disabled}
                onChange={(event) =>
                  setUpdateForm({ ...updateForm, disabled: event.target.checked })
                }
              />
              <span>Disabled</span>
            </label>
            <label className="toggle">
              <input
                type="checkbox"
                checked={updateForm.super_admin}
                onChange={(event) =>
                  setUpdateForm({ ...updateForm, super_admin: event.target.checked })
                }
              />
              <span>Super admin</span>
            </label>
            <button
              disabled={!canWrite}
              onClick={() =>
                onUpdate(selectedUser.user.id, {
                  display_name: updateForm.display_name,
                  disabled: updateForm.disabled,
                  super_admin: updateForm.super_admin,
                })
              }
            >
              Save changes
            </button>
            <div className="divider" />
            <label>
              <span>Reset password</span>
              <input
                type="password"
                value={password}
                onChange={(event) => setPassword(event.target.value)}
              />
            </label>
            <button
              className="ghost"
              disabled={!canWrite}
              onClick={() => {
                if (!password) return
                onSetPassword(selectedUser.user.id, password)
                setPassword('')
              }}
            >
              Update password
            </button>
          </div>
        ) : (
          <p className="muted">Select a user to manage.</p>
        )}
      </div>
      <div className="card">
        <h3>Memberships</h3>
        {selectedUser ? (
          <div className="stack">
            <div className="list">
              {selectedUser.memberships.map((membership) => (
                <div key={membership.id} className="list-row">
                  <div>
                    <strong>{membership.role_name}</strong>
                    <p>
                      {membership.scope_type}:{membership.scope_id}
                    </p>
                  </div>
                  <button
                    className="ghost"
                    disabled={!canWrite}
                    onClick={() =>
                      onDeleteMembership(selectedUser.user.id, membership.id)
                    }
                  >
                    Remove
                  </button>
                </div>
              ))}
              {selectedUser.memberships.length === 0 && (
                <p className="muted">No memberships yet.</p>
              )}
            </div>
            <form
              onSubmit={(event) => {
                event.preventDefault()
                if (!canWrite) return
                if (!membershipForm.role_id) return
                onAddMembership(selectedUser.user.id, membershipForm)
              }}
              className="stack"
            >
              <label>
                <span>Role</span>
                <select
                  value={membershipForm.role_id}
                  onChange={(event) =>
                    setMembershipForm({
                      ...membershipForm,
                      role_id: event.target.value,
                    })
                  }
                >
                  <option value="">Select role</option>
                  {roles.map((role) => (
                    <option key={role.id} value={role.id}>
                      {role.name}
                    </option>
                  ))}
                </select>
              </label>
              <div className="inline">
                <label>
                  <span>Scope type</span>
                  <input
                    value={membershipForm.scope_type}
                    onChange={(event) =>
                      setMembershipForm({
                        ...membershipForm,
                        scope_type: event.target.value,
                      })
                    }
                  />
                </label>
                <label>
                  <span>Scope ID</span>
                  <input
                    value={membershipForm.scope_id}
                    onChange={(event) =>
                      setMembershipForm({
                        ...membershipForm,
                        scope_id: event.target.value,
                      })
                    }
                  />
                </label>
              </div>
              <button type="submit" disabled={!canWrite}>Add membership</button>
            </form>
          </div>
        ) : (
          <p className="muted">Select a user to manage memberships.</p>
        )}
      </div>
    </div>
  )
}

function AuditSection({
  controlPlanes,
  adminAudit,
  controlPlaneAudit,
  onRefreshAdmin,
  onFetchControlPlane,
}: {
  controlPlanes: ControlPlaneSummary[]
  adminAudit: AdminAuditEntry[]
  controlPlaneAudit: AuditLogResponse | null
  onRefreshAdmin: () => Promise<void>
  onFetchControlPlane: (
    id: string,
    params: { network_id?: string; node_id?: string; limit?: number },
  ) => Promise<void>
}) {
  const [mode, setMode] = useState<'admin' | 'control-plane'>('admin')
  const [selectedPlaneId, setSelectedPlaneId] = useState('')
  const [networkId, setNetworkId] = useState('')
  const [nodeId, setNodeId] = useState('')

  return (
    <div className="grid two">
      <div className="card">
        <h3>Audit mode</h3>
        <div className="pill-row">
          <button
            className={mode === 'admin' ? 'pill active' : 'pill'}
            onClick={() => setMode('admin')}
          >
            Admin audit
          </button>
          <button
            className={mode === 'control-plane' ? 'pill active' : 'pill'}
            onClick={() => setMode('control-plane')}
          >
            Control plane audit
          </button>
        </div>

        {mode === 'admin' ? (
          <div className="stack">
            <p className="muted">Admin audit shows UI actions only.</p>
            <button className="ghost" onClick={onRefreshAdmin}>
              Refresh admin audit
            </button>
          </div>
        ) : (
          <form
            onSubmit={(event) => {
              event.preventDefault()
              if (!selectedPlaneId) return
              onFetchControlPlane(selectedPlaneId, {
                network_id: networkId || undefined,
                node_id: nodeId || undefined,
                limit: 200,
              })
            }}
            className="stack"
          >
            <label>
              <span>Control plane</span>
              <select
                value={selectedPlaneId}
                onChange={(event) => setSelectedPlaneId(event.target.value)}
                required
              >
                <option value="">Select</option>
                {controlPlanes.map((plane) => (
                  <option key={plane.id} value={plane.id}>
                    {plane.name}
                  </option>
                ))}
              </select>
            </label>
            <label>
              <span>Network ID (optional)</span>
              <input
                value={networkId}
                onChange={(event) => setNetworkId(event.target.value)}
              />
            </label>
            <label>
              <span>Node ID (optional)</span>
              <input
                value={nodeId}
                onChange={(event) => setNodeId(event.target.value)}
              />
            </label>
            <button type="submit">Fetch control plane audit</button>
          </form>
        )}
      </div>
      <div className="card">
        <h3>{mode === 'admin' ? 'Admin audit log' : 'Control plane audit log'}</h3>
        <div className="list">
          {mode === 'admin'
            ? adminAudit.map((entry) => (
                <div key={entry.id} className="list-row">
                  <div>
                    <strong>{entry.action}</strong>
                    <p>
                      {entry.actor_email || 'system'} ·{' '}
                      {entry.target_type || 'n/a'} {entry.target_id || ''}
                    </p>
                  </div>
                  <span className="tag">{formatDate(entry.created_at)}</span>
                </div>
              ))
            : controlPlaneAudit?.entries.map((entry) => (
                <div key={entry.id} className="list-row">
                  <div>
                    <strong>{entry.action}</strong>
                    <p>
                      {entry.network_id || 'network'} ·{' '}
                      {entry.node_id || 'node'}
                    </p>
                  </div>
                  <span className="tag">{formatEpoch(entry.timestamp)}</span>
                </div>
              ))}
        </div>
      </div>
    </div>
  )
}

function formatEpoch(seconds: number | null | undefined) {
  if (!seconds) return '-'
  return new Date(seconds * 1000).toLocaleString()
}

function formatDate(iso: string | null | undefined) {
  if (!iso) return '-'
  return new Date(iso).toLocaleString()
}

export default App
