import { useEffect, useState, useCallback } from 'react';
import { api } from '@/lib/api';
import { cn } from '@/lib/cn';

// ── Types ──────────────────────────────────────────────────────────────────────

interface UserDto {
  id: string;
  name: string;
  email: string;
  role: string;
  banned: boolean;
  banReason: string | null;
  createdAt: string;
  updatedAt: string;
}

interface UserListDto {
  users: UserDto[];
  total: number;
}

interface ServiceStatusDto {
  status: 'ok' | 'error';
  latencyMs?: number;
  error?: string;
}

interface ProviderStatusDto {
  id: string;
  name: string;
  available: boolean;
  modelCount: number;
}

interface HealthStatusDto {
  status: 'ok' | 'degraded' | 'error';
  database: ServiceStatusDto;
  cache: ServiceStatusDto;
  agentPool: { activeSessions: number };
  providers: ProviderStatusDto[];
  checkedAt: string;
}

// ── Admin Page ─────────────────────────────────────────────────────────────────

// Route-level access control lives in AdminGuard (spa/guards.tsx); this page
// assumes an authenticated admin session.
export function AdminPage(): React.ReactElement {
  const [activeTab, setActiveTab] = useState<'users' | 'health'>('users');

  return (
    <div className="mx-auto max-w-5xl space-y-6">
      <div className="flex items-center justify-between">
        <h1 className="text-2xl font-semibold text-text-primary">Admin Panel</h1>
      </div>

      <div className="flex gap-1 border-b border-surface-border">
        {(['users', 'health'] as const).map((tab) => (
          <button
            key={tab}
            type="button"
            onClick={() => setActiveTab(tab)}
            className={cn(
              'px-4 py-2 text-sm font-medium capitalize transition-colors',
              activeTab === tab
                ? 'border-b-2 border-blue-500 text-blue-400'
                : 'text-text-secondary hover:text-text-primary',
            )}
          >
            {tab === 'users' ? 'User Management' : 'System Health'}
          </button>
        ))}
      </div>

      {activeTab === 'users' ? <UsersTab /> : <HealthTab />}
    </div>
  );
}

// ── Users Tab ──────────────────────────────────────────────────────────────────

function UsersTab(): React.ReactElement {
  const [users, setUsers] = useState<UserDto[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [showCreate, setShowCreate] = useState(false);

  const loadUsers = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const data = await api<UserListDto>('/api/admin/users');
      setUsers(data.users);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load users');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void loadUsers();
  }, [loadUsers]);

  async function handleRoleToggle(user: UserDto): Promise<void> {
    const newRole = user.role === 'admin' ? 'member' : 'admin';
    try {
      await api(`/api/admin/users/${user.id}/role`, {
        method: 'PATCH',
        body: { role: newRole },
      });
      await loadUsers();
    } catch (err) {
      alert(err instanceof Error ? err.message : 'Failed to update role');
    }
  }

  async function handleBanToggle(user: UserDto): Promise<void> {
    const endpoint = user.banned ? 'unban' : 'ban';
    try {
      await api(`/api/admin/users/${user.id}/${endpoint}`, { method: 'POST' });
      await loadUsers();
    } catch (err) {
      alert(err instanceof Error ? err.message : 'Failed to update ban status');
    }
  }

  async function handleDelete(user: UserDto): Promise<void> {
    if (!confirm(`Delete user ${user.email}? This cannot be undone.`)) return;
    try {
      await api(`/api/admin/users/${user.id}`, { method: 'DELETE' });
      await loadUsers();
    } catch (err) {
      alert(err instanceof Error ? err.message : 'Failed to delete user');
    }
  }

  if (loading) {
    return <p className="text-sm text-text-muted">Loading users...</p>;
  }

  if (error) {
    return (
      <div className="rounded-lg border border-red-500/30 bg-red-500/10 p-4">
        <p className="text-sm text-red-400">{error}</p>
        <button
          type="button"
          onClick={() => void loadUsers()}
          className="mt-2 text-xs text-red-300 underline hover:no-underline"
        >
          Retry
        </button>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <p className="text-sm text-text-muted">{users.length} user(s)</p>
        <button
          type="button"
          onClick={() => setShowCreate(true)}
          className="rounded-md bg-blue-600 px-3 py-1.5 text-sm text-white transition-colors hover:bg-blue-700"
        >
          + New User
        </button>
      </div>

      {showCreate && (
        <CreateUserForm
          onCancel={() => setShowCreate(false)}
          onCreated={() => {
            setShowCreate(false);
            void loadUsers();
          }}
        />
      )}

      {users.length === 0 ? (
        <div className="rounded-lg border border-surface-border bg-surface-card p-6 text-center">
          <p className="text-sm text-text-muted">No users found</p>
        </div>
      ) : (
        <div className="overflow-hidden rounded-lg border border-surface-border">
          <table className="w-full">
            <thead>
              <tr className="border-b border-surface-border bg-surface-elevated text-left text-xs text-text-muted">
                <th className="px-4 py-2 font-medium">Name / Email</th>
                <th className="px-4 py-2 font-medium">Role</th>
                <th className="hidden px-4 py-2 font-medium md:table-cell">Status</th>
                <th className="hidden px-4 py-2 font-medium md:table-cell">Created</th>
                <th className="px-4 py-2 font-medium">Actions</th>
              </tr>
            </thead>
            <tbody>
              {users.map((user) => (
                <tr key={user.id} className="border-b border-surface-border last:border-b-0">
                  <td className="px-4 py-3">
                    <div className="text-sm font-medium text-text-primary">{user.name}</div>
                    <div className="text-xs text-text-muted">{user.email}</div>
                  </td>
                  <td className="px-4 py-3">
                    <span
                      className={cn(
                        'inline-flex rounded-full px-2 py-0.5 text-xs font-medium',
                        user.role === 'admin'
                          ? 'bg-purple-500/20 text-purple-400'
                          : 'bg-surface-elevated text-text-secondary',
                      )}
                    >
                      {user.role}
                    </span>
                  </td>
                  <td className="hidden px-4 py-3 md:table-cell">
                    {user.banned ? (
                      <span className="inline-flex rounded-full bg-red-500/20 px-2 py-0.5 text-xs font-medium text-red-400">
                        Banned
                      </span>
                    ) : (
                      <span className="inline-flex rounded-full bg-green-500/20 px-2 py-0.5 text-xs font-medium text-green-400">
                        Active
                      </span>
                    )}
                  </td>
                  <td className="hidden px-4 py-3 text-xs text-text-muted md:table-cell">
                    {new Date(user.createdAt).toLocaleDateString()}
                  </td>
                  <td className="px-4 py-3">
                    <div className="flex items-center gap-2">
                      <button
                        type="button"
                        onClick={() => void handleRoleToggle(user)}
                        className="text-xs text-blue-400 hover:text-blue-300"
                        title={user.role === 'admin' ? 'Demote to member' : 'Promote to admin'}
                      >
                        {user.role === 'admin' ? 'Demote' : 'Promote'}
                      </button>
                      <button
                        type="button"
                        onClick={() => void handleBanToggle(user)}
                        className={cn(
                          'text-xs',
                          user.banned
                            ? 'text-green-400 hover:text-green-300'
                            : 'text-yellow-400 hover:text-yellow-300',
                        )}
                      >
                        {user.banned ? 'Unban' : 'Ban'}
                      </button>
                      <button
                        type="button"
                        onClick={() => void handleDelete(user)}
                        className="text-xs text-red-400 hover:text-red-300"
                      >
                        Delete
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ── Create User Form ──────────────────────────────────────────────────────────

interface CreateUserFormProps {
  onCancel: () => void;
  onCreated: () => void;
}

function CreateUserForm({ onCancel, onCreated }: CreateUserFormProps): React.ReactElement {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [role, setRole] = useState('member');
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function handleSubmit(e: React.FormEvent): Promise<void> {
    e.preventDefault();
    setSubmitting(true);
    setError(null);
    try {
      await api('/api/admin/users', {
        method: 'POST',
        body: { name, email, password, role },
      });
      onCreated();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to create user');
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="rounded-lg border border-surface-border bg-surface-card p-4">
      <h3 className="mb-3 text-sm font-medium text-text-primary">Create New User</h3>
      <form onSubmit={(e) => void handleSubmit(e)} className="space-y-3">
        {error && <p className="text-xs text-red-400">{error}</p>}
        <div className="grid grid-cols-2 gap-3">
          <div>
            <label className="mb-1 block text-xs text-text-muted">Name</label>
            <input
              type="text"
              required
              value={name}
              onChange={(e) => setName(e.target.value)}
              className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-blue-500"
            />
          </div>
          <div>
            <label className="mb-1 block text-xs text-text-muted">Email</label>
            <input
              type="email"
              required
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-blue-500"
            />
          </div>
          <div>
            <label className="mb-1 block text-xs text-text-muted">Password</label>
            <input
              type="password"
              required
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-blue-500"
            />
          </div>
          <div>
            <label className="mb-1 block text-xs text-text-muted">Role</label>
            <select
              value={role}
              onChange={(e) => setRole(e.target.value)}
              className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-blue-500"
            >
              <option value="member">member</option>
              <option value="admin">admin</option>
            </select>
          </div>
        </div>
        <div className="flex justify-end gap-2">
          <button
            type="button"
            onClick={onCancel}
            className="rounded-md px-3 py-1.5 text-sm text-text-muted hover:text-text-primary"
          >
            Cancel
          </button>
          <button
            type="submit"
            disabled={submitting}
            className="rounded-md bg-blue-600 px-3 py-1.5 text-sm text-white hover:bg-blue-700 disabled:opacity-50"
          >
            {submitting ? 'Creating...' : 'Create'}
          </button>
        </div>
      </form>
    </div>
  );
}

// ── Health Tab ────────────────────────────────────────────────────────────────

function HealthTab(): React.ReactElement {
  const [health, setHealth] = useState<HealthStatusDto | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const loadHealth = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const data = await api<HealthStatusDto>('/api/admin/health');
      setHealth(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to load health');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void loadHealth();
  }, [loadHealth]);

  if (loading) {
    return <p className="text-sm text-text-muted">Loading health status...</p>;
  }

  if (error) {
    return (
      <div className="rounded-lg border border-red-500/30 bg-red-500/10 p-4">
        <p className="text-sm text-red-400">{error}</p>
        <button
          type="button"
          onClick={() => void loadHealth()}
          className="mt-2 text-xs text-red-300 underline hover:no-underline"
        >
          Retry
        </button>
      </div>
    );
  }

  if (!health) return <></>;

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <StatusBadge status={health.status} />
          <span className="text-sm text-text-muted">
            Last checked: {new Date(health.checkedAt).toLocaleTimeString()}
          </span>
        </div>
        <button
          type="button"
          onClick={() => void loadHealth()}
          className="text-xs text-blue-400 hover:text-blue-300"
        >
          Refresh
        </button>
      </div>

      <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
        {/* Database */}
        <HealthCard title="Database (PostgreSQL)" status={health.database.status}>
          {health.database.latencyMs !== undefined && (
            <p className="text-xs text-text-muted">Latency: {health.database.latencyMs}ms</p>
          )}
          {health.database.error && <p className="text-xs text-red-400">{health.database.error}</p>}
        </HealthCard>

        {/* Cache */}
        <HealthCard title="Cache (Valkey)" status={health.cache.status}>
          {health.cache.latencyMs !== undefined && (
            <p className="text-xs text-text-muted">Latency: {health.cache.latencyMs}ms</p>
          )}
          {health.cache.error && <p className="text-xs text-red-400">{health.cache.error}</p>}
        </HealthCard>

        {/* Agent Pool */}
        <HealthCard title="Agent Pool" status="ok">
          <p className="text-xs text-text-muted">
            Active sessions: {health.agentPool.activeSessions}
          </p>
        </HealthCard>

        {/* Providers */}
        <HealthCard
          title="LLM Providers"
          status={health.providers.some((p) => p.available) ? 'ok' : 'error'}
        >
          {health.providers.length === 0 ? (
            <p className="text-xs text-text-muted">No providers configured</p>
          ) : (
            <ul className="space-y-1">
              {health.providers.map((p) => (
                <li key={p.id} className="flex items-center justify-between text-xs">
                  <span className="text-text-secondary">{p.name}</span>
                  <span
                    className={cn(
                      'rounded-full px-1.5 py-0.5',
                      p.available ? 'bg-green-500/20 text-green-400' : 'bg-red-500/20 text-red-400',
                    )}
                  >
                    {p.available ? `${p.modelCount} models` : 'unavailable'}
                  </span>
                </li>
              ))}
            </ul>
          )}
        </HealthCard>
      </div>
    </div>
  );
}

// ── Helper Components ─────────────────────────────────────────────────────────

function StatusBadge({ status }: { status: 'ok' | 'degraded' | 'error' }): React.ReactElement {
  const map = {
    ok: 'bg-green-500/20 text-green-400',
    degraded: 'bg-yellow-500/20 text-yellow-400',
    error: 'bg-red-500/20 text-red-400',
  };
  return (
    <span className={cn('rounded-full px-2 py-0.5 text-xs font-medium capitalize', map[status])}>
      {status}
    </span>
  );
}

interface HealthCardProps {
  title: string;
  status: 'ok' | 'error';
  children?: React.ReactNode;
}

function HealthCard({ title, status, children }: HealthCardProps): React.ReactElement {
  return (
    <div className="rounded-lg border border-surface-border bg-surface-card p-4">
      <div className="mb-2 flex items-center justify-between">
        <h3 className="text-sm font-medium text-text-primary">{title}</h3>
        <span
          className={cn('h-2 w-2 rounded-full', status === 'ok' ? 'bg-green-400' : 'bg-red-400')}
        />
      </div>
      {children}
    </div>
  );
}
