// @File: frontend/src/pages/agent/SupportInbox.tsx
// @Desc: Support agent inbox. Lists conversations (unassigned / mine / all /
//        resolved), opens a thread view with AI summary, visitor context
//        sidebar (WHMCS services / invoices / domains), reply composer,
//        internal notes, handover / convert-to-ticket actions.
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { createClient } from "@metagptx/web-sdk";
import { useNavigate } from "react-router-dom";
import {
  Loader2,
  Send,
  Sparkles,
  TicketPlus,
  Users,
  Lock,
  RefreshCcw,
  AlertCircle,
  CheckCircle2,
  MessageSquare,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Badge } from "@/components/ui/badge";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { cn } from "@/lib/utils";

interface ConversationRow {
  id: number;
  visitor_name?: string;
  visitor_email?: string;
  status: string;
  priority: string;
  subject?: string;
  assigned_seat_id?: number | null;
  department_id?: number | null;
  last_message_at?: string | null;
  ai_summary?: string | null;
  linked_ticket_id?: number | null;
  whmcs_client_id?: number | null;
}

interface Message {
  id: number;
  sender_type: "visitor" | "ai" | "agent" | "system";
  sender_name?: string | null;
  content: string;
  is_internal_note?: boolean;
  ai_confidence?: number | null;
  created_at?: string | null;
}

interface WhmcsContext {
  client?: any;
  services: any[];
  invoices: any[];
  domains: any[];
}

interface Department {
  id: number;
  name: string;
  slug: string;
}

const SCOPES = [
  { value: "unassigned", label: "Queue" },
  { value: "mine", label: "My chats" },
  { value: "all", label: "All" },
  { value: "resolved", label: "Resolved" },
];

export default function SupportInbox() {
  const client = useMemo(() => createClient(), []);
  const navigate = useNavigate();
  const [authError, setAuthError] = useState<string | null>(null);
  const [scope, setScope] = useState("unassigned");
  const [list, setList] = useState<ConversationRow[]>([]);
  const [selected, setSelected] = useState<ConversationRow | null>(null);
  const [messages, setMessages] = useState<Message[]>([]);
  const [ctx, setCtx] = useState<WhmcsContext | null>(null);
  const [departments, setDepartments] = useState<Department[]>([]);
  const [draft, setDraft] = useState("");
  const [isNote, setIsNote] = useState(false);
  const [loadingList, setLoadingList] = useState(false);
  const [loadingThread, setLoadingThread] = useState(false);
  const [sending, setSending] = useState(false);
  const [suggesting, setSuggesting] = useState(false);
  const [converting, setConverting] = useState(false);
  const [heartbeatStatus, setHeartbeatStatus] = useState<
    "online" | "busy" | "away" | "offline"
  >("online");
  const [seatInfo, setSeatInfo] = useState<{
    display_name: string;
    role: string;
    current_chats: number;
    chat_limit: number;
  } | null>(null);
  const scrollerRef = useRef<HTMLDivElement | null>(null);
  const pollRef = useRef<number | null>(null);

  // Auth + initial availability
  useEffect(() => {
    (async () => {
      try {
        const me = await client.auth.me();
        if (!me?.data) {
          await client.auth.toLogin();
          return;
        }
        // Verify the user has a seat by calling availability/me.
        const av = await client.apiCall.invoke({
          url: "/api/v1/chat/availability/me",
          method: "GET",
          data: {},
        });
        if (av?.data?.seat) {
          setSeatInfo({
            display_name: av.data.seat.display_name,
            role: av.data.seat.role,
            current_chats: av.data.current_chats,
            chat_limit: av.data.chat_limit,
          });
          setHeartbeatStatus(av.data.availability?.status || "offline");
        }
      } catch (err: any) {
        const msg =
          err?.data?.detail ||
          err?.message ||
          "You are not authorized to access the support inbox.";
        setAuthError(msg);
      }
    })();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Load departments once
  useEffect(() => {
    (async () => {
      try {
        const res = await client.apiCall.invoke({
          url: "/api/v1/chat/departments",
          method: "GET",
          data: {},
        });
        setDepartments(res?.data?.items || []);
      } catch {
        /* non-critical */
      }
    })();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Heartbeat every 30s
  useEffect(() => {
    if (authError) return;
    const tick = async () => {
      try {
        await client.apiCall.invoke({
          url: "/api/v1/chat/availability/heartbeat",
          method: "POST",
          data: { status: heartbeatStatus },
        });
      } catch {
        /* ignore */
      }
    };
    tick();
    const id = window.setInterval(tick, 30_000);
    return () => window.clearInterval(id);
  }, [authError, heartbeatStatus, client]);

  const refreshList = useCallback(async () => {
    setLoadingList(true);
    try {
      const res = await client.apiCall.invoke({
        url: "/api/v1/chat/agent/conversations",
        method: "GET",
        data: { scope, skip: 0, limit: 100 },
      });
      setList(res?.data?.items || []);
    } catch (err: any) {
      if (err?.status === 403) {
        setAuthError(err?.data?.detail || "Not authorized.");
      }
    } finally {
      setLoadingList(false);
    }
  }, [client, scope]);

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

  // Poll the list + the active thread every 7s.
  useEffect(() => {
    if (authError) return;
    pollRef.current = window.setInterval(() => {
      refreshList();
      if (selected) {
        refreshThread(selected.id).catch(() => undefined);
      }
    }, 7000);
    return () => {
      if (pollRef.current) window.clearInterval(pollRef.current);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selected?.id, refreshList, authError]);

  useEffect(() => {
    if (scrollerRef.current) {
      scrollerRef.current.scrollTop = scrollerRef.current.scrollHeight;
    }
  }, [messages.length]);

  async function refreshThread(conversationId: number) {
    setLoadingThread(true);
    try {
      const [msgsRes, convRes, ctxRes] = await Promise.all([
        client.apiCall.invoke({
          url: `/api/v1/chat/conversations/${conversationId}/messages`,
          method: "GET",
          data: { include_internal: true },
        }),
        client.apiCall.invoke({
          url: `/api/v1/chat/conversations/${conversationId}`,
          method: "GET",
          data: {},
        }),
        client.apiCall.invoke({
          url: `/api/v1/chat/agent/conversations/${conversationId}/whmcs-context`,
          method: "GET",
          data: {},
        }),
      ]);
      setMessages(msgsRes?.data?.items || []);
      if (convRes?.data?.conversation) setSelected(convRes.data.conversation);
      setCtx(ctxRes?.data || null);
    } catch {
      /* silent */
    } finally {
      setLoadingThread(false);
    }
  }

  async function openConversation(row: ConversationRow) {
    setSelected(row);
    setMessages([]);
    setCtx(null);
    setDraft("");
    setIsNote(false);
    await refreshThread(row.id);
  }

  async function assignToMe() {
    if (!selected || !seatInfo) return;
    try {
      // Discover our seat id via availability/me (already have it in seatInfo
      // indirectly — but we need the numeric id). Easiest: ask for it now.
      const av = await client.apiCall.invoke({
        url: "/api/v1/chat/availability/me",
        method: "GET",
        data: {},
      });
      const myId = av?.data?.seat?.id;
      if (!myId) return;
      await client.apiCall.invoke({
        url: `/api/v1/chat/agent/conversations/${selected.id}/assign`,
        method: "POST",
        data: { seat_id: myId },
      });
      await refreshThread(selected.id);
      await refreshList();
    } catch (err: any) {
      alert(err?.data?.detail || "Failed to assign.");
    }
  }

  async function sendReply() {
    if (!selected || !draft.trim()) return;
    setSending(true);
    try {
      await client.apiCall.invoke({
        url: `/api/v1/chat/agent/conversations/${selected.id}/reply`,
        method: "POST",
        data: { content: draft.trim(), is_internal_note: isNote },
      });
      setDraft("");
      await refreshThread(selected.id);
      await refreshList();
    } catch (err: any) {
      alert(err?.data?.detail || "Failed to send.");
    } finally {
      setSending(false);
    }
  }

  async function suggest() {
    if (!selected) return;
    setSuggesting(true);
    try {
      const res = await client.apiCall.invoke({
        url: `/api/v1/chat/agent/conversations/${selected.id}/suggest-reply`,
        method: "POST",
        data: {},
      });
      if (res?.data?.suggestion) {
        setDraft(res.data.suggestion);
      }
    } catch (err: any) {
      alert(err?.data?.detail || "Failed to generate suggestion.");
    } finally {
      setSuggesting(false);
    }
  }

  async function summarize() {
    if (!selected) return;
    try {
      const res = await client.apiCall.invoke({
        url: `/api/v1/chat/agent/conversations/${selected.id}/summarize`,
        method: "POST",
        data: {},
      });
      setSelected((prev) =>
        prev ? { ...prev, ai_summary: res?.data?.summary } : prev
      );
    } catch (err: any) {
      alert(err?.data?.detail || "Failed to summarize.");
    }
  }

  async function changeStatus(status: string) {
    if (!selected) return;
    try {
      const res = await client.apiCall.invoke({
        url: `/api/v1/chat/agent/conversations/${selected.id}/status`,
        method: "POST",
        data: { status },
      });
      if (res?.data?.conversation) setSelected(res.data.conversation);
      await refreshList();
    } catch (err: any) {
      alert(err?.data?.detail || "Failed to update status.");
    }
  }

  async function convertToTicket() {
    if (!selected) return;
    if (!confirm("Create a WHMCS ticket from this chat?")) return;
    setConverting(true);
    try {
      const res = await client.apiCall.invoke({
        url: `/api/v1/chat/agent/conversations/${selected.id}/convert-to-ticket`,
        method: "POST",
        data: { subject: selected.subject || undefined },
      });
      alert(`Ticket created: #${res?.data?.whmcs_ticket_id || "?"}`);
      await refreshThread(selected.id);
      await refreshList();
    } catch (err: any) {
      alert(err?.data?.detail || "Failed to create ticket.");
    } finally {
      setConverting(false);
    }
  }

  if (authError) {
    return (
      <div className="flex min-h-screen items-center justify-center bg-muted p-6">
        <div className="max-w-md rounded-lg border border-red-200 bg-white p-6 text-center shadow">
          <AlertCircle className="mx-auto mb-3 h-10 w-10 text-red-500" />
          <h2 className="mb-2 text-lg font-semibold">Access denied</h2>
          <p className="mb-4 text-sm text-muted-foreground">{authError}</p>
          <Button onClick={() => navigate("/")} variant="outline">
            Back to home
          </Button>
        </div>
      </div>
    );
  }

  return (
    <div className="flex h-screen flex-col bg-muted">
      {/* Top bar */}
      <div className="flex items-center justify-between border-b bg-white px-4 py-2">
        <div className="flex items-center gap-3">
          <MessageSquare className="h-5 w-5 text-emerald-600" />
          <h1 className="text-base font-semibold">Support Inbox</h1>
          {seatInfo && (
            <Badge variant="outline" className="text-xs">
              {seatInfo.display_name} · {seatInfo.role} ·{" "}
              {seatInfo.current_chats}/{seatInfo.chat_limit}
            </Badge>
          )}
        </div>
        <div className="flex items-center gap-2">
          <Select
            value={heartbeatStatus}
            onValueChange={(v) => setHeartbeatStatus(v as any)}
          >
            <SelectTrigger className="h-8 w-[120px] text-xs">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="online">🟢 Online</SelectItem>
              <SelectItem value="busy">🟡 Busy</SelectItem>
              <SelectItem value="away">⚪ Away</SelectItem>
              <SelectItem value="offline">⚫ Offline</SelectItem>
            </SelectContent>
          </Select>
          <Button
            size="sm"
            variant="outline"
            onClick={() => {
              refreshList();
              if (selected) refreshThread(selected.id);
            }}
          >
            <RefreshCcw className="mr-1 h-3.5 w-3.5" />
            Refresh
          </Button>
        </div>
      </div>

      <div className="flex flex-1 overflow-hidden">
        {/* Left: list */}
        <div className="flex w-80 flex-col border-r bg-white">
          <Tabs value={scope} onValueChange={setScope} className="w-full">
            <TabsList className="grid w-full grid-cols-4">
              {SCOPES.map((s) => (
                <TabsTrigger key={s.value} value={s.value} className="text-xs">
                  {s.label}
                </TabsTrigger>
              ))}
            </TabsList>
          </Tabs>
          <div className="flex-1 overflow-y-auto">
            {loadingList ? (
              <div className="flex items-center justify-center p-6">
                <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
              </div>
            ) : list.length === 0 ? (
              <div className="p-6 text-center text-xs text-muted-foreground">
                No conversations in this scope.
              </div>
            ) : (
              <ul className="divide-y">
                {list.map((c) => (
                  <li key={c.id}>
                    <button
                      type="button"
                      onClick={() => openConversation(c)}
                      className={cn(
                        "w-full px-3 py-3 text-left transition-colors hover:bg-muted/50",
                        selected?.id === c.id && "bg-emerald-50"
                      )}
                    >
                      <div className="flex items-center justify-between">
                        <span className="text-sm font-medium">
                          {c.visitor_name || "Guest"}
                        </span>
                        <StatusBadge status={c.status} />
                      </div>
                      <div className="mt-0.5 truncate text-xs text-muted-foreground">
                        {c.subject || c.visitor_email || `#${c.id}`}
                      </div>
                      <div className="mt-1 flex items-center gap-2 text-[10px] text-muted-foreground">
                        <PriorityBadge priority={c.priority} />
                        {c.linked_ticket_id ? (
                          <Badge
                            variant="outline"
                            className="h-4 px-1 text-[10px]"
                          >
                            #T{c.linked_ticket_id}
                          </Badge>
                        ) : null}
                        {c.last_message_at ? (
                          <span>{new Date(c.last_message_at).toLocaleString()}</span>
                        ) : null}
                      </div>
                    </button>
                  </li>
                ))}
              </ul>
            )}
          </div>
        </div>

        {/* Middle: thread */}
        <div className="flex flex-1 flex-col">
          {!selected ? (
            <div className="flex flex-1 items-center justify-center text-sm text-muted-foreground">
              Select a conversation to view.
            </div>
          ) : (
            <>
              <div className="flex items-center justify-between border-b bg-white px-4 py-2">
                <div>
                  <div className="flex items-center gap-2">
                    <h2 className="text-sm font-semibold">
                      {selected.visitor_name || "Guest"}
                    </h2>
                    <StatusBadge status={selected.status} />
                    <PriorityBadge priority={selected.priority} />
                  </div>
                  <div className="text-xs text-muted-foreground">
                    {selected.subject || selected.visitor_email || "(no subject)"}
                  </div>
                </div>
                <div className="flex flex-wrap gap-1">
                  {!selected.assigned_seat_id && (
                    <Button size="sm" variant="outline" onClick={assignToMe}>
                      <Users className="mr-1 h-3.5 w-3.5" />
                      Take
                    </Button>
                  )}
                  <Button size="sm" variant="outline" onClick={summarize}>
                    <Sparkles className="mr-1 h-3.5 w-3.5" />
                    Summarize
                  </Button>
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={convertToTicket}
                    disabled={converting || !!selected.linked_ticket_id}
                  >
                    <TicketPlus className="mr-1 h-3.5 w-3.5" />
                    {converting ? "Converting…" : "Ticket"}
                  </Button>
                  {selected.status !== "resolved" &&
                    selected.status !== "closed" && (
                      <Button
                        size="sm"
                        variant="outline"
                        onClick={() => changeStatus("resolved")}
                      >
                        <CheckCircle2 className="mr-1 h-3.5 w-3.5" />
                        Resolve
                      </Button>
                    )}
                </div>
              </div>

              {selected.ai_summary ? (
                <div className="border-b bg-amber-50 px-4 py-2">
                  <div className="mb-1 text-[11px] font-semibold uppercase text-amber-700">
                    AI Summary
                  </div>
                  <pre className="whitespace-pre-wrap text-xs text-amber-900">
                    {selected.ai_summary}
                  </pre>
                </div>
              ) : null}

              <div
                ref={scrollerRef}
                className="flex-1 overflow-y-auto bg-muted/40 px-4 py-3"
              >
                {loadingThread && messages.length === 0 ? (
                  <div className="flex items-center justify-center p-6">
                    <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
                  </div>
                ) : (
                  <div className="flex flex-col gap-2">
                    {messages.map((m) => (
                      <AgentBubble key={m.id} message={m} />
                    ))}
                  </div>
                )}
              </div>

              <div className="border-t bg-white p-3">
                <div className="mb-2 flex items-center justify-between">
                  <label className="flex items-center gap-2 text-xs text-muted-foreground">
                    <input
                      type="checkbox"
                      checked={isNote}
                      onChange={(e) => setIsNote(e.target.checked)}
                    />
                    <Lock className="h-3 w-3" />
                    Internal note (agents only)
                  </label>
                  <Button
                    size="sm"
                    variant="ghost"
                    onClick={suggest}
                    disabled={suggesting}
                  >
                    {suggesting ? (
                      <Loader2 className="mr-1 h-3.5 w-3.5 animate-spin" />
                    ) : (
                      <Sparkles className="mr-1 h-3.5 w-3.5" />
                    )}
                    Suggest reply
                  </Button>
                </div>
                <div className="flex items-end gap-2">
                  <Textarea
                    value={draft}
                    onChange={(e) => setDraft(e.target.value)}
                    onKeyDown={(e) => {
                      if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
                        e.preventDefault();
                        sendReply();
                      }
                    }}
                    placeholder={
                      isNote
                        ? "Write an internal note (not visible to visitor)…"
                        : "Type your reply… (Cmd/Ctrl+Enter to send)"
                    }
                    rows={3}
                    className={cn(
                      "resize-none text-sm",
                      isNote && "bg-amber-50"
                    )}
                  />
                  <Button
                    type="button"
                    onClick={sendReply}
                    disabled={sending || !draft.trim()}
                    className="h-16 bg-emerald-600 text-white hover:bg-emerald-700"
                  >
                    {sending ? (
                      <Loader2 className="h-4 w-4 animate-spin" />
                    ) : (
                      <Send className="h-4 w-4" />
                    )}
                  </Button>
                </div>
              </div>
            </>
          )}
        </div>

        {/* Right: context sidebar */}
        <div className="hidden w-80 flex-col overflow-y-auto border-l bg-white lg:flex">
          {selected ? (
            <ContextPanel ctx={ctx} selected={selected} departments={departments} />
          ) : (
            <div className="p-4 text-xs text-muted-foreground">
              Visitor + WHMCS context will appear here.
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function AgentBubble({ message }: { message: Message }) {
  const isVisitor = message.sender_type === "visitor";
  const isAgent = message.sender_type === "agent";
  const isAI = message.sender_type === "ai";
  const isSystem = message.sender_type === "system";
  const isNote = message.is_internal_note;

  if (isSystem) {
    return (
      <div className="self-center rounded-full bg-slate-100 px-3 py-1 text-center text-[11px] text-slate-700">
        {message.content}
      </div>
    );
  }

  return (
    <div
      className={cn(
        "max-w-[75%] rounded-2xl px-3 py-2 text-sm shadow",
        isVisitor && "self-start bg-white",
        isAI && "self-start border border-emerald-200 bg-emerald-50",
        isAgent && !isNote && "self-end bg-emerald-600 text-white",
        isAgent && isNote && "self-end bg-amber-100 border border-amber-300"
      )}
    >
      <div className="mb-0.5 text-[10px] font-semibold opacity-80">
        {message.sender_name || message.sender_type}
        {isAI ? " · AI" : ""}
        {isNote ? " · Internal note" : ""}
        {message.created_at
          ? ` · ${new Date(message.created_at).toLocaleTimeString()}`
          : ""}
      </div>
      <div className="whitespace-pre-wrap leading-relaxed">{message.content}</div>
    </div>
  );
}

function StatusBadge({ status }: { status: string }) {
  const map: Record<string, string> = {
    ai: "bg-blue-100 text-blue-700",
    queued: "bg-amber-100 text-amber-700",
    assigned: "bg-emerald-100 text-emerald-700",
    resolved: "bg-slate-100 text-slate-700",
    closed: "bg-slate-200 text-slate-600",
  };
  return (
    <span className={cn("rounded px-1.5 py-0.5 text-[10px]", map[status] || "")}>
      {status}
    </span>
  );
}

function PriorityBadge({ priority }: { priority: string }) {
  const map: Record<string, string> = {
    low: "text-slate-500",
    normal: "text-blue-600",
    high: "text-amber-600",
    urgent: "text-red-600 font-semibold",
  };
  return <span className={cn("text-[10px]", map[priority] || "")}>{priority}</span>;
}

function ContextPanel({
  ctx,
  selected,
  departments,
}: {
  ctx: WhmcsContext | null;
  selected: ConversationRow;
  departments: Department[];
}) {
  const dept = departments.find((d) => d.id === selected.department_id);
  return (
    <div className="space-y-4 p-4 text-sm">
      <section>
        <h3 className="mb-1 text-xs font-semibold uppercase text-muted-foreground">
          Visitor
        </h3>
        <div className="rounded border bg-muted/30 p-2 text-xs">
          <div>
            <span className="font-medium">Name:</span>{" "}
            {selected.visitor_name || "Guest"}
          </div>
          <div>
            <span className="font-medium">Email:</span>{" "}
            {selected.visitor_email || "—"}
          </div>
          <div>
            <span className="font-medium">WHMCS Client:</span>{" "}
            {selected.whmcs_client_id || "—"}
          </div>
          <div>
            <span className="font-medium">Department:</span>{" "}
            {dept?.name || "—"}
          </div>
        </div>
      </section>

      {ctx?.client ? (
        <section>
          <h3 className="mb-1 text-xs font-semibold uppercase text-muted-foreground">
            WHMCS Profile
          </h3>
          <div className="rounded border bg-muted/30 p-2 text-xs">
            <div>
              <span className="font-medium">ID:</span>{" "}
              {ctx.client.userid || ctx.client.id}
            </div>
            <div>
              <span className="font-medium">Company:</span>{" "}
              {ctx.client.companyname || "—"}
            </div>
            <div>
              <span className="font-medium">Country:</span>{" "}
              {ctx.client.country || "—"}
            </div>
            <div>
              <span className="font-medium">Status:</span>{" "}
              {ctx.client.status || "—"}
            </div>
            <div>
              <span className="font-medium">Credit:</span>{" "}
              {ctx.client.credit || "0"}
            </div>
          </div>
        </section>
      ) : null}

      <section>
        <h3 className="mb-1 text-xs font-semibold uppercase text-muted-foreground">
          Active Services ({ctx?.services?.length || 0})
        </h3>
        {ctx?.services?.length ? (
          <ul className="space-y-1 text-xs">
            {ctx.services.slice(0, 10).map((s: any) => (
              <li key={s.id} className="rounded border bg-muted/30 p-2">
                <div className="font-medium">{s.name || s.productname}</div>
                <div className="text-muted-foreground">
                  {s.domain || ""} · {s.status}
                </div>
              </li>
            ))}
          </ul>
        ) : (
          <div className="text-xs text-muted-foreground">None.</div>
        )}
      </section>

      <section>
        <h3 className="mb-1 text-xs font-semibold uppercase text-muted-foreground">
          Invoices ({ctx?.invoices?.length || 0})
        </h3>
        {ctx?.invoices?.length ? (
          <ul className="space-y-1 text-xs">
            {ctx.invoices.slice(0, 10).map((i: any) => (
              <li key={i.id} className="rounded border bg-muted/30 p-2">
                <div className="flex justify-between">
                  <span>
                    <span className="font-medium">#{i.id}</span> · {i.status}
                  </span>
                  <span>
                    {i.total} {i.currencycode}
                  </span>
                </div>
                <div className="text-muted-foreground">
                  Due {i.duedate || "—"}
                </div>
              </li>
            ))}
          </ul>
        ) : (
          <div className="text-xs text-muted-foreground">None.</div>
        )}
      </section>

      <section>
        <h3 className="mb-1 text-xs font-semibold uppercase text-muted-foreground">
          Domains ({ctx?.domains?.length || 0})
        </h3>
        {ctx?.domains?.length ? (
          <ul className="space-y-1 text-xs">
            {ctx.domains.slice(0, 10).map((d: any) => (
              <li key={d.id} className="rounded border bg-muted/30 p-2">
                <div className="font-medium">{d.domainname}</div>
                <div className="text-muted-foreground">
                  {d.registrar} · exp {d.expirydate}
                </div>
              </li>
            ))}
          </ul>
        ) : (
          <div className="text-xs text-muted-foreground">None.</div>
        )}
      </section>
    </div>
  );
}