import { useMutation, useQuery } from "@tanstack/react-query";
import { Activity, Cpu, Copy, RadioTower, ScrollText } from "lucide-react";
import { useState } from "react";

import { AgentInstallInfo, api, Node } from "../api/client";
import { DataTable } from "../components/DataTable";
import { iconButtonClass, secondaryButtonClass } from "../components/FormControls";
import { LoadingOverlay } from "../components/LoadingOverlay";
import { Modal } from "../components/Modal";
import { PageHeader } from "../components/PageHeader";

export function Nodes() {
  const nodes = useQuery({ queryKey: ["nodes-agents"], queryFn: () => api<Node[]>("/nodes/agents") });
  const [selectedNode, setSelectedNode] = useState<Node | null>(null);
  const [detailNode, setDetailNode] = useState<Node | null>(null);
  const [copied, setCopied] = useState(false);
  const installInfo = useMutation({
    mutationFn: (node: Node) => api<AgentInstallInfo>(`/nodes/${node.id}/agent/install-info`),
    onSuccess: (_data, node) => {
      setSelectedNode(node);
      setCopied(false);
    },
  });

  async function copyCommand() {
    if (!installInfo.data) {
      return;
    }
    await navigator.clipboard.writeText(installInfo.data.command);
    setCopied(true);
  }

  function agentFlows(node: Node) {
    const flows = node.agent?.last_payload?.flows;
    const interfaceTraffic = node.agent?.last_payload?.interface_traffic;
    if (Array.isArray(flows) && flows.length) {
      return flows;
    }
    return Array.isArray(interfaceTraffic) ? interfaceTraffic : [];
  }

  function agentInterfaces(node: Node) {
    const interfaces = node.agent?.last_payload?.interfaces;
    return Array.isArray(interfaces) ? interfaces : [];
  }

  function agentConntrack(node: Node) {
    const conntrack = node.agent?.last_payload?.conntrack;
    return conntrack && typeof conntrack === "object" ? conntrack as Record<string, unknown> : {};
  }

  return (
    <>
      <PageHeader title="Nodes" subtitle="Cluster nodes, capacity, health, and NexaFabric agent enrollment." />
      <LoadingOverlay open={installInfo.isPending} message="Generating node agent installer..." />
      {nodes.isLoading ? <div className="rounded-md border border-border bg-panel p-8 text-sm">Loading...</div> : null}
      {nodes.error ? <div className="rounded-md border border-danger p-4 text-sm text-danger">Failed to load nodes.</div> : null}
      {!nodes.isLoading && !nodes.error ? (
        <DataTable
          rows={(nodes.data ?? []) as unknown as Record<string, unknown>[]}
          columns={[
            { key: "name", label: "Name" },
            { key: "status", label: "Status" },
            { key: "cpu_count", label: "CPU" },
            { key: "memory_mb", label: "Memory MB" },
            {
              key: "agent",
              label: "Agent",
              render: (row) => {
                const node = row as unknown as Node;
                return node.agent ? `${node.agent.status}${node.agent.version ? ` · ${node.agent.version}` : ""}` : "not_installed";
              },
            },
            {
              key: "actions",
              label: "Actions",
              render: (row) => {
                const node = row as unknown as Node;
                return (
                  <div className="flex justify-end gap-2">
                    <button
                      className={iconButtonClass}
                      title="View agent data"
                      aria-label={`View agent data for ${node.name}`}
                      disabled={!node.agent?.last_payload}
                      onClick={() => setDetailNode(node)}
                    >
                      <ScrollText size={16} />
                    </button>
                    <button
                      className={iconButtonClass}
                      title="Install node agent"
                      aria-label={`Install agent on ${node.name}`}
                      onClick={() => installInfo.mutate(node)}
                    >
                      <RadioTower size={16} />
                    </button>
                  </div>
                );
              },
            },
          ]}
        />
      ) : null}
      <Modal title="Install Node Agent" open={Boolean(selectedNode)} onClose={() => setSelectedNode(null)}>
        <div className="space-y-4">
          <div className="flex items-center gap-2 font-medium">
            <Cpu size={18} />
            {selectedNode?.name}
          </div>
          <div className="rounded-md border border-border bg-canvas p-3 text-xs text-slate-500 dark:text-slate-400">
            Run this command as root on the Proxmox node. It installs the agent under <code>/opt/nexafabric-agent</code> and starts a systemd service.
          </div>
          <pre className="max-h-48 overflow-auto rounded-md border border-border bg-canvas p-3 text-xs">
            {installInfo.data?.command ?? "Generating installer..."}
          </pre>
          <div className="grid gap-2 text-xs">
            <span className="text-slate-500 dark:text-slate-400">Installer link</span>
            <code className="break-all rounded-md border border-border bg-canvas p-3">{installInfo.data?.install_url ?? ""}</code>
          </div>
          <button className={secondaryButtonClass} disabled={!installInfo.data} onClick={copyCommand}>
            <Copy size={16} />
            {copied ? "Copied" : "Copy Command"}
          </button>
        </div>
      </Modal>
      <Modal title="Agent Data" open={Boolean(detailNode)} onClose={() => setDetailNode(null)}>
        {detailNode ? (
          <div className="space-y-4">
            <div className="flex items-center gap-2 font-medium">
              <Activity size={18} />
              {detailNode.name}
            </div>
            <div className="grid gap-3 sm:grid-cols-3">
              <div className="rounded-md border border-border bg-canvas p-3">
                <div className="text-xs text-slate-500 dark:text-slate-400">Status</div>
                <div className="mt-1 text-sm font-medium">{detailNode.agent?.status ?? "not_installed"}</div>
              </div>
              <div className="rounded-md border border-border bg-canvas p-3">
                <div className="text-xs text-slate-500 dark:text-slate-400">Flows</div>
                <div className="mt-1 text-sm font-medium">{agentFlows(detailNode).length}</div>
              </div>
              <div className="rounded-md border border-border bg-canvas p-3">
                <div className="text-xs text-slate-500 dark:text-slate-400">Conntrack</div>
                <div className="mt-1 text-sm font-medium">{String(agentConntrack(detailNode).count ?? "unknown")}</div>
              </div>
            </div>
            <section>
              <div className="mb-2 text-sm font-medium">Interfaces</div>
              <div className="max-h-48 overflow-auto rounded-md border border-border">
                {agentInterfaces(detailNode).length ? agentInterfaces(detailNode).map((item, index) => {
                  const iface = item as Record<string, unknown>;
                  return (
                    <div key={`${String(iface.name)}-${index}`} className="grid grid-cols-[1fr_auto] gap-3 border-b border-border px-3 py-2 text-xs last:border-0">
                      <div>
                        <div className="font-medium">{String(iface.name)}</div>
                        <div className="text-slate-500">state {String(iface.operstate ?? "unknown")} {iface.vmid ? `· VMID ${String(iface.vmid)}` : ""}</div>
                      </div>
                      <div className="text-right text-slate-500">
                        <div>rx {String(iface.rx_bytes ?? 0)}</div>
                        <div>tx {String(iface.tx_bytes ?? 0)}</div>
                      </div>
                    </div>
                  );
                }) : <div className="p-3 text-xs text-slate-500">No interface telemetry in the last heartbeat.</div>}
              </div>
            </section>
            <section>
              <div className="mb-2 text-sm font-medium">Flows</div>
              <div className="max-h-48 overflow-auto rounded-md border border-border">
                {agentFlows(detailNode).length ? agentFlows(detailNode).slice(0, 50).map((item, index) => {
                  const flow = item as Record<string, unknown>;
                  const isInterfaceCounter = flow.protocol === "interface-counter";
                  return (
                    <div key={index} className="border-b border-border px-3 py-2 text-xs last:border-0">
                      <div className="font-medium">
                        {isInterfaceCounter
                          ? `VMID ${String(flow.vmid)} ${String(flow.interface ?? "")}`
                          : `${String(flow.source_ip)}:${String(flow.source_port ?? "")} -> ${String(flow.destination_ip)}:${String(flow.destination_port ?? "")}`}
                      </div>
                      <div className="text-slate-500">
                        {String(flow.protocol ?? "unknown")} · {String(flow.bytes ?? 0)} bytes · {String(flow.packets ?? 0)} packets · {String(flow.state ?? "unknown")}
                      </div>
                      {isInterfaceCounter ? <div className="text-slate-500">rx {String(flow.rx_bytes ?? 0)} · tx {String(flow.tx_bytes ?? 0)}</div> : null}
                    </div>
                  );
                }) : <div className="p-3 text-xs text-slate-500">No conntrack flows or interface counters were reported in the last heartbeat.</div>}
              </div>
            </section>
            <section>
              <div className="mb-2 text-sm font-medium">Raw Payload</div>
              <pre className="max-h-60 overflow-auto rounded-md border border-border bg-canvas p-3 text-xs">
                {JSON.stringify(detailNode.agent?.last_payload ?? {}, null, 2)}
              </pre>
            </section>
          </div>
        ) : null}
      </Modal>
    </>
  );
}
