"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import {
  Smartphone,
  RefreshCw,
  Cpu,
  Clock,
  Link2,
  CheckCircle,
  XCircle,
  AlertCircle,
  Store,
  DollarSign,
  ExternalLink,
  Wallet,
  Settings,
  Activity,
  Zap,
  HardDrive,
  Timer,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import Link from "next/link";

interface DeviceItem {
  id: string;
  name: string;
  tunnel_url: string;
  models: string[];
  hardware: string;
  status: string;
  last_seen: string;
  latency_ms: number | null;
  created_at: string;
  // Enhanced heartbeat fields
  vram_usage_mb: number | null;
  active_model: string | null;
  requests_served: number;
  uptime_seconds: number;
  savings_usd: number;
  marketplace_enabled?: boolean;
  price_cents_per_hour?: number | null;
}

interface DevicesResponse {
  devices: DeviceItem[];
}

interface ConnectStatus {
  connected: boolean;
  accountId?: string;
}

interface CreditsBalance {
  balance_cents: number;
}

interface SSEDeviceEvent {
  device: DeviceItem;
}

interface SSEHeartbeatEvent {
  devices: DeviceItem[];
}

const CREDIT_AMOUNTS = [
  { label: "$10", cents: 1000 },
  { label: "$100", cents: 10000 },
  { label: "$1,000", cents: 100000 },
] as const;

function formatUptime(seconds: number): string {
  if (seconds < 60) return `${seconds}s`;
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  return m > 0 ? `${h}h ${m}m` : `${h}h`;
}

function formatVram(mb: number | null): string {
  if (mb == null) return "N/A";
  if (mb >= 1024) return `${(mb / 1024).toFixed(1)} GB`;
  return `${mb} MB`;
}

export default function DevicesPage() {
  const [devices, setDevices] = useState<DeviceItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [lastRefresh, setLastRefresh] = useState<Date | null>(null);
  const [sseConnected, setSseConnected] = useState(false);
  const [notification, setNotification] = useState<string | null>(null);
  const [connectStatus, setConnectStatus] = useState<ConnectStatus | null>(null);
  const [connectLoading, setConnectLoading] = useState(false);
  const [creditsBalance, setCreditsBalance] = useState<CreditsBalance | null>(null);
  const [creditsLoading, setCreditsLoading] = useState(false);
  const [creditsPurchaseLoading, setCreditsPurchaseLoading] = useState<number | null>(null);
  // Operator agreement consent when enabling marketplace (#304)
  const [pendingEnableDeviceId, setPendingEnableDeviceId] = useState<string | null>(null);
  const [agreementChecked, setAgreementChecked] = useState(false);

  const eventSourceRef = useRef<EventSource | null>(null);
  const notificationTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Show a temporary notification
  const showNotification = useCallback((message: string) => {
    setNotification(message);
    if (notificationTimerRef.current) clearTimeout(notificationTimerRef.current);
    notificationTimerRef.current = setTimeout(() => setNotification(null), 5000);
  }, []);

  // Initial fetch via REST (fallback + first paint)
  const fetchDevices = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const res = await fetch("/api/dashboard/devices");
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const data: DevicesResponse = await res.json();
      setDevices(data.devices);
      setLastRefresh(new Date());
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to load devices");
    } finally {
      setLoading(false);
    }
  }, []);

  // SSE connection for real-time updates
  useEffect(() => {
    // Initial REST fetch
    fetchDevices();

    // Connect SSE
    const connectSSE = () => {
      const es = new EventSource("/api/devices/events");
      eventSourceRef.current = es;

      es.onopen = () => {
        setSseConnected(true);
      };

      es.addEventListener("heartbeat", (event) => {
        try {
          const data: SSEHeartbeatEvent = JSON.parse(event.data);
          setDevices(data.devices);
          setLastRefresh(new Date());
        } catch {
          // Ignore parse errors
        }
      });

      es.addEventListener("device_online", (event) => {
        try {
          const data: SSEDeviceEvent = JSON.parse(event.data);
          setDevices((prev) => {
            const exists = prev.find((d) => d.id === data.device.id);
            if (exists) {
              return prev.map((d) => (d.id === data.device.id ? data.device : d));
            }
            return [data.device, ...prev];
          });
          showNotification(`New device detected: ${data.device.name}`);
        } catch {
          // Ignore parse errors
        }
      });

      es.addEventListener("device_offline", (event) => {
        try {
          const data: SSEDeviceEvent = JSON.parse(event.data);
          setDevices((prev) =>
            prev.map((d) => (d.id === data.device.id ? data.device : d))
          );
        } catch {
          // Ignore parse errors
        }
      });

      es.addEventListener("device_updated", (event) => {
        try {
          const data: SSEDeviceEvent = JSON.parse(event.data);
          setDevices((prev) =>
            prev.map((d) => (d.id === data.device.id ? data.device : d))
          );
          setLastRefresh(new Date());
        } catch {
          // Ignore parse errors
        }
      });

      es.onerror = () => {
        setSseConnected(false);
        es.close();
        // Reconnect after 5 seconds
        setTimeout(connectSSE, 5000);
      };
    };

    connectSSE();

    return () => {
      if (eventSourceRef.current) {
        eventSourceRef.current.close();
        eventSourceRef.current = null;
      }
      if (notificationTimerRef.current) {
        clearTimeout(notificationTimerRef.current);
      }
    };
  }, [fetchDevices, showNotification]);

  const fetchConnectStatus = useCallback(async () => {
    try {
      const res = await fetch("/api/stripe/connect/status");
      if (!res.ok) return;
      const data: ConnectStatus = await res.json();
      setConnectStatus(data);
    } catch {
      // Non-blocking; status is optional
    }
  }, []);

  const fetchCreditsBalance = useCallback(async () => {
    setCreditsLoading(true);
    try {
      const res = await fetch("/api/dashboard/marketplace/credits");
      if (!res.ok) return;
      const data: CreditsBalance = await res.json();
      setCreditsBalance(data);
    } catch {
      // Non-blocking
    } finally {
      setCreditsLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchConnectStatus();
  }, [fetchConnectStatus]);

  useEffect(() => {
    fetchCreditsBalance();
  }, [fetchCreditsBalance]);

  // Refetch Connect status when returning from Stripe onboarding
  useEffect(() => {
    const params = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
    if (params?.get("connect") === "return" || params?.get("connect") === "refresh") {
      fetchConnectStatus();
    }
  }, [fetchConnectStatus]);

  // Refetch credits when returning from Stripe credits purchase
  useEffect(() => {
    const params = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
    if (params?.get("credits") === "success" || params?.get("credits") === "cancelled") {
      fetchCreditsBalance();
      if (typeof window !== "undefined") {
        window.history.replaceState({}, "", window.location.pathname);
      }
    }
  }, [fetchCreditsBalance]);

  const purchaseCredits = useCallback(async (amountCents: number) => {
    setCreditsPurchaseLoading(amountCents);
    try {
      const res = await fetch("/api/marketplace/credits/purchase", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ amount_cents: amountCents }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Failed to start checkout");
      if (data.url) window.location.href = data.url;
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to add credits");
    } finally {
      setCreditsPurchaseLoading(null);
    }
  }, []);

  const startConnectOnboard = useCallback(async () => {
    setConnectLoading(true);
    try {
      const res = await fetch("/api/stripe/connect/onboard", { method: "POST" });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Failed to start onboarding");
      if (data.url) window.location.href = data.url;
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to start Connect");
    } finally {
      setConnectLoading(false);
    }
  }, []);

  const openConnectDashboard = useCallback(async () => {
    setConnectLoading(true);
    try {
      const res = await fetch("/api/stripe/connect/login-link", { method: "POST" });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Failed to open dashboard");
      if (data.url) window.location.href = data.url;
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to open dashboard");
    } finally {
      setConnectLoading(false);
    }
  }, []);

  const patchDevice = useCallback(
    async (
      id: string,
      payload: {
        marketplace_enabled?: boolean;
        price_cents_per_hour?: number | null;
        operator_agreement_accepted?: boolean;
      }
    ) => {
      const res = await fetch(`/api/dashboard/devices/${id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        if (res.status === 400 && data.code === "OPERATOR_AGREEMENT_REQUIRED") {
          setPendingEnableDeviceId(id);
          setAgreementChecked(false);
        }
        throw new Error(data.error ?? "Failed to update device");
      }
      const updated = (await res.json()) as {
        id: string;
        marketplace_enabled?: boolean;
        price_cents_per_hour?: number | null;
      };
      setDevices((prev) =>
        prev.map((d) =>
          d.id === id
            ? {
                ...d,
                marketplace_enabled:
                  updated.marketplace_enabled ?? d.marketplace_enabled,
                price_cents_per_hour:
                  updated.price_cents_per_hour !== undefined
                    ? updated.price_cents_per_hour
                    : d.price_cents_per_hour,
              }
            : d
        )
      );
    },
    []
  );

  const getStatusIcon = (status: string) => {
    switch (status) {
      case "online":
        return <CheckCircle size={16} className="text-green-400" />;
      case "offline":
        return <XCircle size={16} className="text-red-400" />;
      default:
        return <AlertCircle size={16} className="text-yellow-400" />;
    }
  };

  const formatLastSeen = (iso: string) => {
    const d = new Date(iso);
    const now = new Date();
    const diffMs = now.getTime() - d.getTime();
    if (diffMs < 60_000) return "Just now";
    if (diffMs < 3600_000) return `${Math.floor(diffMs / 60_000)}m ago`;
    if (diffMs < 86400_000) return `${Math.floor(diffMs / 3600_000)}h ago`;
    return d.toLocaleDateString();
  };

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold text-gray-100">Devices</h1>
          <p className="mt-1 text-sm text-gray-400">
            Nodes registered via <code className="rounded bg-gray-800 px-1.5 py-0.5 text-xs">llmhosts up</code> (tunnel + device code)
          </p>
          <p className="mt-1 text-xs text-gray-500">
            We discover and use your existing stacks — you&apos;re in control. Value is based on your real usage, not speculation.
          </p>
        </div>
        <div className="flex items-center gap-3">
          {/* SSE connection indicator */}
          <span
            className={`flex items-center gap-1.5 text-xs ${
              sseConnected ? "text-green-500" : "text-gray-600"
            }`}
            title={sseConnected ? "Live updates active" : "Reconnecting..."}
          >
            <span
              className={`inline-block h-1.5 w-1.5 rounded-full ${
                sseConnected ? "bg-green-500 animate-pulse" : "bg-gray-600"
              }`}
            />
            {sseConnected ? "Live" : "Offline"}
          </span>
          {lastRefresh && (
            <span className="text-xs text-gray-500">
              Updated {lastRefresh.toLocaleTimeString()}
            </span>
          )}
          <Link href="/dashboard/devices/operator">
            <Button variant="secondary" size="sm">
              <Settings size={16} className="mr-2" />
              Operator Settings
            </Button>
          </Link>
          <Button
            variant="secondary"
            size="sm"
            onClick={fetchDevices}
            disabled={loading}
          >
            <RefreshCw
              size={16}
              className={`mr-2 ${loading ? "animate-spin" : ""}`}
            />
            Refresh
          </Button>
        </div>
      </div>

      {/* Notification toast */}
      {notification && (
        <div className="animate-in slide-in-from-top-2 rounded-lg border border-green-800/50 bg-green-900/20 p-3">
          <p className="flex items-center gap-2 text-sm text-green-400">
            <Zap size={14} />
            {notification}
          </p>
        </div>
      )}

      {error && (
        <div className="rounded-lg border border-yellow-800/50 bg-yellow-900/20 p-4">
          <p className="text-sm text-yellow-400">{error}</p>
        </div>
      )}

      <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
        <div className="rounded-lg border border-gray-800 bg-gray-900 p-4">
          <div className="flex items-center gap-3">
            <div className="rounded-lg bg-indigo-500/10 p-2">
              <Smartphone size={20} className="text-indigo-400" />
            </div>
            <div>
              <p className="text-2xl font-bold text-gray-100">{devices.length}</p>
              <p className="text-xs text-gray-400">Registered</p>
            </div>
          </div>
        </div>
        <div className="rounded-lg border border-gray-800 bg-gray-900 p-4">
          <div className="flex items-center gap-3">
            <div className="rounded-lg bg-green-500/10 p-2">
              <Cpu size={20} className="text-green-400" />
            </div>
            <div>
              <p className="text-2xl font-bold text-gray-100">
                {devices.reduce((sum, d) => sum + d.models.length, 0)}
              </p>
              <p className="text-xs text-gray-400">Total Models</p>
            </div>
          </div>
        </div>
        <div className="rounded-lg border border-gray-800 bg-gray-900 p-4">
          <div className="flex items-center gap-3">
            <div className="rounded-lg bg-cyan-500/10 p-2">
              <Link2 size={20} className="text-cyan-400" />
            </div>
            <div>
              <p className="text-2xl font-bold text-gray-100">
                {devices.filter((d) => d.status === "online").length}
              </p>
              <p className="text-xs text-gray-400">Online</p>
            </div>
          </div>
        </div>
        <div className="rounded-lg border border-gray-800 bg-gray-900 p-4">
          <div className="flex items-center gap-3">
            <div className="rounded-lg bg-emerald-500/10 p-2">
              <DollarSign size={20} className="text-emerald-400" />
            </div>
            <div>
              <p className="text-2xl font-bold text-gray-100">
                ${devices.reduce((sum, d) => sum + (d.savings_usd || 0), 0).toFixed(2)}
              </p>
              <p className="text-xs text-gray-400">Session savings</p>
            </div>
          </div>
        </div>
      </div>

      {/* Buyer: Prepaid credits balance + Add credits */}
      <div className="rounded-lg border border-gray-800 bg-gray-900 p-4">
        <div className="flex flex-wrap items-center justify-between gap-4">
          <div className="flex items-center gap-3">
            <div className="rounded-lg bg-amber-500/10 p-2">
              <Wallet size={20} className="text-amber-400" />
            </div>
            <div>
              <h3 className="font-semibold text-gray-100">Credits balance</h3>
              <p className="text-sm text-gray-400">
                Prepaid credits for using marketplace (remote) devices.
              </p>
              <p className="mt-1 text-2xl font-bold text-gray-100">
                {creditsLoading
                  ? "..."
                  : `$${((creditsBalance?.balance_cents ?? 0) / 100).toFixed(2)}`}
              </p>
            </div>
          </div>
          <div className="flex flex-wrap items-center gap-2">
            <span className="text-sm text-gray-500">Add credits:</span>
            {CREDIT_AMOUNTS.map(({ label, cents }) => (
              <Button
                key={cents}
                variant="secondary"
                size="sm"
                onClick={() => purchaseCredits(cents)}
                disabled={creditsPurchaseLoading !== null}
              >
                {creditsPurchaseLoading === cents ? (
                  <RefreshCw size={14} className="mr-2 animate-spin" />
                ) : null}
                {label}
              </Button>
            ))}
          </div>
        </div>
      </div>

      {/* Payouts -- Stripe Connect Express */}
      <div className="rounded-lg border border-gray-800 bg-gray-900 p-4">
        <div className="flex flex-wrap items-center justify-between gap-4">
          <div className="flex items-center gap-3">
            <div className="rounded-lg bg-emerald-500/10 p-2">
              <Wallet size={20} className="text-emerald-400" />
            </div>
            <div>
              <h3 className="font-semibold text-gray-100">Receive payouts</h3>
              <p className="text-sm text-gray-400">
                Connect a Stripe Express account to get paid for marketplace usage.
              </p>
            </div>
          </div>
          <div className="flex items-center gap-2">
            {connectStatus?.connected ? (
              <>
                <span className="flex items-center gap-1.5 rounded-full bg-emerald-500/20 px-3 py-1.5 text-sm text-emerald-400">
                  <CheckCircle size={14} />
                  Stripe connected
                </span>
                <Button
                  variant="secondary"
                  size="sm"
                  onClick={openConnectDashboard}
                  disabled={connectLoading}
                >
                  <ExternalLink size={14} className="mr-2" />
                  Dashboard
                </Button>
              </>
            ) : (
              <Button
                variant="primary"
                size="sm"
                onClick={startConnectOnboard}
                disabled={connectLoading}
              >
                {connectLoading ? (
                  <RefreshCw size={14} className="mr-2 animate-spin" />
                ) : (
                  <Wallet size={14} className="mr-2" />
                )}
                Connect Stripe to receive payouts
              </Button>
            )}
          </div>
        </div>
      </div>

      {loading && devices.length === 0 ? (
        <div className="flex justify-center py-12">
          <RefreshCw size={24} className="animate-spin text-gray-500" />
          <span className="ml-3 text-gray-500">Loading devices...</span>
        </div>
      ) : devices.length === 0 ? (
        <div className="rounded-lg border border-gray-800 bg-gray-900 p-8 text-center">
          <Smartphone size={48} className="mx-auto mb-4 text-gray-500" />
          <h3 className="text-lg font-medium text-gray-300">Connect your first GPU</h3>
          <p className="mt-2 text-sm text-gray-400">
            Run this command on any machine with a GPU to connect it in 90 seconds.
          </p>
          <div className="mx-auto mt-4 max-w-md rounded bg-gray-800 px-4 py-3">
            <code className="text-sm text-gray-200 select-all">pip install llmhosts && llmhosts up</code>
          </div>
          <p className="mt-4 text-xs text-gray-500">
            The CLI auto-discovers your GPU, starts the inference engine, and registers via device code flow.
          </p>
        </div>
      ) : (
        <div className="space-y-3">
          {devices.map((d) => (
            <div
              key={d.id}
              className="rounded-lg border border-gray-800 bg-gray-900 p-4 transition-colors hover:border-gray-700"
            >
              <div className="flex items-start justify-between">
                <div className="flex items-center gap-3">
                  {getStatusIcon(d.status)}
                  <div>
                    <h3 className="font-semibold text-gray-100">{d.name}</h3>
                    <p className="text-sm text-gray-400 truncate max-w-md" title={d.tunnel_url}>
                      {d.tunnel_url}
                    </p>
                  </div>
                </div>
                <div className="flex items-center gap-4 text-sm">
                  {d.latency_ms != null && (
                    <div className="flex items-center gap-1.5 text-gray-400">
                      <Clock size={14} />
                      <span className="text-gray-400">{d.latency_ms}ms</span>
                    </div>
                  )}
                  <span className="text-gray-500">
                    {formatLastSeen(d.last_seen)}
                  </span>
                </div>
              </div>

              {/* Enhanced device details */}
              <div className="mt-3 grid grid-cols-2 gap-3 sm:grid-cols-4">
                {/* VRAM usage */}
                <div className="flex items-center gap-2">
                  <HardDrive size={14} className="text-purple-400" />
                  <div className="flex-1 min-w-0">
                    <p className="text-xs text-gray-500">VRAM</p>
                    <p className="text-sm font-medium text-gray-200">
                      {formatVram(d.vram_usage_mb)}
                    </p>
                  </div>
                </div>

                {/* Active model */}
                <div className="flex items-center gap-2">
                  <Activity size={14} className="text-cyan-400" />
                  <div className="flex-1 min-w-0">
                    <p className="text-xs text-gray-500">Active model</p>
                    {d.active_model ? (
                      <span className="inline-block rounded bg-cyan-900/30 px-1.5 py-0.5 text-xs font-medium text-cyan-300">
                        {d.active_model}
                      </span>
                    ) : (
                      <p className="text-sm text-gray-500">None</p>
                    )}
                  </div>
                </div>

                {/* Requests served */}
                <div className="flex items-center gap-2">
                  <Zap size={14} className="text-amber-400" />
                  <div className="flex-1 min-w-0">
                    <p className="text-xs text-gray-500">Requests</p>
                    <p className="text-sm font-medium text-gray-200">
                      {d.requests_served.toLocaleString()}
                    </p>
                  </div>
                </div>

                {/* Uptime */}
                <div className="flex items-center gap-2">
                  <Timer size={14} className="text-green-400" />
                  <div className="flex-1 min-w-0">
                    <p className="text-xs text-gray-500">Uptime</p>
                    <p className="text-sm font-medium text-gray-200">
                      {d.uptime_seconds > 0 ? formatUptime(d.uptime_seconds) : "N/A"}
                    </p>
                  </div>
                </div>
              </div>

              {d.models.length > 0 && (
                <div className="mt-3 flex flex-wrap gap-1.5">
                  {d.models.slice(0, 8).map((m) => (
                    <span
                      key={m}
                      className={`rounded-full px-2.5 py-0.5 text-xs ${
                        m === d.active_model
                          ? "bg-cyan-900/40 text-cyan-300 ring-1 ring-cyan-700/50"
                          : "bg-gray-800 text-gray-300"
                      }`}
                    >
                      {m}
                    </span>
                  ))}
                  {d.models.length > 8 && (
                    <span className="rounded-full bg-gray-800 px-2.5 py-0.5 text-xs text-gray-500">
                      +{d.models.length - 8} more
                    </span>
                  )}
                </div>
              )}

              <div className="mt-3 border-t border-gray-800 pt-3">
                <div className="flex flex-wrap items-center gap-4">
                  <div className="flex items-center gap-3">
                    <Store size={14} className="text-gray-500" />
                    <span className="text-sm text-gray-400">
                      List on marketplace
                    </span>
                    <button
                      type="button"
                      role="switch"
                      aria-checked={d.marketplace_enabled ?? false}
                      onClick={() => {
                        const enabling = !(d.marketplace_enabled ?? false);
                        if (enabling) {
                          setPendingEnableDeviceId(d.id);
                          setAgreementChecked(false);
                        } else {
                          patchDevice(d.id, {
                            marketplace_enabled: false,
                          });
                        }
                      }}
                      className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors ${
                        d.marketplace_enabled ? "bg-indigo-500" : "bg-gray-700"
                      }`}
                    >
                      <span
                        className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                          d.marketplace_enabled
                            ? "translate-x-6"
                            : "translate-x-1"
                        }`}
                      />
                    </button>
                    <span className="text-xs text-gray-500">
                      By listing you agree to the{" "}
                      <a
                        href="/legal/operator-agreement.md"
                        target="_blank"
                        rel="noopener noreferrer"
                        className="text-indigo-400 hover:underline"
                      >
                        Operator Agreement
                      </a>
                      .
                    </span>
                  </div>
                  {pendingEnableDeviceId === d.id && (
                    <div className="w-full rounded-lg border border-indigo-800/50 bg-indigo-900/20 p-3 mt-2">
                      <label className="flex items-start gap-2 cursor-pointer">
                        <input
                          type="checkbox"
                          checked={agreementChecked}
                          onChange={(e) =>
                            setAgreementChecked(e.target.checked)
                          }
                          className="mt-1 rounded border-gray-600 bg-gray-800 text-indigo-500 focus:ring-indigo-500"
                          aria-describedby={`operator-agreement-desc-${d.id}`}
                        />
                        <span id={`operator-agreement-desc-${d.id}`} className="text-sm text-gray-300">
                          I agree to the{" "}
                          <a
                            href="/legal/operator-agreement.md"
                            target="_blank"
                            rel="noopener noreferrer"
                            className="text-indigo-400 hover:underline"
                          >
                            Operator Agreement
                          </a>
                          .
                        </span>
                      </label>
                      <div className="flex gap-2 mt-3">
                        <Button
                          variant="secondary"
                          size="sm"
                          onClick={() => {
                            setPendingEnableDeviceId(null);
                            setAgreementChecked(false);
                          }}
                        >
                          Cancel
                        </Button>
                        <Button
                          variant="primary"
                          size="sm"
                          disabled={!agreementChecked}
                          onClick={async () => {
                            if (!agreementChecked) return;
                            try {
                              await patchDevice(d.id, {
                                marketplace_enabled: true,
                                operator_agreement_accepted: true,
                              });
                              setPendingEnableDeviceId(null);
                              setAgreementChecked(false);
                            } catch (err) {
                              setError(err instanceof Error ? err.message : "Failed to update device");
                            }
                          }}
                        >
                          Enable listing
                        </Button>
                      </div>
                    </div>
                  )}
                  {d.marketplace_enabled && (
                    <div className="flex items-center gap-2">
                      <div className="w-32">
                        <Input
                          type="number"
                          min={0}
                          step={1}
                          placeholder="cents"
                          aria-label="Price per GPU-hour in cents"
                          value={
                            d.price_cents_per_hour != null
                              ? String(d.price_cents_per_hour)
                              : ""
                          }
                          onBlur={(e) => {
                            const raw = e.target.value.trim();
                            const cents =
                              raw === ""
                                ? null
                                : Math.max(
                                    0,
                                    Math.round(Number(raw)) || 0
                                  );
                            if (
                              cents !== d.price_cents_per_hour &&
                              (cents !== null || d.price_cents_per_hour != null)
                            ) {
                              patchDevice(d.id, {
                                price_cents_per_hour: cents,
                              });
                            }
                          }}
                          onChange={(e) => {
                            const raw = e.target.value;
                            const num = raw === "" ? null : Number(raw);
                            setDevices((prev) =>
                              prev.map((dev) =>
                                dev.id === d.id
                                  ? {
                                      ...dev,
                                      price_cents_per_hour:
                                        raw === ""
                                          ? null
                                          : Math.max(
                                              0,
                                              Math.round(num ?? 0)
                                            ),
                                    }
                                  : dev
                              )
                            );
                          }}
                          className="bg-gray-800 text-gray-100"
                        />
                      </div>
                      <span className="text-xs text-gray-500">
                        =
                        {d.price_cents_per_hour != null
                          ? ` $${(d.price_cents_per_hour / 100).toFixed(2)}/hr`
                          : " $0.00/hr"}
                      </span>
                    </div>
                  )}
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
