'use client';

import { useState, useEffect, useRef } from 'react';
import Link from 'next/link';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import {
  ArrowLeft,
  Loader2,
  Play,
  Globe,
  CheckCircle2,
  XCircle,
  AlertTriangle,
  MinusCircle,
  Filter,
  RefreshCw,
  Building2,
  Server,
  GitFork,
  Plus,
  ChevronDown,
  ChevronRight,
  Network,
} from 'lucide-react';
import { toast } from 'sonner';
import { HostManager } from '@/components/zabbix/host-manager';

type SyncMode = 'all' | 'client' | 'site';

interface SiteResult {
  siteName: string;
  siteUid: string;
  companyId: number | null;
  companyName: string | null;
  wanIp: string | null;
  qualifyingDevices: number;
  multiWan: boolean;
  singleDeviceFallback: boolean;
  isp: string | null;
  asn: string | null;
  action: 'created' | 'updated' | 'filtered' | 'no-ip' | 'error' | 'skipped';
  hostId: string | null;
  filterReason?: string;
  error?: string;
}

interface Mapping {
  company_id: number;
  company_name: string;
  rmm_site_uid: string;
  rmm_site_name: string;
}

interface Stats {
  total: number;
  created: number;
  updated: number;
  filtered: number;
  noIp: number;
  errors: number;
  skipped: number;
  multiWan: number;
}

const ACTION_CONFIG: Record<string, { label: string; variant: 'default' | 'secondary' | 'destructive' | 'outline'; icon: React.ElementType }> = {
  created:  { label: 'Created',  variant: 'default',      icon: CheckCircle2 },
  updated:  { label: 'Updated',  variant: 'secondary',    icon: RefreshCw },
  filtered: { label: 'Filtered', variant: 'outline',      icon: Filter },
  'no-ip':  { label: 'No IP',    variant: 'outline',      icon: MinusCircle },
  skipped:  { label: 'Dry Run',  variant: 'outline',      icon: MinusCircle },
  error:    { label: 'Error',    variant: 'destructive',  icon: XCircle },
};

function ActionBadge({ action }: { action: string }) {
  const cfg = ACTION_CONFIG[action] ?? { label: action, variant: 'outline' as const, icon: MinusCircle };
  const Icon = cfg.icon;
  return (
    <Badge variant={cfg.variant} className="gap-1 text-xs">
      <Icon className="w-3 h-3" />
      {cfg.label}
    </Badge>
  );
}

export default function ZabbixWanPage() {
  const [mode, setMode] = useState<SyncMode>('all');
  const [companyId, setCompanyId] = useState<string>('');
  const [siteUid, setSiteUid] = useState<string>('');
  const [minDevices, setMinDevices] = useState(2);
  const [maxLastSeenHours, setMaxLastSeenHours] = useState(48);
  const [allowSingleDevice, setAllowSingleDevice] = useState(false);
  const [dryRun, setDryRun] = useState(true);

  const [mappings, setMappings] = useState<Mapping[]>([]);
  const [loadingMappings, setLoadingMappings] = useState(true);

  const [running, setRunning] = useState(false);
  const [results, setResults] = useState<SiteResult[]>([]);
  const [stats, setStats] = useState<Stats | null>(null);
  const [fatalError, setFatalError] = useState<string | null>(null);

  const abortRef = useRef<AbortController | null>(null);
  const tableBottomRef = useRef<HTMLDivElement>(null);

  // Manual host creation state
  const [manualOpen, setManualOpen] = useState(false);
  const [manualIp, setManualIp] = useState('');
  const [manualSiteName, setManualSiteName] = useState('');
  const [manualCompanyId, setManualCompanyId] = useState<string>('');
  const [manualDryRun, setManualDryRun] = useState(true);
  const [manualRunning, setManualRunning] = useState(false);
  const [manualResult, setManualResult] = useState<{
    action: string;
    dryRun: boolean;
    siteName: string;
    ip: string;
    companyName: string | null;
    isp: string | null;
    asn: string | null;
    hostId: string | null;
    error?: string;
  } | null>(null);

  useEffect(() => {
    fetch('/api/rmm/site-mappings')
      .then((r) => r.json())
      .then((d) => setMappings(d.mappings ?? []))
      .catch(() => toast.error('Failed to load site mappings'))
      .finally(() => setLoadingMappings(false));

    // Pre-fill manual IP with the user's current public IP (client-side)
    fetch('https://ipinfo.io/json')
      .then((r) => r.json())
      .then((d) => { if (d.ip) setManualIp(d.ip); })
      .catch(() => { /* ignore */ });
  }, []);

  // Scroll results table as rows stream in
  useEffect(() => {
    if (running) tableBottomRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  }, [results.length, running]);

  // Deduplicated company list
  const companies = Array.from(
    new Map(mappings.filter((m) => m.company_id).map((m) => [m.company_id, m.company_name])).entries()
  )
    .map(([id, name]) => ({ id, name }))
    .sort((a, b) => a.name.localeCompare(b.name));

  // Sites list (for site mode) — sorted by name
  const sites = [...mappings].sort((a, b) => a.rmm_site_name.localeCompare(b.rmm_site_name));

  // Sites filtered by selected company (for client mode label display)
  const selectedCompanyName = companies.find((c) => String(c.id) === companyId)?.name;
  const selectedSiteName = sites.find((s) => s.rmm_site_uid === siteUid)?.rmm_site_name;

  const canRun =
    !running &&
    !loadingMappings &&
    (mode === 'all' || (mode === 'client' && !!companyId) || (mode === 'site' && !!siteUid));

  const handleRun = async () => {
    setRunning(true);
    setResults([]);
    setStats(null);
    setFatalError(null);

    const ctrl = new AbortController();
    abortRef.current = ctrl;

    try {
      const resp = await fetch('/api/zabbix/sync-wan', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          mode,
          companyId: companyId ? Number(companyId) : undefined,
          siteUid: siteUid || undefined,
          minDevices,
          maxLastSeenHours,
          allowSingleDevice,
          dryRun,
        }),
        signal: ctrl.signal,
      });

      if (!resp.ok || !resp.body) {
        throw new Error(`Server error: ${resp.status}`);
      }

      const reader = resp.body.getReader();
      const decoder = new TextDecoder();
      let buf = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buf += decoder.decode(value, { stream: true });
        const lines = buf.split('\n');
        buf = lines.pop() ?? '';
        for (const line of lines) {
          if (!line.trim()) continue;
          try {
            const msg = JSON.parse(line);
            if (msg.type === 'site' && msg.result) {
              setResults((prev) => [...prev, msg.result]);
            } else if (msg.type === 'summary') {
              setStats(msg.stats);
            } else if (msg.type === 'error') {
              setFatalError(msg.message);
              toast.error(msg.message);
            }
          } catch { /* skip malformed line */ }
        }
      }
    } catch (err: any) {
      if (err.name !== 'AbortError') {
        setFatalError(String(err));
        toast.error('Run failed: ' + String(err));
      }
    } finally {
      setRunning(false);
      abortRef.current = null;
    }
  };

  const handleStop = () => {
    abortRef.current?.abort();
    setRunning(false);
  };

  // Manual host creation
  const ipv4Valid = /^(\d{1,3}\.){3}\d{1,3}$/.test(manualIp);
  const canCreateManual = !manualRunning && manualIp.trim() !== '' && manualSiteName.trim() !== '' && ipv4Valid;

  const handleManualCreate = async () => {
    setManualRunning(true);
    setManualResult(null);
    try {
      const resp = await fetch('/api/zabbix/create-host', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          ip: manualIp.trim(),
          siteName: manualSiteName.trim(),
          companyId: manualCompanyId && manualCompanyId !== 'none' ? Number(manualCompanyId) : undefined,
          dryRun: manualDryRun,
        }),
      });
      const data = await resp.json();
      if (!resp.ok) {
        setManualResult({ action: 'error', dryRun: manualDryRun, siteName: manualSiteName, ip: manualIp, companyName: null, isp: null, asn: null, hostId: null, error: data.error });
        toast.error(data.error ?? 'Failed to create host');
      } else {
        setManualResult(data);
        if (data.action === 'created') toast.success(`Host "${data.siteName}" created (id=${data.hostId})`);
        else if (data.action === 'updated') toast.success(`Host "${data.siteName}" updated (id=${data.hostId})`);
        else if (data.action === 'skipped') toast.info('Dry run — no changes written to Zabbix');
      }
    } catch (err) {
      setManualResult({ action: 'error', dryRun: manualDryRun, siteName: manualSiteName, ip: manualIp, companyName: null, isp: null, asn: null, hostId: null, error: String(err) });
      toast.error('Request failed: ' + String(err));
    } finally {
      setManualRunning(false);
    }
  };

  return (
    <div className="container mx-auto py-8 max-w-6xl space-y-6">
      {/* Header */}
      <div className="flex items-center gap-3">
        <Link href="/admin/sync">
          <Button variant="ghost" size="sm" className="gap-2">
            <ArrowLeft className="w-4 h-4" /> Back
          </Button>
        </Link>
        <div>
          <h1 className="text-2xl font-bold tracking-tight flex items-center gap-2">
            <Globe className="w-6 h-6" /> Zabbix WAN Monitor Setup
          </h1>
          <p className="text-sm text-muted-foreground mt-0.5">
            Create or update Zabbix hosts with WAN IPs and Autotask macros for alert routing
          </p>
        </div>
      </div>

      {/* Config card */}
      <Card>
        <CardHeader className="pb-4">
          <CardTitle className="text-base">Run Configuration</CardTitle>
          <CardDescription>Select scope, filters, and whether to write to Zabbix</CardDescription>
        </CardHeader>
        <CardContent className="space-y-6">
          {/* Mode */}
          <div className="space-y-2">
            <Label className="text-sm font-medium">Scope</Label>
            <div className="flex gap-2">
              {(['all', 'client', 'site'] as SyncMode[]).map((m) => (
                <button
                  key={m}
                  onClick={() => { setMode(m); setCompanyId(''); setSiteUid(''); }}
                  className={`px-4 py-2 rounded-md text-sm font-medium border transition-colors ${
                    mode === m
                      ? 'bg-primary text-primary-foreground border-primary'
                      : 'bg-background border-border hover:bg-accent'
                  }`}
                >
                  {m === 'all' ? 'All Sites' : m === 'client' ? 'By Client' : 'Single Site'}
                </button>
              ))}
            </div>
          </div>

          {/* Client selector */}
          {mode === 'client' && (
            <div className="space-y-2">
              <Label className="text-sm font-medium flex items-center gap-1.5">
                <Building2 className="w-3.5 h-3.5" /> Client
              </Label>
              <Select value={companyId} onValueChange={setCompanyId} disabled={loadingMappings}>
                <SelectTrigger className="w-80">
                  <SelectValue placeholder={loadingMappings ? 'Loading…' : 'Select a client'} />
                </SelectTrigger>
                <SelectContent>
                  {companies.map((c) => (
                    <SelectItem key={c.id} value={String(c.id)}>
                      {c.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          )}

          {/* Site selector */}
          {mode === 'site' && (
            <div className="space-y-2">
              <Label className="text-sm font-medium flex items-center gap-1.5">
                <Server className="w-3.5 h-3.5" /> Site
              </Label>
              <Select value={siteUid} onValueChange={setSiteUid} disabled={loadingMappings}>
                <SelectTrigger className="w-80">
                  <SelectValue placeholder={loadingMappings ? 'Loading…' : 'Select a site'} />
                </SelectTrigger>
                <SelectContent>
                  {sites.map((s) => (
                    <SelectItem key={s.rmm_site_uid} value={s.rmm_site_uid}>
                      {s.rmm_site_name}
                      {s.company_name ? ` (${s.company_name})` : ''}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          )}

          {/* Filters */}
          <div className="grid grid-cols-2 gap-6">
            <div className="space-y-2">
              <Label htmlFor="min-devices" className="text-sm font-medium">
                Min devices with same public IP
              </Label>
              <div className="flex items-center gap-2">
                <Input
                  id="min-devices"
                  type="number"
                  min={1}
                  max={50}
                  value={minDevices}
                  onChange={(e) => setMinDevices(Math.max(1, Number(e.target.value)))}
                  className="w-24"
                />
                <span className="text-sm text-muted-foreground">device(s)</span>
              </div>
              <p className="text-xs text-muted-foreground">
                Skip site if fewer than this many devices share the top WAN IP
              </p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="last-seen" className="text-sm font-medium">
                Max device last-seen age
              </Label>
              <div className="flex items-center gap-2">
                <Input
                  id="last-seen"
                  type="number"
                  min={1}
                  max={8760}
                  value={maxLastSeenHours}
                  onChange={(e) => setMaxLastSeenHours(Math.max(1, Number(e.target.value)))}
                  className="w-24"
                />
                <span className="text-sm text-muted-foreground">hours</span>
              </div>
              <p className="text-xs text-muted-foreground">
                Only count devices seen within this window
              </p>
            </div>
          </div>

          {/* Single-device fallback */}
          <div className="flex items-center gap-3">
            <Switch
              id="allow-single"
              checked={allowSingleDevice}
              onCheckedChange={setAllowSingleDevice}
            />
            <div>
              <Label htmlFor="allow-single" className="text-sm font-medium cursor-pointer">
                Allow single-device fallback
              </Label>
              <p className="text-xs text-muted-foreground">
                If laptop exclusion removes all IPs, accept any single device (desktop, server, network, etc.)
              </p>
            </div>
          </div>

          {/* Dry-run + actions */}
          <div className="flex items-center justify-between pt-2 border-t">
            <div className="flex items-center gap-3">
              <Switch
                id="dry-run"
                checked={dryRun}
                onCheckedChange={setDryRun}
              />
              <div>
                <Label htmlFor="dry-run" className="text-sm font-medium cursor-pointer">
                  Dry run
                </Label>
                <p className="text-xs text-muted-foreground">
                  Preview what would happen — no writes to Zabbix
                </p>
              </div>
            </div>

            <div className="flex gap-2">
              {running && (
                <Button variant="outline" size="sm" onClick={handleStop}>
                  Stop
                </Button>
              )}
              <Button
                onClick={handleRun}
                disabled={!canRun}
                className="gap-2"
              >
                {running ? (
                  <><Loader2 className="w-4 h-4 animate-spin" /> Running…</>
                ) : (
                  <><Play className="w-4 h-4" /> {dryRun ? 'Preview' : 'Run'}</>
                )}
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>

      {/* Manual Host Creation */}
      <Card>
        <CardHeader
          className="pb-4 cursor-pointer select-none"
          onClick={() => setManualOpen((v) => !v)}
        >
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2">
              {manualOpen ? <ChevronDown className="w-4 h-4 text-muted-foreground" /> : <ChevronRight className="w-4 h-4 text-muted-foreground" />}
              <Network className="w-4 h-4" />
              <CardTitle className="text-base">Manual Host</CardTitle>
            </div>
            <CardDescription className="mt-0">Create a Zabbix host from an IP address — for testing or clients not in RMM</CardDescription>
          </div>
        </CardHeader>
        {manualOpen && (
          <CardContent className="space-y-5 pt-0">
            <div className="grid grid-cols-2 gap-6">
              {/* IP Address */}
              <div className="space-y-2">
                <Label htmlFor="manual-ip" className="text-sm font-medium">IP Address</Label>
                <Input
                  id="manual-ip"
                  placeholder="203.0.113.42"
                  value={manualIp}
                  onChange={(e) => setManualIp(e.target.value)}
                  className={`w-56 font-mono ${manualIp && !ipv4Valid ? 'border-destructive' : ''}`}
                />
                {manualIp && !ipv4Valid && (
                  <p className="text-xs text-destructive">Enter a valid IPv4 address</p>
                )}
              </div>

              {/* Site Name */}
              <div className="space-y-2">
                <Label htmlFor="manual-site" className="text-sm font-medium">Site Name</Label>
                <Input
                  id="manual-site"
                  placeholder="Acme Corp - Main Office"
                  value={manualSiteName}
                  onChange={(e) => setManualSiteName(e.target.value)}
                  className="w-80"
                />
                <p className="text-xs text-muted-foreground">Becomes the Zabbix host display name</p>
              </div>
            </div>

            {/* Client selector */}
            <div className="space-y-2">
              <Label className="text-sm font-medium flex items-center gap-1.5">
                <Building2 className="w-3.5 h-3.5" /> Client (optional)
              </Label>
              <Select value={manualCompanyId} onValueChange={setManualCompanyId} disabled={loadingMappings}>
                <SelectTrigger className="w-80">
                  <SelectValue placeholder={loadingMappings ? 'Loading…' : 'No client (unlinked)'} />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="none">No client (unlinked)</SelectItem>
                  {companies.map((c) => (
                    <SelectItem key={c.id} value={String(c.id)}>
                      {c.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <p className="text-xs text-muted-foreground">
                Links the host to an Autotask client with macros, tags, and a client host group
              </p>
            </div>

            {/* Dry-run + actions */}
            <div className="flex items-center justify-between pt-2 border-t">
              <div className="flex items-center gap-3">
                <Switch
                  id="manual-dry-run"
                  checked={manualDryRun}
                  onCheckedChange={setManualDryRun}
                />
                <div>
                  <Label htmlFor="manual-dry-run" className="text-sm font-medium cursor-pointer">
                    Dry run
                  </Label>
                  <p className="text-xs text-muted-foreground">
                    Preview only — no writes to Zabbix
                  </p>
                </div>
              </div>

              <Button
                onClick={handleManualCreate}
                disabled={!canCreateManual}
                className="gap-2"
              >
                {manualRunning ? (
                  <><Loader2 className="w-4 h-4 animate-spin" /> Creating…</>
                ) : (
                  <><Plus className="w-4 h-4" /> {manualDryRun ? 'Preview' : 'Create Host'}</>
                )}
              </Button>
            </div>

            {/* Manual result */}
            {manualResult && (
              <div className={`rounded-md border p-4 space-y-2 ${
                manualResult.action === 'error'
                  ? 'border-destructive/30 bg-destructive/5'
                  : manualResult.action === 'created'
                  ? 'border-green-500/30 bg-green-500/5'
                  : manualResult.action === 'updated'
                  ? 'border-blue-500/30 bg-blue-500/5'
                  : 'border-border bg-muted/20'
              }`}>
                <div className="flex items-center gap-3">
                  <ActionBadge action={manualResult.action} />
                  <span className="font-medium text-sm">{manualResult.siteName}</span>
                  <span className="font-mono text-sm text-muted-foreground">{manualResult.ip}</span>
                </div>
                <div className="flex flex-wrap gap-x-6 gap-y-1 text-xs text-muted-foreground">
                  {manualResult.companyName && <span>Client: <strong>{manualResult.companyName}</strong></span>}
                  {manualResult.isp && <span>ISP: {manualResult.isp}</span>}
                  {manualResult.asn && <span>{manualResult.asn}</span>}
                  {manualResult.hostId && <span>Zabbix ID: <strong className="font-mono">{manualResult.hostId}</strong></span>}
                  {manualResult.dryRun && <span className="italic">Dry run — no changes written</span>}
                </div>
                {manualResult.error && (
                  <p className="text-xs text-destructive">{manualResult.error}</p>
                )}
              </div>
            )}
          </CardContent>
        )}
      </Card>

      {/* Host Manager */}
      <HostManager companies={companies} />

      {/* Results */}
      {(results.length > 0 || running || fatalError) && (
        <Card>
          <CardHeader className="pb-3">
            <div className="flex items-center justify-between">
              <CardTitle className="text-base flex items-center gap-2">
                Results
                {running && <Loader2 className="w-4 h-4 animate-spin text-muted-foreground" />}
                <span className="text-sm font-normal text-muted-foreground">
                  {results.length} site{results.length !== 1 ? 's' : ''} processed
                  {stats ? '' : running ? '…' : ''}
                </span>
              </CardTitle>

              {/* Summary stats */}
              {stats && (
                <div className="flex flex-wrap gap-3 text-xs text-muted-foreground">
                  {stats.created > 0   && <span className="text-green-600 font-medium">{stats.created} created</span>}
                  {stats.updated > 0   && <span className="text-blue-600 font-medium">{stats.updated} updated</span>}
                  {stats.skipped > 0   && <span>{stats.skipped} dry-run</span>}
                  {stats.filtered > 0  && <span className="text-yellow-600">{stats.filtered} filtered</span>}
                  {stats.noIp > 0      && <span>{stats.noIp} no-ip</span>}
                  {stats.multiWan > 0  && <span className="text-orange-500 font-medium">{stats.multiWan} multi-WAN</span>}
                  {stats.errors > 0    && <span className="text-red-600 font-medium">{stats.errors} errors</span>}
                </div>
              )}
            </div>

            {fatalError && (
              <div className="flex items-center gap-2 text-sm text-destructive rounded-md border border-destructive/30 bg-destructive/5 p-3 mt-2">
                <AlertTriangle className="w-4 h-4 flex-shrink-0" />
                {fatalError}
              </div>
            )}
          </CardHeader>

          <CardContent className="p-0">
            <div className="max-h-[520px] overflow-y-auto">
              <Table>
                <TableHeader className="sticky top-0 bg-background z-10">
                  <TableRow>
                    <TableHead>Site</TableHead>
                    <TableHead>Client</TableHead>
                    <TableHead>WAN IP</TableHead>
                    <TableHead>ISP</TableHead>
                    <TableHead className="text-center">Devices</TableHead>
                    <TableHead>Action</TableHead>
                    <TableHead>Reason</TableHead>
                    <TableHead>Zabbix ID</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {results.map((r, i) => (
                    <TableRow key={i} className={r.action === 'error' ? 'bg-destructive/5' : ''}>
                      <TableCell className="font-medium text-sm">{r.siteName}</TableCell>
                      <TableCell className="text-sm text-muted-foreground">
                        {r.companyName ?? <span className="italic text-muted-foreground/60">unmapped</span>}
                      </TableCell>
                      <TableCell>
                        <div className="space-y-0.5">
                          <span className="font-mono text-sm">
                            {r.wanIp ?? <span className="text-muted-foreground">—</span>}
                          </span>
                          {r.multiWan && (
                            <div className="flex items-center gap-1 text-xs text-orange-500">
                              <GitFork className="w-3 h-3" /> Multi-WAN
                            </div>
                          )}
                          {r.singleDeviceFallback && (
                            <div className="flex items-center gap-1 text-xs text-yellow-500">
                              <AlertTriangle className="w-3 h-3" /> Single device
                            </div>
                          )}
                        </div>
                      </TableCell>
                      <TableCell className="text-sm">
                        {r.isp ? (
                          <div className="space-y-0.5">
                            <span>{r.isp}</span>
                            {r.asn && <div className="text-xs text-muted-foreground">{r.asn}</div>}
                          </div>
                        ) : (
                          <span className="text-muted-foreground">—</span>
                        )}
                      </TableCell>
                      <TableCell className="text-center text-sm tabular-nums">
                        {r.qualifyingDevices > 0 ? r.qualifyingDevices : '—'}
                      </TableCell>
                      <TableCell>
                        <div className="space-y-1">
                          <ActionBadge action={r.action} />
                          {r.error && (
                            <p className="text-xs text-destructive leading-tight max-w-[240px] truncate" title={r.error}>
                              {r.error}
                            </p>
                          )}
                        </div>
                      </TableCell>
                      <TableCell className="text-xs text-muted-foreground max-w-[220px]">
                        {r.filterReason ?? '—'}
                      </TableCell>
                      <TableCell className="font-mono text-sm text-muted-foreground">
                        {r.hostId ?? '—'}
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
              <div ref={tableBottomRef} />
            </div>
          </CardContent>
        </Card>
      )}

      {/* Empty state */}
      {results.length === 0 && !running && !fatalError && (
        <div className="text-center py-16 text-muted-foreground text-sm">
          Configure your options above and click {dryRun ? 'Preview' : 'Run'} to start.
        </div>
      )}
    </div>
  );
}
