import { useEffect, useState } from 'react';
import { api, Machine, SSHKey, TestConnectionResponse } from '../api/client';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Label } from '@/components/ui/Label';
import { Select, SelectValue, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/Select';
import { Badge } from '@/components/ui/Badge';
import {
  Modal,
  ModalContent,
  ModalHeader,
  ModalTitle,
  ModalDescription,
  ModalBody,
  ModalFooter,
} from '@/components/ui/Modal';
import { PageHeader } from '@/components/ui/PageHeader';
import {
  Table,
  TableHeader,
  TableBody,
  TableHead,
  TableRow,
  TableCell,
} from '@/components/ui/Table';
import { EmptyState } from '@/components/ui/EmptyState';
import { CopyButton } from '@/components/ui/CopyButton';
import { Card } from '@/components/ui/Card';
import { Pencil, Trash2, Plus, Server, Zap, Cable } from 'lucide-react';
import { toast } from 'sonner';
import { cn } from '@/lib/utils';
import { subscribeMachineStatus } from '@/lib/sse';

type MachineForm = {
  id: number | undefined;
  name: string;
  host: string;
  port: number;
  ssh_user: string;
  ssh_key_id: number | null;
  mac_address: string;
  wol_enabled: boolean;
  broadcast_addr: string;
  wake_timeout_seconds: number;
  wake_check_interval_seconds: number;
};

const defaultForm: MachineForm = {
  id: undefined,
  name: '',
  host: '',
  port: 22,
  ssh_user: 'root',
  ssh_key_id: null,
  mac_address: '',
  wol_enabled: false,
  broadcast_addr: '',
  wake_timeout_seconds: 180,
  wake_check_interval_seconds: 5,
};

export default function Machines() {
  const [machines, setMachines] = useState<Machine[]>([]);
  const [sshKeys, setSSHKeys] = useState<SSHKey[]>([]);
  const [modalOpen, setModalOpen] = useState(false);
  const [deleteId, setDeleteId] = useState<number | null>(null);
  const [form, setForm] = useState<MachineForm>(defaultForm);
  const [loading, setLoading] = useState(false);
  const [probing, setProbing] = useState(false);
  const [connModal, setConnModal] = useState<{ machine: Machine | null; result: TestConnectionResponse | null; loading: boolean }>({ machine: null, result: null, loading: false });

  useEffect(() => {
    load();
    setProbing(true);
    api('/api/machines/refresh', { method: 'POST' }).catch(() => {});
    const timer = setTimeout(() => setProbing(false), 5000);
    return () => clearTimeout(timer);
  }, []);

  useEffect(() => {
    const unsub = subscribeMachineStatus((evt) => {
      setMachines((prev) =>
        prev.map((m) =>
          m.id === evt.machine_id ? { ...m, status: evt.status } : m
        )
      );
    });
    return unsub;
  }, []);

  async function load() {
    try {
      const [ms, ks] = await Promise.all([
        api<Machine[]>('/api/machines'),
        api<SSHKey[]>('/api/ssh-keys'),
      ]);
      setMachines(ms);
      setSSHKeys(ks);
    } catch {}
  }

  function openCreate() {
    setForm(defaultForm);
    setModalOpen(true);
  }

  function openEdit(m: Machine) {
    setForm({
      id: m.id,
      name: m.name,
      host: m.host,
      port: m.port,
      ssh_user: m.ssh_user,
      ssh_key_id: m.ssh_key_id,
      mac_address: m.mac_address || '',
      wol_enabled: m.wol_enabled,
      broadcast_addr: m.broadcast_addr || '',
      wake_timeout_seconds: m.wake_timeout_seconds || 180,
      wake_check_interval_seconds: m.wake_check_interval_seconds || 5,
    });
    setModalOpen(true);
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!form.name.trim() || !form.host.trim()) {
      toast.error('Name and host are required');
      return;
    }
    if (
      form.mac_address &&
      !/^([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$/.test(form.mac_address)
    ) {
      toast.error('Invalid MAC address format (AA:BB:CC:DD:EE:FF)');
      return;
    }
    setLoading(true);
    try {
      const payload: Record<string, unknown> = {
        id: form.id || null,
        name: form.name,
        host: form.host,
        port: Number(form.port),
        ssh_user: form.ssh_user,
        ssh_key_id: form.ssh_key_id,
        mac_address: form.mac_address || null,
        wol_enabled: Boolean(form.wol_enabled),
        broadcast_addr: form.broadcast_addr || null,
        wake_timeout_seconds: Number(form.wake_timeout_seconds),
        wake_check_interval_seconds: Number(form.wake_check_interval_seconds),
      };
      await api(form.id ? `/api/machines/${form.id}` : '/api/machines', {
        method: form.id ? 'PUT' : 'POST',
        body: payload,
      });
      setModalOpen(false);
      toast.success(form.id ? 'Machine updated' : 'Machine created');
      load();
    } catch (e: unknown) {
      toast.error((e as Error).message);
    } finally {
      setLoading(false);
    }
  }

  async function handleDelete() {
    if (deleteId === null) return;
    try {
      await api(`/api/machines/${deleteId}`, { method: 'DELETE' });
      toast.success('Machine deleted');
      setDeleteId(null);
      load();
    } catch (e: unknown) {
      toast.error((e as Error).message);
    }
  }

  async function handleTestWol(m: Machine) {
    try {
      await api<{ ok: boolean; sent: number }>(`/api/machines/${m.id}/test-wol`, { method: 'POST' });
      toast.success(`Magic packet sent (${m.mac_address})`);
    } catch (e: unknown) {
      toast.error(`Wake failed: ${(e as Error).message}`);
    }
  }

  async function handleTestConnection(m: Machine) {
    setConnModal({ machine: m, result: null, loading: true });
    try {
      const result = await api<TestConnectionResponse>(`/api/machines/${m.id}/test-connection`, { method: 'POST' });
      setConnModal({ machine: m, result, loading: false });
    } catch (e: unknown) {
      setConnModal({ machine: m, result: { success: false, error: (e as Error).message }, loading: false });
    }
  }

  async function handleApproveFingerprint() {
    if (!connModal.machine || !connModal.result?.fingerprint) return;
    try {
      const updated = await api<Machine>(`/api/machines/${connModal.machine.id}/approve-fingerprint`, {
        method: 'POST',
        body: { fingerprint: connModal.result.fingerprint },
      });
      setMachines(prev => prev.map(m => m.id === updated.id ? updated : m));
      toast.success('Fingerprint approved');
      setConnModal({ machine: null, result: null, loading: false });
    } catch (e: unknown) {
      toast.error(`Approve failed: ${(e as Error).message}`);
    }
  }

  function closeConnModal() {
    setConnModal({ machine: null, result: null, loading: false });
  }

  function keyLabel(id: number | null) {
    if (!id) return 'Server Key';
    const k = sshKeys.find(k => k.id === id);
    return k ? k.label : `Key #${id}`;
  }

  return (
    <div className="space-y-6">
      <PageHeader
        title="Machines"
        description="Remote machines reachable via SSH"
        actions={
          <Button onClick={openCreate} size="sm">
            <Plus className="h-4 w-4" />
            Add Machine
          </Button>
        }
      />

      <Card>
        <div className="p-0">
          {machines.length === 0 ? (
            <EmptyState
              icon={<Server className="h-5 w-5" />}
              title="No machines"
              description="Add a remote machine to start syncing data"
              action={
                <Button onClick={openCreate} size="sm">
                  <Plus className="h-4 w-4" />
                  Add Machine
                </Button>
              }
            />
          ) : (
            <>
              {probing && (
                <div className="flex items-center gap-2 px-4 pt-3 text-xs text-muted-foreground">
                  <span className="inline-block h-2 w-2 bg-amber-400 rounded-full animate-pulse" />
                  Checking machine status...
                </div>
              )}
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Name</TableHead>
                  <TableHead>Host</TableHead>
                  <TableHead>SSH Key</TableHead>
                  <TableHead>WoL</TableHead>
                  <TableHead>WoL Timeout</TableHead>
                  <TableHead>Status</TableHead>
                  <TableHead className="w-24">Actions</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {machines.map(m => (
                  <TableRow key={m.id}>
                    <TableCell className="font-medium">{m.name}</TableCell>
                    <TableCell>
                      <span className="font-mono text-xs text-fg-muted">
                        {m.host}:{m.port}
                      </span>
                    </TableCell>
                    <TableCell className="text-fg-muted text-xs">
                      {keyLabel(m.ssh_key_id)}
                    </TableCell>
                    <TableCell>
                      {m.wol_enabled ? (
                        <Badge variant="info" label="Yes" />
                      ) : (
                        <span className="text-fg-subtle text-xs">No</span>
                      )}
                    </TableCell>
                    <TableCell>
                      {m.wol_enabled ? (
                        <span className="text-xs text-fg-muted">
                          {m.wake_timeout_seconds}s
                        </span>
                      ) : (
                        <span className="text-fg-subtle text-xs">—</span>
                      )}
                    </TableCell>
                    <TableCell>
                      <StatusBadge status={m.status} />
                    </TableCell>
                    <TableCell>
                      <div className="flex items-center gap-1">
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          onClick={() => openEdit(m)}
                          title="Edit"
                        >
                          <Pencil className="h-3.5 w-3.5" />
                        </Button>
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          onClick={() => handleTestConnection(m)}
                          title="Test SSH Connection"
                        >
                          <Cable className="h-3.5 w-3.5" />
                        </Button>
                        {m.wol_enabled && (
                          <Button
                            variant="ghost"
                            size="icon-sm"
                            onClick={() => handleTestWol(m)}
                            title="Test Wake-on-LAN"
                          >
                            <Zap className="h-3.5 w-3.5" />
                          </Button>
                        )}
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          onClick={() => setDeleteId(m.id)}
                          className="text-rose-400 hover:text-rose-300 hover:bg-rose-500/10"
                          title="Delete"
                        >
                          <Trash2 className="h-3.5 w-3.5" />
                        </Button>
                      </div>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
            </>
          )}
        </div>
      </Card>

      <Modal open={modalOpen} onOpenChange={setModalOpen}>
        <ModalContent size="md">
          <ModalHeader>
            <ModalTitle>{form.id ? 'Edit Machine' : 'Add Machine'}</ModalTitle>
            <ModalDescription>
              {form.id
                ? 'Update the configuration for this machine'
                : 'Configure a new remote machine for syncing'}
            </ModalDescription>
          </ModalHeader>
          <form onSubmit={handleSubmit}>
            <ModalBody className="space-y-4">
              <div className="space-y-1.5">
                <Label htmlFor="name" required>
                  Name
                </Label>
                <Input
                  id="name"
                  placeholder="backup-nas"
                  value={form.name}
                  onChange={e => setForm({ ...form, name: e.target.value })}
                />
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1.5">
                  <Label htmlFor="host">Host / IP</Label>
                  <Input
                    id="host"
                    placeholder="192.168.1.100"
                    value={form.host}
                    onChange={e => setForm({ ...form, host: e.target.value })}
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="port">SSH Port</Label>
                  <Input
                    id="port"
                    type="number"
                    placeholder="22"
                    value={form.port}
                    onChange={e =>
                      setForm({ ...form, port: Number(e.target.value) })
                    }
                  />
                </div>
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1.5">
                  <Label htmlFor="ssh_user">SSH User</Label>
                  <Input
                    id="ssh_user"
                    placeholder="root"
                    value={form.ssh_user}
                    onChange={e =>
                      setForm({ ...form, ssh_user: e.target.value })
                    }
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="ssh_key_id">SSH Key</Label>
                  <Select
                    value={form.ssh_key_id?.toString() ?? ''}
                    onValueChange={v =>
                      setForm({ ...form, ssh_key_id: v ? Number(v) : null })
                    }
                  >
                    <SelectTrigger id="ssh_key_id">
                      <SelectValue placeholder="Server Key" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="">Server Key (default)</SelectItem>
                      {sshKeys.map(k => (
                        <SelectItem key={k.id} value={k.id.toString()}>
                          {k.label} {k.in_use ? '(in use)' : ''}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="mac_address">MAC Address</Label>
                <Input
                  id="mac_address"
                  placeholder="AA:BB:CC:DD:EE:FF"
                  value={form.mac_address}
                  onChange={e =>
                    setForm({ ...form, mac_address: e.target.value })
                  }
                />
                <p className="text-xs text-fg-subtle">
                  Required for Wake-on-LAN
                </p>
              </div>
              <div
                className={cn(
                  'flex items-center gap-2 rounded-card p-3 transition-colors',
                  form.wol_enabled
                    ? 'bg-accent/5 border border-accent/20'
                    : 'bg-surface-raised border border-border'
                )}
              >
                <input
                  type="checkbox"
                  id="wol_enabled"
                  checked={form.wol_enabled}
                  onChange={e =>
                    setForm({ ...form, wol_enabled: e.target.checked })
                  }
                  className="h-4 w-4 rounded border-border accent-accent"
                />
                <Label htmlFor="wol_enabled" className="cursor-pointer mb-0">
                  Enable Wake-on-LAN
                </Label>
              </div>
              {form.wol_enabled && (
                <div className="space-y-3 p-3 border border-border rounded-card bg-surface-raised">
                  <p className="text-xs text-fg-subtle font-medium">Wake-on-LAN Settings</p>
                  <div className="space-y-1.5">
                    <Label htmlFor="broadcast_addr">Broadcast Address</Label>
                    <Input
                      id="broadcast_addr"
                      placeholder="255.255.255.255"
                      value={form.broadcast_addr}
                      onChange={e =>
                        setForm({ ...form, broadcast_addr: e.target.value })
                      }
                    />
                    <p className="text-xs text-fg-subtle">
                      Leave blank to use 255.255.255.255. Set to your subnet broadcast
                      address if the server has multiple interfaces.
                    </p>
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div className="space-y-1.5">
                      <Label htmlFor="wake_timeout_seconds">Wake timeout (s)</Label>
                      <Input
                        id="wake_timeout_seconds"
                        type="number"
                        min={10}
                        max={600}
                        value={form.wake_timeout_seconds}
                        onChange={e =>
                          setForm({ ...form, wake_timeout_seconds: Number(e.target.value) })
                        }
                      />
                      <p className="text-xs text-fg-subtle">
                        HP Microservers typically need ~180s.
                      </p>
                    </div>
                    <div className="space-y-1.5">
                      <Label htmlFor="wake_check_interval_seconds">Check interval (s)</Label>
                      <Input
                        id="wake_check_interval_seconds"
                        type="number"
                        min={1}
                        max={60}
                        value={form.wake_check_interval_seconds}
                        onChange={e =>
                          setForm({ ...form, wake_check_interval_seconds: Number(e.target.value) })
                        }
                      />
                      <p className="text-xs text-fg-subtle">
                        How often to poll SSH readiness.
                      </p>
                    </div>
                  </div>
                </div>
              )}
            </ModalBody>
            <ModalFooter>
              <Button
                type="button"
                variant="secondary"
                onClick={() => setModalOpen(false)}
              >
                Cancel
              </Button>
              <Button type="submit" loading={loading}>
                {form.id ? 'Save Changes' : 'Add Machine'}
              </Button>
            </ModalFooter>
          </form>
        </ModalContent>
      </Modal>

      <Modal open={deleteId !== null} onOpenChange={v => !v && setDeleteId(null)}>
        <ModalContent size="sm">
          <ModalHeader>
            <ModalTitle>Delete Machine</ModalTitle>
            <ModalDescription>
              Are you sure you want to delete this machine? This action cannot
              be undone.
            </ModalDescription>
          </ModalHeader>
          <ModalFooter>
            <Button variant="secondary" onClick={() => setDeleteId(null)}>
              Cancel
            </Button>
            <Button variant="danger-solid" onClick={handleDelete}>
              Delete
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>

      <Modal open={connModal.machine !== null} onOpenChange={v => !v && closeConnModal()}>
        <ModalContent size="md">
          <ModalHeader>
            <ModalTitle>SSH Connection Test</ModalTitle>
            <ModalDescription>
              {connModal.machine?.name} ({connModal.machine?.host}:{connModal.machine?.port})
            </ModalDescription>
          </ModalHeader>
          <ModalBody className="space-y-4">
            {connModal.loading && (
              <div className="flex items-center justify-center py-8">
                <div className="h-6 w-6 border-2 border-accent border-t-transparent rounded-full animate-spin" />
              </div>
            )}
            {!connModal.loading && connModal.result && (
              <div className="space-y-4">
                {connModal.result.success ? (
                  <div className="rounded-card bg-emerald-500/10 border border-emerald-500/30 p-4">
                    <p className="text-sm font-medium text-emerald-400 mb-1">Connection successful</p>
                    <pre className="text-xs text-fg-muted whitespace-pre-wrap">{connModal.result.output}</pre>
                  </div>
                ) : (
                  <div className="rounded-card bg-rose-500/10 border border-rose-500/30 p-4">
                    <p className="text-sm font-medium text-rose-400 mb-1">Connection failed</p>
                    <p className="text-xs text-fg-muted">{connModal.result.error}</p>
                  </div>
                )}
                {connModal.result.fingerprint && (
                  <div className="space-y-2">
                    <p className="text-sm font-medium text-fg">Host Key Fingerprint</p>
                    <div className="flex items-center gap-2">
                      <code className="flex-1 text-xs font-mono bg-surface-raised rounded-card px-3 py-2 text-fg-muted border border-border">
                        {connModal.result.fingerprint}
                      </code>
                      <CopyButton text={connModal.result.fingerprint} />
                    </div>
                    {connModal.machine && !connModal.machine.fingerprint_confirmed && (
                      <div className="flex items-center gap-2 mt-2">
                        <Badge variant="pending" label="Not verified" />
                        <span className="text-xs text-fg-muted">Approve to trust this fingerprint</span>
                      </div>
                    )}
                    {connModal.machine && connModal.machine.fingerprint_confirmed && (
                      <div className="flex items-center gap-2 mt-2">
                        <Badge variant="success" label="Verified" />
                      </div>
                    )}
                  </div>
                )}
              </div>
            )}
          </ModalBody>
          <ModalFooter>
            <Button variant="secondary" onClick={closeConnModal}>
              Close
            </Button>
            {!connModal.loading && connModal.result && connModal.result.fingerprint && connModal.machine && !connModal.machine.fingerprint_confirmed && (
              <Button onClick={handleApproveFingerprint}>
                Approve &amp; Trust Fingerprint
              </Button>
            )}
          </ModalFooter>
        </ModalContent>
      </Modal>
    </div>
  );
}

function StatusBadge({ status }: { status: string }) {
  const variant =
    status === 'online'
      ? 'success'
      : status === 'offline'
        ? 'neutral'
        : 'info';
  return <Badge variant={variant} label={status} />;
}
