// ── Tunnel Management (admin-only) ──────────────────────────────────────

function TunnelManagementPage() {
  const [tab, setTab] = useState('overview');
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  const [analytics, setAnalytics] = useState({});
  const [analyticsRange, setAnalyticsRange] = useState('24h');
  const [tunnels, setTunnels] = useState({});
  const [connections, setConnections] = useState({ rows: [], total: 0 });
  const [requests, setRequests] = useState({ rows: [], total: 0 });
  const [invites, setInvites] = useState([]);
  const [bans, setBans] = useState([]);
  const [settings, setSettings] = useState({});
  const [settingsSaved, setSettingsSaved] = useState(false);

  const [inviteForm, setInviteForm] = useState({ label: '', max_uses: 0, max_concurrent: 5, max_duration_minutes: 0, expires_at: '' });
  const [newInviteCode, setNewInviteCode] = useState('');
  const [usageInvite, setUsageInvite] = useState(null);
  const [inviteUsage, setInviteUsage] = useState([]);
  const [editingInviteId, setEditingInviteId] = useState(null);
  const [editConcurrentVal, setEditConcurrentVal] = useState(5);
  const concurrentRef = useRef(null);

  const [banForm, setBanForm] = useState({ ip: '', reason: '' });

  const [staticData, setStaticData] = useState({ rows: [], total: 0, active_count: 0, total_storage: 0 });
  const [staticBandwidth, setStaticBandwidth] = useState({ total_30d: 0 });
  const [staticSettings, setStaticSettings] = useState({ max_deployments_per_invite: '10' });
  const [staticSettingsMB, setStaticSettingsMB] = useState({ max_deployment_size_mb: 100, max_total_storage_mb: 500, max_bandwidth_mb: 10240, max_file_size_mb: 50 });
  const [staticSettingsSaved, setStaticSettingsSaved] = useState(false);

  const tm = (p, opts) => api(`/api/tunnel-mgmt${p}`, opts);

  const loadAnalytics = useCallback(async (range) => {
    try {
      const r = range || analyticsRange;
      const data = await tm(`/analytics?range=${r}`);
      setAnalytics(data);
    } catch (e) { setError(e.message); }
  }, [analyticsRange]);

  const loadTunnels = useCallback(async () => {
    try { setTunnels(await tm('/tunnels')); } catch (e) { setError(e.message); }
  }, []);

  const loadConnections = useCallback(async () => {
    try { setConnections(await tm('/connections?limit=100')); } catch (e) { setError(e.message); }
  }, []);

  const loadRequests = useCallback(async () => {
    try { setRequests(await tm('/requests?limit=100')); } catch (e) { setError(e.message); }
  }, []);

  const loadInvites = useCallback(async () => {
    try { setInvites(await tm('/invites')); } catch (e) { setError(e.message); }
  }, []);

  const loadBans = useCallback(async () => {
    try { setBans(await tm('/bans')); } catch (e) { setError(e.message); }
  }, []);

  const loadSettings = useCallback(async () => {
    try { setSettings(await tm('/settings')); } catch (e) { setError(e.message); }
  }, []);

  const loadStaticDeploys = useCallback(async () => {
    try {
      const [d, bw, s] = await Promise.all([
        tm('/static/deployments'), tm('/static/bandwidth'), tm('/static/settings'),
      ]);
      setStaticData(d);
      setStaticBandwidth(bw);
      setStaticSettings({ max_deployments_per_invite: s.max_deployments_per_invite || '10' });
      setStaticSettingsMB({
        max_deployment_size_mb: Math.round((parseInt(s.max_deployment_size_bytes) || 104857600) / 1048576),
        max_total_storage_mb: Math.round((parseInt(s.max_total_storage_bytes) || 524288000) / 1048576),
        max_bandwidth_mb: Math.round((parseInt(s.max_bandwidth_bytes_monthly) || 10737418240) / 1048576),
        max_file_size_mb: Math.round((parseInt(s.max_file_size_bytes) || 52428800) / 1048576),
      });
    } catch (e) { setError(e.message); }
  }, []);

  const loaders = { overview: loadAnalytics, tunnels: loadTunnels, connections: loadConnections, requests: loadRequests, invites: loadInvites, static: loadStaticDeploys, bans: loadBans, settings: loadSettings };

  useEffect(() => {
    setLoading(true);
    loadAnalytics().finally(() => setLoading(false));
  }, []);

  const switchTab = (t) => {
    setTab(t);
    setError('');
    if (loaders[t]) loaders[t]();
  };

  const killTunnel = async (addr) => {
    if (!confirm(`Disconnect ${addr}?`)) return;
    await tm(`/tunnels/${encodeURIComponent(addr)}`, { method: 'DELETE' });
    loadTunnels();
  };

  const createInvite = async () => {
    if (!inviteForm.label) return;
    const body = { ...inviteForm };
    if (!body.expires_at) delete body.expires_at;
    try {
      const r = await tm('/invites', { method: 'POST', body: JSON.stringify(body) });
      if (r.code) {
        setNewInviteCode(r.code);
        setInviteForm({ label: '', max_uses: 0, max_concurrent: 5, max_duration_minutes: 0, expires_at: '' });
        loadInvites();
      }
    } catch (e) { setError(e.message); }
  };

  const toggleInvite = async (id, active) => {
    await tm(`/invites/${id}`, { method: 'PUT', body: JSON.stringify({ active }) });
    loadInvites();
  };

  const saveConcurrent = async (inv) => {
    const val = editConcurrentVal;
    setEditingInviteId(null);
    if (val !== inv.max_concurrent) {
      await tm(`/invites/${inv.id}`, { method: 'PUT', body: JSON.stringify({ max_concurrent: val }) });
      loadInvites();
    }
  };

  const viewUsage = async (inv) => {
    setUsageInvite(inv);
    setInviteUsage(await tm(`/invites/${inv.id}/usage`));
  };

  const addBan = async () => {
    if (!banForm.ip) return;
    await tm('/bans', { method: 'POST', body: JSON.stringify(banForm) });
    setBanForm({ ip: '', reason: '' });
    loadBans();
  };

  const removeBan = async (id) => {
    await tm(`/bans/${id}`, { method: 'DELETE' });
    loadBans();
  };

  const saveSettings = async () => {
    await tm('/settings', { method: 'PUT', body: JSON.stringify(settings) });
    setSettingsSaved(true);
    setTimeout(() => setSettingsSaved(false), 2000);
  };

  const deleteStaticDeploy = async (id) => {
    if (!confirm(`Delete deployment ${id}? This cannot be undone.`)) return;
    await tm(`/static/deployments/${id}`, { method: 'DELETE' });
    loadStaticDeploys();
  };

  const saveStaticSettings = async () => {
    await tm('/static/settings', { method: 'PUT', body: JSON.stringify({
      max_deployments_per_invite: staticSettings.max_deployments_per_invite,
      max_deployment_size_bytes: String(staticSettingsMB.max_deployment_size_mb * 1048576),
      max_total_storage_bytes: String(staticSettingsMB.max_total_storage_mb * 1048576),
      max_bandwidth_bytes_monthly: String(staticSettingsMB.max_bandwidth_mb * 1048576),
      max_file_size_bytes: String(staticSettingsMB.max_file_size_mb * 1048576),
    })});
    setStaticSettingsSaved(true);
    setTimeout(() => setStaticSettingsSaved(false), 2000);
  };

  const tabStyle = (t) => ({
    padding: '8px 16px', cursor: 'pointer', fontWeight: 600, fontSize: 13,
    borderBottom: tab === t ? '2px solid var(--accent)' : '2px solid transparent',
    color: tab === t ? 'var(--accent)' : 'var(--text-dim)',
    background: 'none', border: 'none', borderBottomStyle: 'solid',
  });

  if (loading) return (<><h2>Tunnel Management</h2><div className="wh-empty"><p>Loading...</p></div></>);

  return (
    <>
      <h2>Tunnel Management</h2>
      <div className="page-sub">Monitor tunnels, manage invites, bans, and settings</div>

      {error && <div className="error-banner">{error}</div>}

      <div style={{display:'flex',gap:0,borderBottom:'1px solid var(--border)',marginBottom:16,overflowX:'auto'}}>
        {[['overview','Overview'],['tunnels','Active Tunnels'],['connections','Connections'],['requests','Requests'],
          ['invites','Invites'],['static','Static Deploys'],['bans','Banned IPs'],['settings','Settings']].map(([k,label]) => (
          <button key={k} style={tabStyle(k)} onClick={() => switchTab(k)}>{label}</button>
        ))}
      </div>

      {tab === 'overview' && (
        <TunnelMgmtTabOverview
          analytics={analytics}
          analyticsRange={analyticsRange}
          setAnalyticsRange={setAnalyticsRange}
          loadAnalytics={loadAnalytics}
        />
      )}

      {tab === 'tunnels' && (
        <TunnelMgmtTabTunnels tunnels={tunnels} loadTunnels={loadTunnels} killTunnel={killTunnel} />
      )}

      {tab === 'connections' && (
        <TunnelMgmtTabConnections connections={connections} />
      )}

      {tab === 'requests' && (
        <TunnelMgmtTabRequests requests={requests} />
      )}

      {tab === 'invites' && (
        <TunnelMgmtTabInvites
          inviteForm={inviteForm}
          setInviteForm={setInviteForm}
          newInviteCode={newInviteCode}
          createInvite={createInvite}
          invites={invites}
          editingInviteId={editingInviteId}
          setEditingInviteId={setEditingInviteId}
          editConcurrentVal={editConcurrentVal}
          setEditConcurrentVal={setEditConcurrentVal}
          concurrentRef={concurrentRef}
          saveConcurrent={saveConcurrent}
          toggleInvite={toggleInvite}
          viewUsage={viewUsage}
          usageInvite={usageInvite}
          inviteUsage={inviteUsage}
          setUsageInvite={setUsageInvite}
          setInviteUsage={setInviteUsage}
        />
      )}

      {tab === 'static' && (
        <TunnelMgmtTabStatic
          staticData={staticData}
          staticBandwidth={staticBandwidth}
          loadStaticDeploys={loadStaticDeploys}
          deleteStaticDeploy={deleteStaticDeploy}
          staticSettings={staticSettings}
          setStaticSettings={setStaticSettings}
          staticSettingsMB={staticSettingsMB}
          setStaticSettingsMB={setStaticSettingsMB}
          saveStaticSettings={saveStaticSettings}
          staticSettingsSaved={staticSettingsSaved}
        />
      )}

      {tab === 'bans' && (
        <TunnelMgmtTabBans
          banForm={banForm}
          setBanForm={setBanForm}
          addBan={addBan}
          bans={bans}
          removeBan={removeBan}
        />
      )}

      {tab === 'settings' && (
        <TunnelMgmtTabSettings
          settings={settings}
          setSettings={setSettings}
          saveSettings={saveSettings}
          settingsSaved={settingsSaved}
        />
      )}
    </>
  );
}
