"use client";

import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useParams, useRouter } from "next/navigation";
import Link from "next/link";
import { api, ServerStatus, GenerateKeyOptions, PackageUpdate, Inventory } from "@/lib/api";
import { Badge, Button, Card, CardHeader, CardTitle } from "@/components/ui";
import { Table, Thead, Tbody, Tr, Th, Td } from "@/components/ui";
import { useLicense } from "@/lib/useLicense";

function statusVariant(status: ServerStatus) {
    switch (status) {
        case "active":
            return "success";
        case "pending":
            return "warning";
        case "offline":
            return "danger";
    }
}

function formatDate(dateStr: string) {
    return new Date(dateStr).toLocaleString();
}

function formatBytes(n: number): string {
    if (!n) return "0 B";
    const u = ["B", "KB", "MB", "GB", "TB"];
    const i = Math.floor(Math.log(n) / Math.log(1024));
    return `${(n / Math.pow(1024, i)).toFixed(1)} ${u[i]}`;
}

function UsageBar({ used, total }: { used: number; total: number }) {
    const pct = total > 0 ? Math.min(100, (used / total) * 100) : 0;
    return (
        <div className="h-2 w-full overflow-hidden rounded-full bg-surface-2">
            <div className={`h-full rounded-full ${pct > 90 ? "bg-danger" : "bg-accent"}`} style={{ width: `${pct}%` }} />
        </div>
    );
}

function InventoryPanel({ inv }: { inv: Inventory }) {
    return (
        <Card>
            <h2 className="mb-4 text-lg font-semibold text-text-primary">Inventory</h2>
            <div className="grid gap-4 sm:grid-cols-2">
                <div>
                    <div className="mb-1 flex justify-between text-sm">
                        <span className="text-text-secondary">CPU</span>
                        <span className="text-text-primary">{inv.cpu.usage_pct.toFixed(0)}%</span>
                    </div>
                    <UsageBar used={inv.cpu.usage_pct} total={100} />
                    <p className="mt-1 text-xs text-text-secondary">
                        {inv.cpu.model} · {inv.cpu.cores} cores · load {inv.cpu.load1?.toFixed(2)}
                    </p>
                </div>
                <div>
                    <div className="mb-1 flex justify-between text-sm">
                        <span className="text-text-secondary">Memory</span>
                        <span className="text-text-primary">
                            {formatBytes(inv.memory.used_bytes)} / {formatBytes(inv.memory.total_bytes)}
                        </span>
                    </div>
                    <UsageBar used={inv.memory.used_bytes} total={inv.memory.total_bytes} />
                    <div className="mb-1 mt-3 flex justify-between text-sm">
                        <span className="text-text-secondary">Swap</span>
                        <span className="text-text-primary">
                            {formatBytes(inv.swap_used_bytes)} / {formatBytes(inv.swap_total_bytes)}
                        </span>
                    </div>
                    <UsageBar used={inv.swap_used_bytes} total={inv.swap_total_bytes} />
                </div>
            </div>
            {inv.partitions && inv.partitions.length > 0 && (
                <div className="mt-5">
                    <h3 className="mb-2 text-sm font-medium text-text-secondary">Partitions</h3>
                    <div className="space-y-3">
                        {inv.partitions.map((p) => (
                            <div key={p.mountpoint}>
                                <div className="mb-1 flex justify-between text-xs">
                                    <span className="font-mono text-text-primary">{p.mountpoint}</span>
                                    <span className="text-text-secondary">
                                        {formatBytes(p.used_bytes)} / {formatBytes(p.total_bytes)} · {p.fstype}
                                    </span>
                                </div>
                                <UsageBar used={p.used_bytes} total={p.total_bytes} />
                            </div>
                        ))}
                    </div>
                </div>
            )}
            {inv.kernel && <p className="mt-4 text-xs text-text-secondary">Kernel {inv.kernel}</p>}
        </Card>
    );
}

const KEY_SIZES: Record<string, number[]> = {
    rsa: [2048, 3072, 4096],
    ecdsa: [256, 384, 521],
};

const DEFAULT_SIZE: Record<string, number> = {
    rsa: 4096,
    ecdsa: 256,
};

function GenerateKeyModal({ onClose, onSubmit, isPending }: { onClose: () => void; onSubmit: (opts: GenerateKeyOptions) => void; isPending: boolean }) {
    const [label, setLabel] = useState("");
    const [keyType, setKeyType] = useState<"ed25519" | "rsa" | "ecdsa">("ed25519");
    const [keySize, setKeySize] = useState<number>(4096);
    const [passphrase, setPassphrase] = useState("");
    const [comment, setComment] = useState("");

    function handleKeyTypeChange(t: "ed25519" | "rsa" | "ecdsa") {
        setKeyType(t);
        if (t !== "ed25519") {
            setKeySize(DEFAULT_SIZE[t]);
        }
    }

    function handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        onSubmit({
            label: label || "generated",
            key_type: keyType,
            key_size: keyType !== "ed25519" ? keySize : undefined,
            passphrase: passphrase || undefined,
            comment: comment || undefined,
        });
    }

    const sizes = KEY_SIZES[keyType];

    return (
        <div className="fixed inset-0 z-50 flex items-center justify-center">
            <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={onClose} />
            <div className="relative z-10 w-full max-w-md rounded-xl border border-border bg-surface-1 p-6 shadow-2xl">
                <div className="mb-5 flex items-center justify-between">
                    <h2 className="text-lg font-semibold text-text-primary">Generate SSH Key</h2>
                    <button onClick={onClose} className="rounded-md p-1 text-text-secondary hover:text-text-primary transition-colors">
                        <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                            <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                    </button>
                </div>

                <form onSubmit={handleSubmit} className="space-y-4">
                    <div>
                        <label className="mb-1.5 block text-sm font-medium text-text-secondary">
                            Label <span className="text-text-tertiary">(used as the key name in Vantage)</span>
                        </label>
                        <input
                            type="text"
                            value={label}
                            onChange={(e) => setLabel(e.target.value)}
                            placeholder="e.g. server-deploy-key"
                            className="w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:border-accent/50 focus:outline-none focus:ring-1 focus:ring-accent/30"
                        />
                    </div>

                    <div>
                        <label className="mb-1.5 block text-sm font-medium text-text-secondary">Key Type</label>
                        <div className="grid grid-cols-3 gap-2">
                            {(["ed25519", "rsa", "ecdsa"] as const).map((t) => (
                                <button
                                    key={t}
                                    type="button"
                                    onClick={() => handleKeyTypeChange(t)}
                                    className={`rounded-lg border px-3 py-2 text-sm font-medium transition-colors ${
                                        keyType === t ? "border-accent bg-accent/10 text-accent" : "border-border bg-surface-2 text-text-secondary hover:border-accent/40 hover:text-text-primary"
                                    }`}
                                >
                                    {t}
                                </button>
                            ))}
                        </div>
                        {keyType === "ed25519" && <p className="mt-1.5 text-xs text-text-tertiary">Modern, fast, and secure. Recommended for new keys.</p>}
                        {keyType === "rsa" && <p className="mt-1.5 text-xs text-text-tertiary">Widely compatible with older systems.</p>}
                        {keyType === "ecdsa" && <p className="mt-1.5 text-xs text-text-tertiary">Elliptic curve shorter keys, good compatibility.</p>}
                    </div>

                    {sizes && (
                        <div>
                            <label className="mb-1.5 block text-sm font-medium text-text-secondary">Key Size (bits)</label>
                            <select
                                value={keySize}
                                onChange={(e) => setKeySize(Number(e.target.value))}
                                className="w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary focus:border-accent/50 focus:outline-none focus:ring-1 focus:ring-accent/30"
                            >
                                {sizes.map((s) => (
                                    <option key={s} value={s}>
                                        {s}
                                    </option>
                                ))}
                            </select>
                        </div>
                    )}

                    <div>
                        <label className="mb-1.5 block text-sm font-medium text-text-secondary">
                            Comment <span className="text-text-tertiary">(embedded in the public key)</span>
                        </label>
                        <input
                            type="text"
                            value={comment}
                            onChange={(e) => setComment(e.target.value)}
                            placeholder="e.g. user@hostname"
                            className="w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:border-accent/50 focus:outline-none focus:ring-1 focus:ring-accent/30"
                        />
                    </div>

                    <div>
                        <label className="mb-1.5 block text-sm font-medium text-text-secondary">
                            Passphrase <span className="text-text-tertiary">(leave blank for no passphrase)</span>
                        </label>
                        <input
                            type="password"
                            value={passphrase}
                            onChange={(e) => setPassphrase(e.target.value)}
                            placeholder="Optional passphrase"
                            autoComplete="new-password"
                            className="w-full rounded-lg border border-border bg-surface-2 px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:border-accent/50 focus:outline-none focus:ring-1 focus:ring-accent/30"
                        />
                    </div>

                    <div className="flex gap-3 pt-1">
                        <Button type="submit" variant="primary" loading={isPending} className="flex-1">
                            Generate Key
                        </Button>
                        <Button type="button" variant="ghost" onClick={onClose}>
                            Cancel
                        </Button>
                    </div>
                </form>
            </div>
        </div>
    );
}

function UpdatesModal({ updates, onClose, onApply, isApplying, applySuccess }: { updates: PackageUpdate[]; onClose: () => void; onApply: () => void; isApplying: boolean; applySuccess: boolean }) {
    return (
        <div className="fixed inset-0 z-50 flex items-center justify-center">
            <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" onClick={onClose} />
            <div className="relative z-10 w-full max-w-2xl rounded-xl border border-border bg-surface-1 p-6 shadow-2xl">
                <div className="mb-5 flex items-center justify-between">
                    <div>
                        <h2 className="text-lg font-semibold text-text-primary">Available OS Updates</h2>
                        <p className="mt-0.5 text-sm text-text-secondary">
                            {updates.length} package{updates.length !== 1 ? "s" : ""} available
                        </p>
                    </div>
                    <button onClick={onClose} className="rounded-md p-1 text-text-secondary hover:text-text-primary transition-colors">
                        <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                            <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                    </button>
                </div>

                <div className="max-h-80 overflow-y-auto rounded-lg border border-border">
                    <Table>
                        <Thead>
                            <Tr>
                                <Th>Package</Th>
                                <Th>Current</Th>
                                <Th>Available</Th>
                            </Tr>
                        </Thead>
                        <Tbody>
                            {updates.map((u) => (
                                <Tr key={u.name}>
                                    <Td>
                                        <span className="font-medium font-mono text-sm">{u.name}</span>
                                    </Td>
                                    <Td>
                                        <span className="font-mono text-xs text-text-secondary">{u.current_version || "n/a"}</span>
                                    </Td>
                                    <Td>
                                        <span className="font-mono text-xs text-success">{u.new_version}</span>
                                    </Td>
                                </Tr>
                            ))}
                        </Tbody>
                    </Table>
                </div>

                <div className="mt-5 flex items-center gap-3">
                    <Button variant="primary" loading={isApplying} onClick={onApply}>
                        {applySuccess ? "Sent!" : "Apply Updates"}
                    </Button>
                    <Button variant="ghost" onClick={onClose}>
                        Close
                    </Button>
                    <p className="ml-auto text-xs text-text-tertiary">Upgrade runs in the background. This may take several minutes.</p>
                </div>
            </div>
        </div>
    );
}
export default function ServerDetailPage() {
    const params = useParams();
    const router = useRouter();
    const queryClient = useQueryClient();
    const serverId = params.id as string;
    const [confirmDelete, setConfirmDelete] = useState(false);
    const [showGenerateModal, setShowGenerateModal] = useState(false);
    const [copiedUpdate, setCopiedUpdate] = useState(false);
    const [updateSuccess, setUpdateSuccess] = useState(false);
    const [showUpdatesModal, setShowUpdatesModal] = useState(false);
    const [applySuccess, setApplySuccess] = useState(false);
    const { hasFeature } = useLicense();
    const consoleAllowed = hasFeature("console");

    const {
        data: server,
        isLoading,
        error,
    } = useQuery({
        queryKey: ["servers", serverId],
        queryFn: () => api.getServer(serverId),
        refetchInterval: 30_000,
    });

    const { mutate: generateKey, isPending: isGenerating } = useMutation({
        mutationFn: (opts: GenerateKeyOptions) => api.generateKeyForServer(serverId, opts),
        onSuccess: () => {
            setShowGenerateModal(false);
            queryClient.invalidateQueries({ queryKey: ["servers", serverId] });
            queryClient.invalidateQueries({ queryKey: ["keys"] });
        },
    });

    const { data: latestVersion } = useQuery({
        queryKey: ["agent-latest-version"],
        queryFn: () => api.getLatestAgentVersion(),
        staleTime: 5 * 60_000,
    });

    const { mutate: triggerUpdate, isPending: isUpdating } = useMutation({
        mutationFn: () => api.updateAgent(serverId),
        onSuccess: () => {
            setUpdateSuccess(true);
            setTimeout(() => setUpdateSuccess(false), 4000);
        },
    });

    const { mutate: applyUpdates, isPending: isApplying } = useMutation({
        mutationFn: () => api.applyUpdates(serverId),
        onSuccess: () => {
            setApplySuccess(true);
            setTimeout(() => {
                setApplySuccess(false);
                setShowUpdatesModal(false);
            }, 2000);
        },
    });
    const { mutate: deleteServer, isPending: isDeleting } = useMutation({
        mutationFn: () => api.deleteServer(serverId),
        onSuccess: () => {
            queryClient.invalidateQueries({ queryKey: ["servers"] });
            router.push("/servers");
        },
    });

    if (isLoading) {
        return (
            <div className="flex h-full items-center justify-center">
                <div className="h-8 w-8 animate-spin rounded-full border-2 border-border border-t-accent" />
            </div>
        );
    }

    if (error || !server) {
        return (
            <div className="p-8">
                <div className="rounded-lg border border-danger/30 bg-danger/10 p-4 text-danger">Server not found or failed to load.</div>
            </div>
        );
    }

    return (
        <div className="p-8">
            {showGenerateModal && <GenerateKeyModal onClose={() => setShowGenerateModal(false)} onSubmit={(opts) => generateKey(opts)} isPending={isGenerating} />}
            {showUpdatesModal && server.available_updates && (
                <UpdatesModal updates={server.available_updates} onClose={() => setShowUpdatesModal(false)} onApply={() => applyUpdates()} isApplying={isApplying} applySuccess={applySuccess} />
            )}

            <div className="mb-6 flex items-start justify-between">
                <div>
                    <div className="flex items-center gap-3">
                        <Link href="/servers" className="text-text-secondary hover:text-text-primary text-sm">
                            ← Servers
                        </Link>
                    </div>
                    <div className="mt-2 flex items-center gap-3">
                        <h1 className="text-2xl font-bold text-text-primary">{server.hostname}</h1>
                        <Badge variant={statusVariant(server.status)}>{server.status}</Badge>
                    </div>
                    <p className="mt-1 font-mono text-sm text-text-secondary">{server.ip_address}</p>
                </div>
                <div className="flex gap-2">
                    {/* Rendered disabled rather than hidden when the licence does not
                        include the console: a customer cannot buy what they cannot see,
                        and a feature that vanishes reads as a bug. */}
                    {server.console_protocols?.map((p) => (
                        <Link
                            key={p}
                            href={consoleAllowed ? `/servers/${serverId}/console?protocol=${p}` : "#"}
                            aria-disabled={!consoleAllowed}
                            title={consoleAllowed ? undefined : "Upgrade to use the browser console"}
                            onClick={(e) => {
                                if (!consoleAllowed) e.preventDefault();
                            }}
                            className={consoleAllowed ? undefined : "pointer-events-none opacity-50"}
                        >
                            <Button variant="secondary" disabled={!consoleAllowed}>
                                <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                                    <path
                                        strokeLinecap="round"
                                        strokeLinejoin="round"
                                        d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25m18 0A2.25 2.25 0 0018.75 3H5.25A2.25 2.25 0 003 5.25m18 0V12a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 12V5.25"
                                    />
                                </svg>
                                Connect {p.toUpperCase()}
                            </Button>
                        </Link>
                    ))}
                    {server.available_updates && server.available_updates.length > 0 && (
                        <Button variant="secondary" onClick={() => setShowUpdatesModal(true)} className="border-warning/50 text-warning hover:border-warning hover:bg-warning/10">
                            <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                                <path
                                    strokeLinecap="round"
                                    strokeLinejoin="round"
                                    d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
                                />
                            </svg>
                            {server.available_updates.length} OS Update{server.available_updates.length !== 1 ? "s" : ""}
                        </Button>
                    )}
                    <Button variant="secondary" onClick={() => setShowGenerateModal(true)}>
                        <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                            <path
                                strokeLinecap="round"
                                strokeLinejoin="round"
                                d="M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1121.75 8.25z"
                            />
                        </svg>
                        Generate SSH Key
                    </Button>
                    {!confirmDelete ? (
                        <Button variant="danger" onClick={() => setConfirmDelete(true)}>
                            Remove Server
                        </Button>
                    ) : (
                        <div className="flex items-center gap-2">
                            <span className="text-sm text-danger">Are you sure?</span>
                            <Button variant="danger" loading={isDeleting} onClick={() => deleteServer()}>
                                Confirm
                            </Button>
                            <Button variant="ghost" onClick={() => setConfirmDelete(false)}>
                                Cancel
                            </Button>
                        </div>
                    )}
                </div>
            </div>

            <div className="mb-6">
                <Card>
                    <CardHeader>
                        <CardTitle>Update Agent</CardTitle>
                    </CardHeader>
                    <div className="mb-4 flex flex-wrap items-center gap-4 text-sm">
                        <div>
                            <span className="text-text-secondary">Installed: </span>
                            <span className="font-mono font-medium text-text-primary">{server.agent_version ? `v${server.agent_version}` : "unknown"}</span>
                        </div>
                        <div>
                            <span className="text-text-secondary">Latest: </span>
                            <span className="font-mono font-medium text-text-primary">{latestVersion ? `v${latestVersion.version}` : "n/a"}</span>
                        </div>
                        {latestVersion && server.agent_version && server.agent_version !== latestVersion.version && <Badge variant="warning">update available</Badge>}
                        {latestVersion && server.agent_version && server.agent_version === latestVersion.version && <Badge variant="success">up to date</Badge>}
                    </div>
                    <div className="flex flex-wrap gap-3">
                        <Button
                            variant="primary"
                            loading={isUpdating}
                            onClick={() => triggerUpdate()}
                            disabled={server.status !== "active"}
                            title={server.status !== "active" ? "Agent must be online to update" : undefined}
                        >
                            {updateSuccess ? "Update Sent!" : "Update Agent"}
                        </Button>
                        <div className="relative flex-1 min-w-64 rounded-lg border border-border bg-[#0a0c14] px-4 py-2.5 font-mono text-sm">
                            <span className="text-accent">{server.os_info?.toLowerCase().includes("windows") ? "PS>" : "$"}</span>{" "}
                            <span className="text-text-primary">{api.getUpdateCommand(server.os_info)}</span>
                            <button
                                onClick={async () => {
                                    await navigator.clipboard.writeText(api.getUpdateCommand(server.os_info));
                                    setCopiedUpdate(true);
                                    setTimeout(() => setCopiedUpdate(false), 2000);
                                }}
                                className="absolute right-2 top-1.5 rounded-md border border-border bg-surface-2 px-2 py-0.5 text-xs font-medium text-text-secondary transition-colors hover:border-accent/50 hover:text-text-primary"
                            >
                                {copiedUpdate ? <span className="text-success">Copied!</span> : "Copy"}
                            </button>
                        </div>
                    </div>
                </Card>
            </div>

            {server.inventory && (
                <div className="mb-6">
                    <InventoryPanel inv={server.inventory} />
                </div>
            )}

            <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
                <Card className="lg:col-span-1">
                    <CardHeader>
                        <CardTitle>Details</CardTitle>
                    </CardHeader>
                    <dl className="space-y-3 text-sm">
                        <div>
                            <dt className="text-text-secondary">Server ID</dt>
                            <dd className="mt-0.5 font-mono text-xs text-text-primary break-all">{server.server_id}</dd>
                        </div>
                        <div className="border-t border-border pt-3">
                            <dt className="text-text-secondary">OS</dt>
                            <dd className="mt-0.5 text-text-primary">{server.os_info}</dd>
                        </div>
                        <div className="border-t border-border pt-3">
                            <dt className="text-text-secondary">Agent Version</dt>
                            <dd className="mt-0.5 font-mono text-text-primary">{server.agent_version ? `v${server.agent_version}` : "unknown"}</dd>
                        </div>
                        <div className="border-t border-border pt-3">
                            <dt className="text-text-secondary">Last Seen</dt>
                            <dd className="mt-0.5 text-text-primary">{server.last_seen ? formatDate(server.last_seen) : "Never"}</dd>
                        </div>
                        <div className="border-t border-border pt-3">
                            <dt className="text-text-secondary">Registered</dt>
                            <dd className="mt-0.5 text-text-primary">{formatDate(server.created_at)}</dd>
                        </div>
                    </dl>
                </Card>

                <div className="lg:col-span-2">
                    <Card padding={false}>
                        <div className="flex items-center justify-between border-b border-border px-6 py-4">
                            <h2 className="text-lg font-semibold text-text-primary">
                                Installed SSH Keys
                                <span className="ml-2 rounded-full bg-surface-2 px-2 py-0.5 text-xs text-text-secondary">{server.keys?.filter((k) => !k.revoked_at).length ?? 0} active</span>
                            </h2>
                            <Link href="/keys">
                                <Button variant="ghost" size="sm">
                                    Manage Keys →
                                </Button>
                            </Link>
                        </div>

                        {!server.keys || server.keys.length === 0 ? (
                            <div className="py-16 text-center">
                                <p className="text-text-secondary text-sm">No keys assigned to this server.</p>
                                <Link href="/keys">
                                    <Button variant="secondary" size="sm" className="mt-3">
                                        Assign a key
                                    </Button>
                                </Link>
                            </div>
                        ) : (
                            <Table>
                                <Thead>
                                    <Tr>
                                        <Th>Label</Th>
                                        <Th>Fingerprint</Th>
                                        <Th>Source</Th>
                                        <Th>Status</Th>
                                        <Th>Assigned</Th>
                                        <Th />
                                    </Tr>
                                </Thead>
                                <Tbody>
                                    {server.keys
                                        .filter((a) => a.key)
                                        .map((assignment) => (
                                            <Tr key={assignment.key_id}>
                                                <Td>
                                                    <span className="font-medium">{assignment.key.label}</span>
                                                </Td>
                                                <Td>
                                                    <span className="font-mono text-xs text-text-secondary">{assignment.key.fingerprint}</span>
                                                </Td>
                                                <Td>
                                                    <Badge variant={assignment.key.source === "generated" ? "accent" : "neutral"}>{assignment.key.source}</Badge>
                                                </Td>
                                                <Td>
                                                    <Badge variant={assignment.revoked_at ? "danger" : "success"}>{assignment.revoked_at ? "revoked" : "active"}</Badge>
                                                </Td>
                                                <Td>
                                                    <span className="text-text-secondary text-xs">{formatDate(assignment.assigned_at)}</span>
                                                </Td>
                                                <Td>
                                                    <Link href={`/keys/${assignment.key_id}`}>
                                                        <Button variant="ghost" size="sm">
                                                            View
                                                        </Button>
                                                    </Link>
                                                </Td>
                                            </Tr>
                                        ))}
                                </Tbody>
                            </Table>
                        )}
                    </Card>
                </div>
            </div>
        </div>
    );
}
