import { useMemo, useState } from "react";
import { ApiError } from "../../api/client";
import type { Machine } from "../../api/types";
import { useAuth } from "../../auth/AuthContext";
import { PageHeader } from "../../components/layout/PageHeader";
import {
  InfoIcon,
  KeyIcon,
  RefreshIcon,
  SearchIcon,
  TrashIcon,
} from "../../components/layout/icons";
import { Badge } from "../../components/ui/Badge";
import { Button } from "../../components/ui/Button";
import { Input } from "../../components/ui/Input";
import { Panel } from "../../components/ui/Panel";
import { EmptyState, ErrorState } from "../../components/ui/States";
import { StatusDot } from "../../components/ui/StatusDot";
import { machineTone } from "../../components/ui/status";
import { Table, type Column } from "../../components/ui/Table";
import { TableSkeleton } from "../../components/ui/TableSkeleton";
import { absoluteTime, relativeTime } from "../../lib/time";
import "./machines.css";
import { DeleteMachineDialog } from "./DeleteMachineDialog";
import { MachineDetailDrawer } from "./MachineDetailDrawer";
import { MachineKeysModal } from "./MachineKeysModal";
import { useMachines } from "./hooks";

export function MachinesPage() {
  const { isAdmin } = useAuth();
  const machinesQuery = useMachines();
  const [filter, setFilter] = useState("");

  const [detailFor, setDetailFor] = useState<Machine | null>(null);
  const [keysFor, setKeysFor] = useState<Machine | null>(null);
  const [deleteFor, setDeleteFor] = useState<Machine | null>(null);

  const { data } = machinesQuery;
  const machines = useMemo(() => data ?? [], [data]);

  const filtered = useMemo(() => {
    const q = filter.trim().toLowerCase();
    if (!q) return machines;
    return machines.filter(
      (m) =>
        m.hostname.toLowerCase().includes(q) ||
        m.agent_id.toLowerCase().includes(q),
    );
  }, [machines, filter]);

  const onlineCount = useMemo(
    () => machines.filter((m) => m.status === "online").length,
    [machines],
  );

  const columns: Column<Machine>[] = [
    {
      key: "status",
      header: "",
      cellClass: "dt__status",
      render: (m) => (
        <StatusDot tone={machineTone(m.status)} label={m.status} />
      ),
    },
    {
      key: "hostname",
      header: "Hostname",
      render: (m) => <span className="dt__strong">{m.hostname}</span>,
    },
    {
      key: "os",
      header: "OS",
      render: (m) => (
        <span className="dt__muted">{m.os_version ?? "Unknown"}</span>
      ),
    },
    {
      key: "mode",
      header: "Mode",
      render: (m) =>
        m.is_persistent ? (
          <Badge tone="accent">Persistent</Badge>
        ) : (
          <Badge tone="neutral">Attended</Badge>
        ),
    },
    {
      key: "last_seen",
      header: "Last seen",
      render: (m) => (
        <span className="dt__mono" title={absoluteTime(m.last_seen)}>
          {relativeTime(m.last_seen)}
        </span>
      ),
    },
    {
      key: "agent_id",
      header: "Agent ID",
      render: (m) => (
        <span className="dt__mono" title={m.agent_id}>
          {m.agent_id}
        </span>
      ),
    },
    {
      key: "actions",
      header: "",
      cellClass: "dt__actions",
      render: (m) => (
        <span
          className="dt__rowactions"
          // Row actions shouldn't trigger the row's open-detail click.
          onClick={(e) => e.stopPropagation()}
        >
          <Button
            variant="ghost"
            size="sm"
            onClick={() => setDetailFor(m)}
            aria-label={`View detail for ${m.hostname}`}
          >
            <InfoIcon width={14} height={14} />
            Detail
          </Button>
          {isAdmin && (
            <Button
              variant="ghost"
              size="sm"
              onClick={() => setKeysFor(m)}
              aria-label={`Manage keys for ${m.hostname}`}
            >
              <KeyIcon width={14} height={14} />
              Keys
            </Button>
          )}
          <Button
            variant="danger"
            size="sm"
            onClick={() => setDeleteFor(m)}
            aria-label={`Remove ${m.hostname}`}
          >
            <TrashIcon width={14} height={14} />
            Delete
          </Button>
        </span>
      ),
    },
  ];

  return (
    <div className="page">
      <PageHeader
        title="Machines"
        subtitle="Registered agents across all managed endpoints."
        actions={
          <Button
            variant="ghost"
            onClick={() => void machinesQuery.refetch()}
            loading={machinesQuery.isFetching}
          >
            <RefreshIcon width={15} height={15} />
            Refresh
          </Button>
        }
      />

      <Panel flush>
        <div style={{ padding: "14px 16px 0" }}>
          <div className="toolbar">
            <div className="searchbox">
              <span className="searchbox__icon">
                <SearchIcon width={15} height={15} />
              </span>
              <Input
                placeholder="Filter by hostname or agent ID"
                value={filter}
                onChange={(e) => setFilter(e.target.value)}
                aria-label="Filter machines"
              />
            </div>
            <div className="toolbar__count">
              <span className="mono">{onlineCount}</span> online ·{" "}
              <span className="mono">{machines.length}</span> total
            </div>
          </div>
        </div>

        {machinesQuery.isLoading ? (
          <>
            <span className="visually-hidden" role="status">
              Loading machines
            </span>
            <TableSkeleton
              headers={["", "Hostname", "OS", "Mode", "Last seen", "Agent ID", ""]}
            />
          </>
        ) : machinesQuery.isError ? (
          <ErrorState
            title="Could not load machines"
            message={
              machinesQuery.error instanceof ApiError
                ? machinesQuery.error.message
                : "The GuruConnect server did not respond. Check the relay status, then retry."
            }
            action={
              <Button variant="primary" onClick={() => void machinesQuery.refetch()}>
                Retry
              </Button>
            }
          />
        ) : filtered.length === 0 ? (
          filter ? (
            <EmptyState
              title="No matching machines"
              message={`Nothing matches "${filter}". Clear the filter to see every registered machine.`}
              action={
                <Button variant="ghost" onClick={() => setFilter("")}>
                  Clear filter
                </Button>
              }
            />
          ) : (
            <EmptyState
              title="No machines registered yet"
              message="Agents appear here the moment they enroll with the relay. Install the GuruConnect agent on an endpoint to get started."
            />
          )
        ) : (
          <Table
            columns={columns}
            rows={filtered}
            rowKey={(m) => m.id}
            onRowClick={setDetailFor}
            rowLabel={(m) => m.hostname}
          />
        )}
      </Panel>

      <MachineDetailDrawer machine={detailFor} onClose={() => setDetailFor(null)} />
      {isAdmin && (
        <MachineKeysModal machine={keysFor} onClose={() => setKeysFor(null)} />
      )}
      <DeleteMachineDialog machine={deleteFor} onClose={() => setDeleteFor(null)} />
    </div>
  );
}
