import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import DataTable, { Column } from './ui/DataTable';

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

interface HeaderCluster {
  hash: string;
  unique_ips: number;
  avg_browser_score: number;
  ua_ch_mismatch_count: number;
  ua_ch_mismatch_pct: number;
  top_sec_fetch_modes: string[];
  has_cookie_pct: number;
  has_referer_pct: number;
  classification: string;
}

interface ClusterIP {
  ip: string;
  browser_score: number;
  ua_ch_mismatch: boolean;
  sec_fetch_mode: string;
  sec_fetch_dest: string;
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

function formatNumber(n: number): string {
  return n.toLocaleString('fr-FR');
}

function mismatchColor(pct: number): string {
  if (pct > 50) return 'text-threat-critical';
  if (pct > 10) return 'text-threat-medium';
  return 'text-threat-low';
}

function browserScoreColor(score: number): string {
  if (score >= 70) return 'bg-threat-low';
  if (score >= 40) return 'bg-threat-medium';
  return 'bg-threat-critical';
}

function classificationBadge(cls: string): { bg: string; text: string; label: string } {
  switch (cls) {
    case 'bot':
      return { bg: 'bg-threat-critical/20', text: 'text-threat-critical', label: '🤖 Bot' };
    case 'suspicious':
      return { bg: 'bg-threat-high/20', text: 'text-threat-high', label: '⚠️ Suspect' };
    case 'legitimate':
      return { bg: 'bg-threat-low/20', text: 'text-threat-low', label: '✅ Légitime' };
    default:
      return { bg: 'bg-background-card', text: 'text-text-secondary', label: cls };
  }
}

// ─── Sub-components ───────────────────────────────────────────────────────────

function StatCard({ label, value, accent }: { label: string; value: string | number; accent?: string }) {
  return (
    <div className="bg-background-secondary rounded-lg p-4 flex flex-col gap-1 border border-border">
      <span className="text-text-secondary text-sm">{label}</span>
      <span className={`text-2xl font-bold ${accent ?? 'text-text-primary'}`}>{value}</span>
    </div>
  );
}

function ErrorMessage({ message }: { message: string }) {
  return (
    <div className="bg-threat-critical/10 border border-threat-critical/30 rounded-lg p-4 text-threat-critical">
      ⚠️ {message}
    </div>
  );
}

// ─── Main Component ───────────────────────────────────────────────────────────

export function HeaderFingerprintView() {
  const navigate = useNavigate();

  const [clusters, setClusters] = useState<HeaderCluster[]>([]);
  const [totalClusters, setTotalClusters] = useState(0);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [expandedHash, setExpandedHash] = useState<string | null>(null);
  const [clusterIPsMap, setClusterIPsMap] = useState<Record<string, ClusterIP[]>>({});
  const [loadingHashes, setLoadingHashes] = useState<Set<string>>(new Set());
  const [ipErrors, setIpErrors] = useState<Record<string, string>>({});

  useEffect(() => {
    const fetchClusters = async () => {
      setLoading(true);
      try {
        const res = await fetch('/api/headers/clusters?limit=50');
        if (!res.ok) throw new Error('Erreur chargement des clusters');
        const data: { clusters: HeaderCluster[]; total_clusters: number } = await res.json();
        setClusters(data.clusters ?? []);
        setTotalClusters(data.total_clusters ?? 0);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Erreur inconnue');
      } finally {
        setLoading(false);
      }
    };
    fetchClusters();
  }, []);

  const handleToggleCluster = async (hash: string) => {
    if (expandedHash === hash) {
      setExpandedHash(null);
      return;
    }
    setExpandedHash(hash);
    if (clusterIPsMap[hash] !== undefined) return;
    setLoadingHashes((prev) => new Set(prev).add(hash));
    try {
      const res = await fetch(`/api/headers/cluster/${hash}/ips?limit=50`);
      if (!res.ok) throw new Error('Erreur chargement IPs');
      const data: { items: ClusterIP[] } = await res.json();
      setClusterIPsMap((prev) => ({ ...prev, [hash]: data.items ?? [] }));
    } catch (err) {
      setIpErrors((prev) => ({ ...prev, [hash]: err instanceof Error ? err.message : 'Erreur inconnue' }));
    } finally {
      setLoadingHashes((prev) => {
        const next = new Set(prev);
        next.delete(hash);
        return next;
      });
    }
  };

  const suspiciousClusters = clusters.filter((c) => c.ua_ch_mismatch_pct > 50).length;
  const legitimateClusters = clusters.filter((c) => c.classification === 'legitimate').length;

  const clusterColumns: Column<HeaderCluster>[] = [
    {
      key: 'hash',
      label: 'Hash cluster',
      sortable: true,
      render: (_, row) => (
        <span>
          <span className="text-accent-primary text-xs mr-2">{expandedHash === row.hash ? '▾' : '▸'}</span>
          <span className="font-mono text-xs text-text-primary">{row.hash.slice(0, 16)}…</span>
        </span>
      ),
    },
    {
      key: 'unique_ips',
      label: 'IPs',
      sortable: true,
      align: 'right',
      render: (v) => <span className="text-text-primary">{formatNumber(v)}</span>,
    },
    {
      key: 'avg_browser_score',
      label: 'Browser Score',
      sortable: true,
      render: (v) => (
        <div className="flex items-center gap-2">
          <div className="w-20 bg-background-card rounded-full h-2">
            <div className={`h-2 rounded-full ${browserScoreColor(v)}`} style={{ width: `${v}%` }} />
          </div>
          <span className="text-xs text-text-secondary">{Math.round(v)}</span>
        </div>
      ),
    },
    {
      key: 'ua_ch_mismatch_pct',
      label: 'UA/CH Mismatch %',
      sortable: true,
      align: 'right',
      render: (v) => (
        <span className={`font-semibold text-sm ${mismatchColor(v)}`}>{Math.round(v)}%</span>
      ),
    },
    {
      key: 'classification',
      label: 'Classification',
      sortable: true,
      render: (v) => {
        const badge = classificationBadge(v);
        return (
          <span className={`text-xs px-2 py-1 rounded-full ${badge.bg} ${badge.text}`}>{badge.label}</span>
        );
      },
    },
    {
      key: 'top_sec_fetch_modes',
      label: 'Sec-Fetch modes',
      sortable: false,
      render: (v) => (
        <div className="flex flex-wrap gap-1">
          {(v ?? []).slice(0, 3).map((mode: string) => (
            <span key={mode} className="text-xs bg-background-card border border-border px-1.5 py-0.5 rounded text-text-secondary">
              {mode}
            </span>
          ))}
        </div>
      ),
    },
  ];

  const ipColumns: Column<ClusterIP>[] = [
    {
      key: 'ip',
      label: 'IP',
      sortable: true,
      render: (v) => <span className="font-mono text-text-primary">{v}</span>,
    },
    {
      key: 'browser_score',
      label: 'Browser Score',
      sortable: true,
      align: 'right',
      render: (v) => (
        <span className={v >= 70 ? 'text-threat-low' : v >= 40 ? 'text-threat-medium' : 'text-threat-critical'}>
          {Math.round(v)}
        </span>
      ),
    },
    {
      key: 'ua_ch_mismatch',
      label: 'UA/CH Mismatch',
      sortable: true,
      render: (v) =>
        v ? (
          <span className="text-threat-critical">⚠️ Oui</span>
        ) : (
          <span className="text-threat-low">✓ Non</span>
        ),
    },
    {
      key: 'sec_fetch_mode',
      label: 'Sec-Fetch Mode',
      sortable: true,
      render: (v) => <span className="text-text-secondary">{v || '—'}</span>,
    },
    {
      key: 'sec_fetch_dest',
      label: 'Sec-Fetch Dest',
      sortable: true,
      render: (v) => <span className="text-text-secondary">{v || '—'}</span>,
    },
    {
      key: 'actions',
      label: '',
      sortable: false,
      render: (_, row) => (
        <button
          onClick={(e) => { e.stopPropagation(); navigate(`/investigation/${row.ip}`); }}
          className="bg-accent-primary/10 text-accent-primary px-2 py-0.5 rounded hover:bg-accent-primary/20 transition-colors text-xs"
        >
          Investiguer
        </button>
      ),
    },
  ];

  return (
    <div className="p-6 space-y-6 animate-fade-in">
      {/* Header */}
      <div>
        <h1 className="text-2xl font-bold text-text-primary">📡 Fingerprint HTTP Headers</h1>
        <p className="text-text-secondary mt-1">
          Clustering par ordre et composition des headers HTTP pour identifier les bots et fingerprints suspects.
        </p>
      </div>

      {/* Stat cards */}
      <div className="grid grid-cols-3 gap-4">
        <StatCard label="Total clusters" value={formatNumber(totalClusters)} accent="text-text-primary" />
        <StatCard label="Clusters suspects (UA/CH >50%)" value={formatNumber(suspiciousClusters)} accent="text-threat-critical" />
        <StatCard label="Clusters légitimes" value={formatNumber(legitimateClusters)} accent="text-threat-low" />
      </div>

      {/* Clusters DataTable */}
      <div className="bg-background-secondary rounded-lg border border-border overflow-hidden">
        {error ? (
          <div className="p-4"><ErrorMessage message={error} /></div>
        ) : (
          <DataTable<HeaderCluster>
            data={clusters}
            columns={clusterColumns}
            rowKey="hash"
            defaultSortKey="unique_ips"
            onRowClick={(row) => handleToggleCluster(row.hash)}
            loading={loading}
            emptyMessage="Aucun cluster détecté"
            compact
          />
        )}
      </div>

      {/* Expanded IPs panel */}
      {expandedHash && (
        <div className="bg-background-secondary rounded-lg border border-border overflow-hidden">
          <div className="px-4 py-3 border-b border-border flex items-center justify-between">
            <span className="text-sm font-semibold text-text-primary">
              IPs du cluster{' '}
              <span className="font-mono text-xs text-accent-primary">{expandedHash.slice(0, 16)}…</span>
            </span>
            <button
              onClick={() => setExpandedHash(null)}
              className="text-text-secondary hover:text-text-primary text-xs"
            >
              ✕ Fermer
            </button>
          </div>
          {ipErrors[expandedHash] ? (
            <div className="p-4"><ErrorMessage message={ipErrors[expandedHash]} /></div>
          ) : (
            <DataTable<ClusterIP>
              data={clusterIPsMap[expandedHash] ?? []}
              columns={ipColumns}
              rowKey="ip"
              defaultSortKey="browser_score"
              loading={loadingHashes.has(expandedHash)}
              emptyMessage="Aucune IP trouvée"
              compact
            />
          )}
        </div>
      )}

      {!loading && !error && (
        <p className="text-text-secondary text-xs">{formatNumber(totalClusters)} cluster(s) détecté(s)</p>
      )}
    </div>
  );
}
