/**
 * Network status page with comprehensive node health and peer dashboard.
 * Provides real-time monitoring of network metrics, peer connections, and system health.
 */

import { useState, useEffect, useMemo } from 'react';
import {
  Activity,
  Server,
  Users,
  Cpu,
  Zap,
  Database,
  Clock,
  TrendingUp,
  TrendingDown,
  CheckCircle2,
  XCircle,
  AlertCircle,
  RefreshCw,
  Wifi,
  WifiOff,
  Box,
  Gauge,
} from 'lucide-react';
import { useStats } from '../hooks/useApi';
import {
  useWebSocket,
  useRealtimeStats,
  useRealtimeBlocks,
} from '../contexts/WebSocketContext';
import { api } from '../lib/api';
import type { HealthStatus } from '../lib/types';
import { cn } from '../lib/utils';

interface HistoricalPoint {
  timestamp: number;
  hashrate: number;
  blockRate: number;
  mempoolSize: number;
  peerCount: number;
}

export default function Network() {
  const { data: stats, isLoading, error, refetch } = useStats(10000);
  const { stats: realtimeStats, isConnected: wsConnected } = useRealtimeStats();
  const { blockHistory } = useRealtimeBlocks(20);
  const { status: wsStatus } = useWebSocket();

  const [health, setHealth] = useState<HealthStatus | null>(null);
  const [healthLoading, setHealthLoading] = useState(true);
  const [historical, setHistorical] = useState<HistoricalPoint[]>([]);

  // Fetch health status
  useEffect(() => {
    const fetchHealth = async () => {
      try {
        const healthData = await api.getHealth();
        setHealth(healthData);
      } catch (e) {
        setHealth({ healthy: false, rpcConnected: false });
      } finally {
        setHealthLoading(false);
      }
    };
    fetchHealth();
    const interval = setInterval(fetchHealth, 30000);
    return () => clearInterval(interval);
  }, []);

  // Track historical data points
  useEffect(() => {
    if (!stats && !realtimeStats) return;

    const current = realtimeStats || stats;
    if (!current) return;

    const point: HistoricalPoint = {
      timestamp: Date.now(),
      hashrate: current.hashrate,
      blockRate: 'blockRate' in current ? current.blockRate : (stats?.blockRate || 0),
      mempoolSize: current.mempoolSize,
      peerCount: 'peerCount' in current ? current.peerCount : (stats?.peerCount || 0),
    };

    setHistorical((prev) => [...prev.slice(-59), point]);
  }, [stats, realtimeStats]);

  // Calculate block rate from recent blocks
  const calculatedBlockRate = useMemo(() => {
    if (blockHistory.length < 2) return null;

    const oldest = blockHistory[blockHistory.length - 1];
    const newest = blockHistory[0];
    const timeSpan = (newest.timestamp - oldest.timestamp) / 1000;

    if (timeSpan <= 0) return null;
    return blockHistory.length / timeSpan;
  }, [blockHistory]);

  // Merge stats with realtime updates
  const currentStats = useMemo(() => {
    if (!stats) return null;

    if (realtimeStats) {
      return {
        ...stats,
        blockCount: realtimeStats.blockCount,
        virtualDaaScore: realtimeStats.virtualDaaScore,
        difficulty: realtimeStats.difficulty,
        mempoolSize: realtimeStats.mempoolSize,
        hashrate: realtimeStats.hashrate,
        hashrateHuman: realtimeStats.hashrateHuman,
      };
    }

    return stats;
  }, [stats, realtimeStats]);

  if (isLoading && !currentStats) {
    return <NetworkSkeleton />;
  }

  if (error && !currentStats) {
    return (
      <div className="card p-6 text-red-400">
        Error loading network status: {error.message}
      </div>
    );
  }

  if (!currentStats) {
    return <div className="card p-6 text-gray-400">No network data available</div>;
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="relative">
        <div className="absolute -top-10 left-0 w-[300px] h-[150px] bg-synor-500/10 rounded-full blur-[80px] pointer-events-none" />

        <div className="relative flex flex-col md:flex-row md:items-center justify-between gap-4">
          <div className="flex items-center gap-4">
            <div className="p-3 rounded-xl bg-gradient-to-br from-synor-500/20 to-violet-500/20 border border-synor-500/30">
              <Server size={28} className="text-synor-400" />
            </div>
            <div>
              <h1 className="text-2xl md:text-3xl font-bold bg-gradient-to-r from-white to-gray-300 bg-clip-text text-transparent">
                Network Status
              </h1>
              <p className="text-sm text-gray-400 mt-1">
                Real-time node health and peer monitoring
              </p>
            </div>
          </div>

          <button
            onClick={() => refetch()}
            className="flex items-center gap-2 px-4 py-2 rounded-lg bg-gray-800/50 hover:bg-gray-700/50 transition-colors text-sm"
            aria-label="Refresh network status"
          >
            <RefreshCw size={16} className={isLoading ? 'animate-spin' : ''} />
            Refresh
          </button>
        </div>
      </div>

      {/* Health Status Cards */}
      <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
        <HealthCard
          icon={wsConnected ? <Wifi size={20} /> : <WifiOff size={20} />}
          label="WebSocket"
          status={wsConnected ? 'healthy' : 'unhealthy'}
          value={wsStatus}
          gradient="from-blue-500/30 to-cyan-500/20"
        />
        <HealthCard
          icon={<Server size={20} />}
          label="RPC Node"
          status={health?.rpcConnected ? 'healthy' : 'unhealthy'}
          value={health?.rpcConnected ? 'Connected' : 'Disconnected'}
          loading={healthLoading}
          gradient="from-emerald-500/30 to-green-500/20"
        />
        <HealthCard
          icon={<Activity size={20} />}
          label="Sync Status"
          status={currentStats.isSynced ? 'healthy' : 'warning'}
          value={currentStats.isSynced ? 'Synced' : 'Syncing'}
          subValue={`${currentStats.networkId} network`}
          gradient="from-synor-500/30 to-violet-500/20"
        />
        <HealthCard
          icon={<Database size={20} />}
          label="System Health"
          status={health?.healthy ? 'healthy' : 'unhealthy'}
          value={health?.healthy ? 'Healthy' : 'Degraded'}
          loading={healthLoading}
          gradient="from-amber-500/30 to-orange-500/20"
        />
      </div>

      {/* Main Metrics Grid */}
      <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
        {/* Peer Connections */}
        <MetricCard
          icon={<Users size={20} />}
          label="Connected Peers"
          value={currentStats.peerCount}
          suffix=" nodes"
          trend={getPeerTrend(historical)}
          color="blue"
        >
          <PeerVisualization count={currentStats.peerCount} max={100} />
        </MetricCard>

        {/* Network Hashrate */}
        <MetricCard
          icon={<Cpu size={20} />}
          label="Network Hashrate"
          value={currentStats.hashrateHuman}
          trend={getHashrateTrend(historical)}
          color="purple"
        >
          <MiniChart
            data={historical.map((h) => h.hashrate)}
            color="rgba(139, 92, 246, 0.5)"
          />
        </MetricCard>

        {/* Block Rate */}
        <MetricCard
          icon={<Zap size={20} />}
          label="Block Rate"
          value={calculatedBlockRate?.toFixed(2) || currentStats.blockRate.toFixed(2)}
          suffix=" bps"
          subValue="blocks per second"
          color="amber"
        >
          <MiniChart
            data={historical.map((h) => h.blockRate)}
            color="rgba(245, 158, 11, 0.5)"
          />
        </MetricCard>

        {/* Mempool Size */}
        <MetricCard
          icon={<Clock size={20} />}
          label="Mempool Size"
          value={currentStats.mempoolSize}
          suffix=" txs"
          subValue="pending transactions"
          color="cyan"
        >
          <MiniChart
            data={historical.map((h) => h.mempoolSize)}
            color="rgba(6, 182, 212, 0.5)"
          />
        </MetricCard>

        {/* Block Height */}
        <MetricCard
          icon={<Box size={20} />}
          label="Block Height"
          value={currentStats.blockCount.toLocaleString()}
          subValue={`${currentStats.headerCount.toLocaleString()} headers`}
          color="green"
        />

        {/* Difficulty */}
        <MetricCard
          icon={<Gauge size={20} />}
          label="Network Difficulty"
          value={formatDifficulty(currentStats.difficulty)}
          subValue={`DAA Score: ${currentStats.virtualDaaScore.toLocaleString()}`}
          color="rose"
        />
      </div>

      {/* Supply Information */}
      <div className="card overflow-hidden">
        <div className="p-6">
          <h2 className="text-lg font-semibold mb-4 flex items-center gap-2">
            <Database size={20} className="text-synor-400" />
            Supply Information
          </h2>

          <div className="space-y-4">
            <div>
              <div className="flex justify-between text-sm mb-2">
                <span className="text-gray-400">Circulating Supply</span>
                <span className="font-mono text-white">
                  {currentStats.circulatingSupplyHuman}
                </span>
              </div>
              <div className="h-3 bg-gray-800 rounded-full overflow-hidden">
                <div
                  className="h-full bg-gradient-to-r from-synor-500 to-violet-500 transition-all duration-500"
                  style={{
                    width: `${(currentStats.circulatingSupply / currentStats.maxSupply) * 100}%`,
                  }}
                />
              </div>
              <div className="flex justify-between text-xs text-gray-500 mt-1">
                <span>
                  {((currentStats.circulatingSupply / currentStats.maxSupply) * 100).toFixed(2)}% mined
                </span>
                <span>Max: {formatMaxSupply(currentStats.maxSupply)}</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* DAG Tips */}
      <div className="card">
        <div className="card-header">
          <div className="flex items-center gap-2">
            <Activity size={18} className="text-synor-400" />
            <h2 className="font-semibold">Active DAG Tips</h2>
          </div>
          <span className="text-sm text-gray-400">{currentStats.tipCount} tips</span>
        </div>
        <div className="p-4">
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            {Array.from({ length: Math.min(currentStats.tipCount, 3) }).map((_, i) => (
              <div
                key={i}
                className="flex items-center gap-3 p-3 rounded-lg bg-gray-800/50"
              >
                <div className="w-2 h-2 rounded-full bg-green-400 animate-pulse" />
                <div className="min-w-0">
                  <p className="text-sm text-gray-400">Tip {i + 1}</p>
                  <p className="text-xs text-gray-500 truncate">
                    Block at height {currentStats.blockCount - i}
                  </p>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// Health status card component
function HealthCard({
  icon,
  label,
  status,
  value,
  subValue,
  loading,
  gradient,
}: {
  icon: React.ReactNode;
  label: string;
  status: 'healthy' | 'warning' | 'unhealthy';
  value: string;
  subValue?: string;
  loading?: boolean;
  gradient?: string;
}) {
  const statusConfig = {
    healthy: {
      color: 'text-green-400',
      bg: 'bg-green-500/20',
      icon: <CheckCircle2 size={16} />,
    },
    warning: {
      color: 'text-amber-400',
      bg: 'bg-amber-500/20',
      icon: <AlertCircle size={16} />,
    },
    unhealthy: {
      color: 'text-red-400',
      bg: 'bg-red-500/20',
      icon: <XCircle size={16} />,
    },
  };

  const config = statusConfig[status];

  return (
    <div className="relative overflow-hidden rounded-xl">
      <div
        className={cn(
          'absolute inset-0 rounded-xl bg-gradient-to-br',
          gradient || 'from-gray-500/20 to-gray-600/10'
        )}
        style={{ padding: '1px' }}
      >
        <div className="absolute inset-[1px] rounded-xl bg-gray-900/95" />
      </div>

      <div className="relative p-4 z-10">
        <div className="flex items-center justify-between mb-3">
          <div className="p-2 rounded-lg bg-white/5">{icon}</div>
          {loading ? (
            <div className="w-5 h-5 rounded-full border-2 border-gray-600 border-t-gray-400 animate-spin" />
          ) : (
            <div className={cn('p-1 rounded-full', config.bg, config.color)}>
              {config.icon}
            </div>
          )}
        </div>
        <p className="text-xs text-gray-400 uppercase tracking-wider mb-1">
          {label}
        </p>
        <p className={cn('text-lg font-semibold', config.color)}>
          {loading ? '...' : value}
        </p>
        {subValue && (
          <p className="text-xs text-gray-500 mt-1">{subValue}</p>
        )}
      </div>
    </div>
  );
}

// Metric card with optional visualization
function MetricCard({
  icon,
  label,
  value,
  suffix = '',
  subValue,
  trend,
  color,
  children,
}: {
  icon: React.ReactNode;
  label: string;
  value: string | number;
  suffix?: string;
  subValue?: string;
  trend?: 'up' | 'down' | 'stable';
  color: 'blue' | 'purple' | 'amber' | 'cyan' | 'green' | 'rose';
  children?: React.ReactNode;
}) {
  const colorClasses = {
    blue: 'text-blue-400',
    purple: 'text-violet-400',
    amber: 'text-amber-400',
    cyan: 'text-cyan-400',
    green: 'text-green-400',
    rose: 'text-rose-400',
  };

  return (
    <div className="card p-4">
      <div className="flex items-start justify-between mb-3">
        <div className="flex items-center gap-2">
          <div className={cn('p-2 rounded-lg bg-white/5', colorClasses[color])}>
            {icon}
          </div>
          <div>
            <p className="text-xs text-gray-400 uppercase tracking-wider">
              {label}
            </p>
          </div>
        </div>
        {trend && (
          <div
            className={cn(
              'flex items-center gap-1 text-xs px-2 py-1 rounded-full',
              trend === 'up' && 'bg-green-500/20 text-green-400',
              trend === 'down' && 'bg-red-500/20 text-red-400',
              trend === 'stable' && 'bg-gray-500/20 text-gray-400'
            )}
          >
            {trend === 'up' && <TrendingUp size={12} />}
            {trend === 'down' && <TrendingDown size={12} />}
            {trend === 'stable' && '—'}
          </div>
        )}
      </div>

      <p className={cn('text-2xl font-bold font-mono', colorClasses[color])}>
        {value}
        <span className="text-base text-gray-400">{suffix}</span>
      </p>

      {subValue && (
        <p className="text-xs text-gray-500 mt-1">{subValue}</p>
      )}

      {children && <div className="mt-3">{children}</div>}
    </div>
  );
}

// Visual peer count indicator
function PeerVisualization({ count, max }: { count: number; max: number }) {
  const percentage = Math.min((count / max) * 100, 100);
  const status = count < 5 ? 'low' : count < 15 ? 'medium' : 'good';

  return (
    <div>
      <div className="h-2 bg-gray-800 rounded-full overflow-hidden">
        <div
          className={cn(
            'h-full transition-all duration-500 rounded-full',
            status === 'good' && 'bg-gradient-to-r from-green-500 to-emerald-400',
            status === 'medium' && 'bg-gradient-to-r from-amber-500 to-yellow-400',
            status === 'low' && 'bg-gradient-to-r from-red-500 to-rose-400'
          )}
          style={{ width: `${percentage}%` }}
        />
      </div>
      <div className="flex justify-between text-xs text-gray-500 mt-1">
        <span>{status === 'good' ? 'Healthy' : status === 'medium' ? 'Fair' : 'Low'}</span>
        <span>{count}/{max} max</span>
      </div>
    </div>
  );
}

// Simple mini chart component
function MiniChart({ data, color }: { data: number[]; color: string }) {
  if (data.length < 2) {
    return (
      <div className="h-8 flex items-end gap-px">
        {Array.from({ length: 30 }).map((_, i) => (
          <div
            key={i}
            className="flex-1 bg-gray-800 rounded-t"
            style={{ height: '30%' }}
          />
        ))}
      </div>
    );
  }

  const min = Math.min(...data);
  const max = Math.max(...data);
  const range = max - min || 1;

  return (
    <div className="h-8 flex items-end gap-px">
      {data.slice(-30).map((value, i) => {
        const height = ((value - min) / range) * 100;
        return (
          <div
            key={i}
            className="flex-1 rounded-t transition-all duration-300"
            style={{
              height: `${Math.max(height, 10)}%`,
              backgroundColor: color,
            }}
          />
        );
      })}
    </div>
  );
}

// Utility functions
function formatDifficulty(difficulty: number): string {
  if (difficulty >= 1e12) return `${(difficulty / 1e12).toFixed(2)}T`;
  if (difficulty >= 1e9) return `${(difficulty / 1e9).toFixed(2)}B`;
  if (difficulty >= 1e6) return `${(difficulty / 1e6).toFixed(2)}M`;
  if (difficulty >= 1e3) return `${(difficulty / 1e3).toFixed(2)}K`;
  return difficulty.toFixed(2);
}

function formatMaxSupply(supply: number): string {
  const synor = supply / 100_000_000;
  if (synor >= 1e9) return `${(synor / 1e9).toFixed(0)}B SYNOR`;
  if (synor >= 1e6) return `${(synor / 1e6).toFixed(0)}M SYNOR`;
  return `${synor.toLocaleString()} SYNOR`;
}

function getPeerTrend(history: HistoricalPoint[]): 'up' | 'down' | 'stable' | undefined {
  if (history.length < 5) return undefined;
  const recent = history.slice(-5);
  const first = recent[0].peerCount;
  const last = recent[recent.length - 1].peerCount;
  if (last > first + 2) return 'up';
  if (last < first - 2) return 'down';
  return 'stable';
}

function getHashrateTrend(history: HistoricalPoint[]): 'up' | 'down' | 'stable' | undefined {
  if (history.length < 5) return undefined;
  const recent = history.slice(-5);
  const first = recent[0].hashrate;
  const last = recent[recent.length - 1].hashrate;
  const changePercent = ((last - first) / first) * 100;
  if (changePercent > 2) return 'up';
  if (changePercent < -2) return 'down';
  return 'stable';
}

// Loading skeleton
function NetworkSkeleton() {
  return (
    <div className="space-y-6 animate-pulse">
      <div className="flex items-center gap-4">
        <div className="w-14 h-14 rounded-xl bg-gray-800" />
        <div>
          <div className="h-8 w-48 bg-gray-800 rounded mb-2" />
          <div className="h-4 w-64 bg-gray-800 rounded" />
        </div>
      </div>

      <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
        {Array.from({ length: 4 }).map((_, i) => (
          <div key={i} className="card p-4">
            <div className="flex justify-between mb-3">
              <div className="w-10 h-10 rounded-lg bg-gray-800" />
              <div className="w-6 h-6 rounded-full bg-gray-800" />
            </div>
            <div className="h-3 w-16 bg-gray-800 rounded mb-2" />
            <div className="h-6 w-24 bg-gray-800 rounded" />
          </div>
        ))}
      </div>

      <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
        {Array.from({ length: 6 }).map((_, i) => (
          <div key={i} className="card p-4">
            <div className="h-4 w-24 bg-gray-800 rounded mb-3" />
            <div className="h-8 w-32 bg-gray-800 rounded mb-3" />
            <div className="h-8 bg-gray-800 rounded" />
          </div>
        ))}
      </div>
    </div>
  );
}
