'use client';

import { useCallback, useEffect, useRef, useState } from 'react';
import { formatBytes, formatDate } from '@/lib/format';
import type { TunnelItem } from '@/lib/admin/list';

const PER_PAGE = 25;

export function TunnelsTable({
  initialTunnels,
  initialTotal,
}: {
  initialTunnels: TunnelItem[];
  initialTotal: number;
}) {
  const [tunnels, setTunnels] = useState<TunnelItem[]>(initialTunnels);
  const [total, setTotal] = useState(initialTotal);
  const [page, setPage] = useState(1);
  const [search, setSearch] = useState('');
  const [status, setStatus] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [notice, setNotice] = useState<string | null>(null);
  const [busyId, setBusyId] = useState<string | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const params = new URLSearchParams({
        page: String(page),
        perPage: String(PER_PAGE),
      });
      if (search.trim()) params.set('search', search.trim());
      if (status) params.set('status', status);
      const res = await fetch(`/api/admin/tunnels?${params.toString()}`, {
        credentials: 'same-origin',
      });
      if (!res.ok) {
        const b = (await res.json().catch(() => ({}))) as { error?: string };
        throw new Error(b.error ?? `Request failed (${res.status})`);
      }
      const data = (await res.json()) as { tunnels: TunnelItem[]; total: number };
      setTunnels(data.tunnels);
      setTotal(data.total);
    } catch (e) {
      setError((e as Error).message);
    } finally {
      setLoading(false);
    }
  }, [page, search, status]);

  // First page is server-rendered; skip the on-mount fetch to avoid racing the
  // SSR session-cookie refresh (which intermittently 401'd).
  const didMount = useRef(false);
  useEffect(() => {
    if (!didMount.current) {
      didMount.current = true;
      return;
    }
    const t = setTimeout(load, 250);
    return () => clearTimeout(t);
  }, [load]);

  async function act(
    id: string,
    label: string,
    url: string,
    init: RequestInit,
    confirmMsg?: string,
  ): Promise<unknown | null> {
    if (confirmMsg && !window.confirm(confirmMsg)) return null;
    setBusyId(id);
    setError(null);
    setNotice(null);
    try {
      const res = await fetch(url, { credentials: 'same-origin', ...init });
      const body = (await res.json().catch(() => ({}))) as {
        error?: string;
        [k: string]: unknown;
      };
      if (!res.ok) throw new Error(body.error ?? `Request failed (${res.status})`);
      setNotice(`${label} succeeded`);
      await load();
      return body;
    } catch (e) {
      setError((e as Error).message);
      return null;
    } finally {
      setBusyId(null);
    }
  }

  const jsonInit = (body: unknown): RequestInit => ({
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });

  async function onToggleActive(t: TunnelItem) {
    await act(
      t.user_id,
      t.is_active ? 'Deactivate' : 'Activate',
      `/api/admin/tunnels/${t.user_id}/active`,
      jsonInit({ is_active: !t.is_active }),
    );
  }

  async function onRegenerate(t: TunnelItem) {
    const body = (await act(
      t.user_id,
      'Regenerate token',
      `/api/admin/tunnels/${t.user_id}/regenerate-token`,
      { method: 'POST' },
      `Regenerate the token for ${t.subdomain}? The old token stops working.`,
    )) as { token?: string } | null;
    if (body?.token) {
      window.prompt('New token (copy it now):', body.token);
    }
  }

  async function onResetUsage(t: TunnelItem) {
    await act(
      t.user_id,
      'Reset usage',
      `/api/admin/tunnels/${t.user_id}/reset-usage`,
      { method: 'POST' },
      `Reset bandwidth usage for ${t.subdomain} to zero?`,
    );
  }

  async function onSetQuota(t: TunnelItem) {
    const input = window.prompt(
      `New quota in GiB for ${t.subdomain}:`,
      String(Math.round(t.quota_bytes / 1024 ** 3)),
    );
    if (input === null) return;
    const gib = Number(input);
    if (!Number.isFinite(gib) || gib <= 0) {
      setError('Quota must be a positive number of GiB');
      return;
    }
    await act(
      t.user_id,
      'Set quota',
      `/api/admin/tunnels/${t.user_id}/quota`,
      jsonInit({ quota_bytes: Math.round(gib * 1024 ** 3) }),
    );
  }

  async function onReassign(t: TunnelItem) {
    const input = window.prompt(
      `New subdomain for ${t.owner_email ?? t.subdomain}:`,
      t.subdomain,
    );
    if (input === null) return;
    await act(
      t.user_id,
      'Reassign',
      `/api/admin/tunnels/${t.user_id}/reassign`,
      jsonInit({ subdomain: input.trim().toLowerCase() }),
    );
  }

  async function onDelete(t: TunnelItem) {
    await act(
      t.user_id,
      'Delete tunnel',
      `/api/admin/tunnels/${t.user_id}`,
      { method: 'DELETE' },
      `Delete the tunnel ${t.subdomain}? This frees the subdomain.`,
    );
  }

  const totalPages = Math.max(1, Math.ceil(total / PER_PAGE));

  return (
    <div>
      <h1>Tunnels</h1>

      <div className="row" style={{ marginBottom: '1rem', flexWrap: 'wrap' }}>
        <input
          type="text"
          placeholder="Search subdomain…"
          value={search}
          onChange={(e) => {
            setPage(1);
            setSearch(e.target.value);
          }}
          style={{ maxWidth: 260 }}
        />
        <select
          value={status}
          onChange={(e) => {
            setPage(1);
            setStatus(e.target.value);
          }}
          style={{
            padding: '0.6rem 0.75rem',
            background: 'var(--bg)',
            color: 'var(--fg)',
            border: '1px solid var(--border)',
            borderRadius: 6,
          }}
        >
          <option value="">All statuses</option>
          <option value="active">Active</option>
          <option value="inactive">Inactive</option>
          <option value="over_quota">Over quota</option>
        </select>
        <button className="secondary btn-sm" type="button" onClick={load}>
          Refresh
        </button>
      </div>

      {error && <p className="error">{error}</p>}
      {notice && <p className="success">{notice}</p>}

      {loading ? (
        <p className="muted">Loading…</p>
      ) : tunnels.length === 0 ? (
        <p className="muted">No tunnels found.</p>
      ) : (
        <div className="admin-table-wrap">
          <table className="admin-table">
            <thead>
              <tr>
                <th>Subdomain</th>
                <th>Owner</th>
                <th>Status</th>
                <th>Usage</th>
                <th>Last seen</th>
                <th>Actions</th>
              </tr>
            </thead>
            <tbody>
              {tunnels.map((t) => (
                <tr key={t.user_id}>
                  <td>{t.subdomain}</td>
                  <td style={{ wordBreak: 'break-all' }}>
                    {t.owner_email ?? '—'}
                  </td>
                  <td>
                    {t.is_active ? (
                      <span className="badge badge-ok">active</span>
                    ) : (
                      <span className="badge">inactive</span>
                    )}
                  </td>
                  <td style={{ minWidth: 140 }}>
                    <div>
                      {formatBytes(t.bytes_used)} / {formatBytes(t.quota_bytes)}
                    </div>
                    <div className="progress" style={{ marginTop: 4 }}>
                      <div
                        style={{
                          width: `${Math.min(100, t.usage_pct).toFixed(1)}%`,
                          background:
                            t.usage_pct >= 100
                              ? 'var(--danger)'
                              : 'var(--accent)',
                        }}
                      />
                    </div>
                  </td>
                  <td>{formatDate(t.last_seen_at)}</td>
                  <td>
                    <div className="row" style={{ flexWrap: 'wrap', gap: 4 }}>
                      <button
                        type="button"
                        className="secondary btn-sm"
                        disabled={busyId === t.user_id}
                        onClick={() => onToggleActive(t)}
                      >
                        {t.is_active ? 'Deactivate' : 'Activate'}
                      </button>
                      <button
                        type="button"
                        className="secondary btn-sm"
                        disabled={busyId === t.user_id}
                        onClick={() => onSetQuota(t)}
                      >
                        Quota
                      </button>
                      <button
                        type="button"
                        className="secondary btn-sm"
                        disabled={busyId === t.user_id}
                        onClick={() => onResetUsage(t)}
                      >
                        Reset
                      </button>
                      <button
                        type="button"
                        className="secondary btn-sm"
                        disabled={busyId === t.user_id}
                        onClick={() => onReassign(t)}
                      >
                        Reassign
                      </button>
                      <button
                        type="button"
                        className="secondary btn-sm"
                        disabled={busyId === t.user_id}
                        onClick={() => onRegenerate(t)}
                      >
                        Token
                      </button>
                      <button
                        type="button"
                        className="btn-danger btn-sm"
                        disabled={busyId === t.user_id}
                        onClick={() => onDelete(t)}
                      >
                        Delete
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      <div className="row" style={{ marginTop: '1rem' }}>
        <button
          className="secondary btn-sm"
          type="button"
          disabled={page <= 1}
          onClick={() => setPage((p) => Math.max(1, p - 1))}
        >
          Prev
        </button>
        <span className="muted">
          Page {page} of {totalPages} ({total} total)
        </span>
        <button
          className="secondary btn-sm"
          type="button"
          disabled={page >= totalPages}
          onClick={() => setPage((p) => p + 1)}
        >
          Next
        </button>
      </div>
    </div>
  );
}
