// @File: frontend/src/pages/admin/cms/CmsWhmcsLogs.tsx
// @Desc: Admin page showing paginated WHMCS API activity logs with filters
//        (action, status, user email) and an aggregate-stats card.
import { useCallback, useEffect, useMemo, useState } from "react";
import { createClient } from "@metagptx/web-sdk";
import CmsLayout from "./CmsLayout";
import { PageHeader, SectionCard, Field, TextInput, Select, Badge } from "./ui";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { CheckCircle2, Loader2, RefreshCw, XCircle } from "lucide-react";
import { toast } from "sonner";

interface WhmcsHealthCheckResponse {
  ok: boolean;
  http_status: number | null;
  latency_ms: number | null;
  cf_ray: string | null;
  server: string | null;
  message: string;
  body_snippet: string | null;
  api_url: string | null;
  // Diagnostic enrichments (added to help admins pinpoint the exact fault
  // category: IP whitelist, bad credentials, wrong endpoint, missing role
  // permission, Cloudflare HTML challenge, etc.)
  error_category: string | null;
  whmcs_version: string | null;
  whmcs_system_url: string | null;
  authenticated_user: string | null;
  outbound_ip: string | null;
  outbound_ip_provider: string | null;
  ip_whitelist_hint: string | null;
}

interface WhmcsActionProbe {
  action: string;
  feature: string;
  ok: boolean;
  http_status: number | null;
  whmcs_result: string | null;
  message: string | null;
  latency_ms: number | null;
  required_permission: string;
}

interface WhmcsActionsHealthResponse {
  ok: boolean;
  probed_at: number;
  client_id_resolved: number | null;
  test_email: string | null;
  probes: WhmcsActionProbe[];
  summary: string;
}

interface WhmcsLogItem {
  id: number;
  action: string;
  user_email: string | null;
  status: string;
  http_status: number | null;
  duration_ms: number | null;
  error: string | null;
  created_at: string | null;
}

interface WhmcsLogList {
  items: WhmcsLogItem[];
  total: number;
  skip: number;
  limit: number;
}

interface WhmcsLogStats {
  total: number;
  success: number;
  error: number;
  top_actions: Array<{ action: string; count: number }>;
}

const PAGE_SIZE = 25;
const client = createClient();

export default function CmsWhmcsLogs() {
  const [items, setItems] = useState<WhmcsLogItem[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(0);
  const [loading, setLoading] = useState(true);
  const [stats, setStats] = useState<WhmcsLogStats | null>(null);

  const [actionFilter, setActionFilter] = useState("");
  const [statusFilter, setStatusFilter] = useState<string>("all");
  const [emailFilter, setEmailFilter] = useState("");

  const [healthLoading, setHealthLoading] = useState(false);
  const [healthResult, setHealthResult] =
    useState<WhmcsHealthCheckResponse | null>(null);

  const [actionsProbeLoading, setActionsProbeLoading] = useState(false);
  const [actionsProbeResult, setActionsProbeResult] =
    useState<WhmcsActionsHealthResponse | null>(null);
  const [probeEmail, setProbeEmail] = useState("");

  const callApi = useCallback(
    async <T,>(path: string, method: "GET" | "POST" = "GET"): Promise<T> => {
      const res = await client.apiCall.invoke({ path, method });
      if (res?.error) {
        throw new Error(res.error);
      }
      return (res?.data ?? res) as T;
    },
    [],
  );

  const fetchStats = useCallback(async () => {
    try {
      const res = await callApi<WhmcsLogStats>("/api/v1/whmcs/admin/logs/stats");
      setStats(res);
    } catch (err) {
      // eslint-disable-next-line no-console
      console.warn("Failed to load WHMCS log stats", err);
    }
  }, [callApi]);

  const runHealthCheck = useCallback(async () => {
    setHealthLoading(true);
    setHealthResult(null);
    try {
      const res = await callApi<WhmcsHealthCheckResponse>(
        "/api/v1/whmcs/admin/system/health-check",
        "POST",
      );
      setHealthResult(res);
      if (res.ok) {
        toast.success("WHMCS connection is healthy.");
      } else {
        toast.error("WHMCS connection check failed — see details below.");
      }
      // Refresh stats/logs so the new probe entry shows up.
      fetchStats();
      fetchLogs();
    } catch (err) {
      const msg =
        err instanceof Error ? err.message : "Failed to run WHMCS health check";
      toast.error(msg);
      setHealthResult({
        ok: false,
        http_status: null,
        latency_ms: null,
        cf_ray: null,
        server: null,
        message: msg,
        body_snippet: null,
        api_url: null,
        error_category: "client_error",
        whmcs_version: null,
        whmcs_system_url: null,
        authenticated_user: null,
        outbound_ip: null,
        outbound_ip_provider: null,
        ip_whitelist_hint: null,
      });
    } finally {
      setHealthLoading(false);
    }
    // fetchLogs is stable-by-filters; this is intentional.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [callApi, fetchStats]);

  const runActionsProbe = useCallback(async () => {
    setActionsProbeLoading(true);
    setActionsProbeResult(null);
    try {
      const params = new URLSearchParams();
      if (probeEmail.trim()) {
        params.set("test_email", probeEmail.trim());
      }
      const suffix = params.toString() ? `?${params.toString()}` : "";
      const res = await callApi<WhmcsActionsHealthResponse>(
        `/api/v1/whmcs/admin/system/actions-health${suffix}`,
        "GET",
      );
      setActionsProbeResult(res);
      if (res.ok) {
        toast.success("All WHMCS API actions are healthy.");
      } else {
        const failedCount = res.probes.filter((p) => !p.ok).length;
        toast.error(
          `${failedCount} WHMCS action${failedCount === 1 ? "" : "s"} failed — see the breakdown below.`,
        );
      }
      fetchStats();
      fetchLogs();
    } catch (err) {
      const msg =
        err instanceof Error ? err.message : "Failed to run actions probe";
      toast.error(msg);
    } finally {
      setActionsProbeLoading(false);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [callApi, probeEmail, fetchStats]);

  const fetchLogs = useCallback(async () => {
    setLoading(true);
    try {
      const params = new URLSearchParams({
        skip: String(page * PAGE_SIZE),
        limit: String(PAGE_SIZE),
      });
      if (actionFilter.trim()) params.set("action", actionFilter.trim());
      if (statusFilter && statusFilter !== "all") params.set("status", statusFilter);
      if (emailFilter.trim()) params.set("user_email", emailFilter.trim());
      const res = await callApi<WhmcsLogList>(
        `/api/v1/whmcs/admin/logs?${params.toString()}`,
      );
      setItems(res.items || []);
      setTotal(res.total || 0);
    } catch (err) {
      const msg = err instanceof Error ? err.message : "Failed to load WHMCS logs";
      toast.error(msg);
    } finally {
      setLoading(false);
    }
  }, [callApi, page, actionFilter, statusFilter, emailFilter]);

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

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

  const totalPages = useMemo(
    () => Math.max(1, Math.ceil(total / PAGE_SIZE)),
    [total],
  );

  const formatDate = (iso: string | null) => {
    if (!iso) return "—";
    try {
      return new Date(iso).toLocaleString();
    } catch {
      return iso;
    }
  };

  const refreshAction = (
    <button
      type="button"
      onClick={() => {
        setPage(0);
        fetchLogs();
        fetchStats();
      }}
      disabled={loading}
      className="inline-flex items-center gap-2 px-4 py-2 rounded-lg border border-slate-300 text-slate-700 text-sm font-semibold bg-white hover:bg-slate-50 transition disabled:opacity-60"
    >
      <RefreshCw className="h-4 w-4" />
      Refresh
    </button>
  );

  return (
    <CmsLayout>
      <PageHeader
        title="WHMCS API Logs"
        description="Audit every call the portal makes to WHMCS — success, failure, and latency."
      />

      {/* Stats cards */}
      <div className="mb-6 grid grid-cols-1 gap-4 md:grid-cols-4">
        <div className="bg-white rounded-2xl shadow-sm border border-slate-200 p-5">
          <div className="text-sm text-slate-500">Total Calls</div>
          <div className="mt-1 text-3xl font-bold text-slate-900">
            {stats?.total ?? 0}
          </div>
        </div>
        <div className="bg-white rounded-2xl shadow-sm border border-slate-200 p-5">
          <div className="text-sm text-slate-500">Successful</div>
          <div className="mt-1 text-3xl font-bold text-emerald-600">
            {stats?.success ?? 0}
          </div>
        </div>
        <div className="bg-white rounded-2xl shadow-sm border border-slate-200 p-5">
          <div className="text-sm text-slate-500">Errors</div>
          <div className="mt-1 text-3xl font-bold text-red-600">
            {stats?.error ?? 0}
          </div>
        </div>
        <div className="bg-white rounded-2xl shadow-sm border border-slate-200 p-5">
          <div className="text-sm text-slate-500">Top Action</div>
          <div className="mt-1 truncate text-lg font-semibold text-slate-900">
            {stats?.top_actions?.[0]?.action ?? "—"}
          </div>
          <div className="text-xs text-slate-500">
            {stats?.top_actions?.[0]?.count ?? 0} calls
          </div>
        </div>
      </div>

      {/* Connection test card */}
      <SectionCard
        title="Test WHMCS Connection"
        description="Run a live probe against the WHMCS API to verify credentials, IP whitelist, and origin reachability."
        actions={
          <button
            type="button"
            onClick={runHealthCheck}
            disabled={healthLoading}
            className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-emerald-600 text-white text-sm font-semibold hover:bg-emerald-700 transition disabled:opacity-60"
          >
            {healthLoading ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <CheckCircle2 className="h-4 w-4" />
            )}
            {healthLoading ? "Testing…" : "Run test"}
          </button>
        }
      >
        {healthResult ? (
          <div
            className={`rounded-lg border p-4 ${
              healthResult.ok
                ? "bg-emerald-50 border-emerald-200"
                : "bg-red-50 border-red-200"
            }`}
          >
            <div className="flex items-start gap-3">
              {healthResult.ok ? (
                <CheckCircle2 className="h-5 w-5 text-emerald-600 mt-0.5 flex-shrink-0" />
              ) : (
                <XCircle className="h-5 w-5 text-red-600 mt-0.5 flex-shrink-0" />
              )}
              <div className="flex-1 min-w-0">
                <div
                  className={`font-semibold ${
                    healthResult.ok ? "text-emerald-800" : "text-red-800"
                  }`}
                >
                  {healthResult.ok
                    ? "Connection healthy"
                    : "Connection failed"}
                </div>
                <div className="mt-1 text-sm text-slate-700">
                  {healthResult.message}
                </div>
                <dl className="mt-3 grid grid-cols-2 gap-x-4 gap-y-1 text-xs text-slate-600 sm:grid-cols-4">
                  <div>
                    <dt className="font-medium text-slate-500">HTTP</dt>
                    <dd>{healthResult.http_status ?? "—"}</dd>
                  </div>
                  <div>
                    <dt className="font-medium text-slate-500">Latency</dt>
                    <dd>
                      {healthResult.latency_ms != null
                        ? `${healthResult.latency_ms} ms`
                        : "—"}
                    </dd>
                  </div>
                  <div>
                    <dt className="font-medium text-slate-500">Server</dt>
                    <dd className="truncate">{healthResult.server ?? "—"}</dd>
                  </div>
                  <div>
                    <dt className="font-medium text-slate-500">cf-ray</dt>
                    <dd className="truncate font-mono">
                      {healthResult.cf_ray ?? "—"}
                    </dd>
                  </div>
                </dl>
                {/* Extended diagnostic grid — only renders the rows that have data,
                    so a healthy probe shows a compact card and a failing probe
                    shows everything the admin needs to fix the problem. */}
                <dl className="mt-3 grid grid-cols-1 gap-x-4 gap-y-1 text-xs text-slate-600 sm:grid-cols-2">
                  {healthResult.api_url ? (
                    <div className="sm:col-span-2">
                      <dt className="font-medium text-slate-500">Endpoint</dt>
                      <dd className="font-mono break-all">{healthResult.api_url}</dd>
                    </div>
                  ) : null}
                  {healthResult.whmcs_version ? (
                    <div>
                      <dt className="font-medium text-slate-500">WHMCS version</dt>
                      <dd className="font-mono">{healthResult.whmcs_version}</dd>
                    </div>
                  ) : null}
                  {healthResult.whmcs_system_url ? (
                    <div>
                      <dt className="font-medium text-slate-500">System URL</dt>
                      <dd className="font-mono break-all">
                        {healthResult.whmcs_system_url}
                      </dd>
                    </div>
                  ) : null}
                  {healthResult.authenticated_user ? (
                    <div>
                      <dt className="font-medium text-slate-500">Identifier</dt>
                      <dd className="font-mono">{healthResult.authenticated_user}</dd>
                    </div>
                  ) : null}
                  {healthResult.outbound_ip ? (
                    <div>
                      <dt className="font-medium text-slate-500">Backend outbound IP</dt>
                      <dd className="font-mono">
                        {healthResult.outbound_ip}
                        {healthResult.outbound_ip_provider ? (
                          <span className="ml-1 text-slate-400">
                            ({healthResult.outbound_ip_provider})
                          </span>
                        ) : null}
                      </dd>
                    </div>
                  ) : null}
                  {healthResult.error_category ? (
                    <div>
                      <dt className="font-medium text-slate-500">Error category</dt>
                      <dd className="font-mono">{healthResult.error_category}</dd>
                    </div>
                  ) : null}
                </dl>
                {/* Actionable remediation hint — pre-built by the backend so the UI
                    just displays it. This is the line that tells the admin
                    exactly which IP to whitelist or which permission to enable. */}
                {healthResult.ip_whitelist_hint ? (
                  <div
                    className={`mt-3 rounded-md border p-2 text-xs ${
                      healthResult.ok
                        ? "bg-emerald-100/60 border-emerald-200 text-emerald-900"
                        : "bg-amber-50 border-amber-200 text-amber-900"
                    }`}
                  >
                    <span className="font-semibold">Next step: </span>
                    {healthResult.ip_whitelist_hint}
                  </div>
                ) : null}
                {healthResult.body_snippet ? (
                  <details className="mt-2 text-xs text-slate-600">
                    <summary className="cursor-pointer font-medium">
                      Response snippet
                    </summary>
                    <pre className="mt-1 rounded bg-slate-900/90 p-2 text-[11px] text-slate-100 overflow-x-auto whitespace-pre-wrap">
                      {healthResult.body_snippet}
                    </pre>
                  </details>
                ) : null}
              </div>
            </div>
          </div>
        ) : (
          <div className="text-sm text-slate-500">
            Click <span className="font-semibold">Run test</span> to probe the
            WHMCS API. Useful after credential, IP-whitelist, or Cloudflare
            changes.
          </div>
        )}
      </SectionCard>

      {/* Per-action diagnostic card */}
      <SectionCard
        title="Per-action diagnostic"
        description="Probe every WHMCS API action the dashboard uses. Use this when specific sections (services, invoices, domains, tickets, emails) fail to load — it tells you exactly which API permission is missing in WHMCS."
        actions={
          <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
            <TextInput
              placeholder="Test client email (optional)"
              value={probeEmail}
              onChange={(e) => setProbeEmail(e.target.value)}
              className="sm:w-64"
            />
            <button
              type="button"
              onClick={runActionsProbe}
              disabled={actionsProbeLoading}
              className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-indigo-600 text-white text-sm font-semibold hover:bg-indigo-700 transition disabled:opacity-60"
            >
              {actionsProbeLoading ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <CheckCircle2 className="h-4 w-4" />
              )}
              {actionsProbeLoading ? "Probing…" : "Probe all actions"}
            </button>
          </div>
        }
      >
        {actionsProbeResult ? (
          <div className="space-y-3">
            <div
              className={`rounded-lg border p-3 text-sm ${
                actionsProbeResult.ok
                  ? "bg-emerald-50 border-emerald-200 text-emerald-800"
                  : "bg-amber-50 border-amber-200 text-amber-900"
              }`}
            >
              <div className="font-semibold">
                {actionsProbeResult.ok ? "All healthy" : "Action failures detected"}
              </div>
              <div className="mt-1">{actionsProbeResult.summary}</div>
              <div className="mt-2 text-xs text-slate-600">
                Test email:{" "}
                <span className="font-mono">
                  {actionsProbeResult.test_email || "—"}
                </span>
                {" · "}Resolved client id:{" "}
                <span className="font-mono">
                  {actionsProbeResult.client_id_resolved ?? "—"}
                </span>
              </div>
            </div>
            <div className="overflow-x-auto rounded-lg border border-slate-200">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead className="w-40">Feature</TableHead>
                    <TableHead className="w-48">Action</TableHead>
                    <TableHead className="w-24">Status</TableHead>
                    <TableHead className="w-20">HTTP</TableHead>
                    <TableHead className="w-24">WHMCS</TableHead>
                    <TableHead className="w-24">Latency</TableHead>
                    <TableHead>Message</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {actionsProbeResult.probes.map((probe) => (
                    <TableRow key={probe.action}>
                      <TableCell className="text-xs font-medium text-slate-700">
                        {probe.feature}
                      </TableCell>
                      <TableCell className="font-mono text-xs">
                        {probe.action}
                      </TableCell>
                      <TableCell>
                        <Badge tone={probe.ok ? "green" : "red"}>
                          {probe.ok ? "pass" : "fail"}
                        </Badge>
                      </TableCell>
                      <TableCell className="text-xs">
                        {probe.http_status ?? "—"}
                      </TableCell>
                      <TableCell className="text-xs">
                        {probe.whmcs_result ?? "—"}
                      </TableCell>
                      <TableCell className="text-xs">
                        {probe.latency_ms != null
                          ? `${probe.latency_ms} ms`
                          : "—"}
                      </TableCell>
                      <TableCell
                        className="max-w-md truncate text-xs text-slate-600"
                        title={probe.message ?? ""}
                      >
                        {probe.ok ? (
                          <span className="text-emerald-700">OK</span>
                        ) : (
                          <span className="text-red-600">
                            {probe.message ||
                              `Permission required: ${probe.required_permission}`}
                          </span>
                        )}
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
            <div className="text-xs text-slate-500">
              If an action shows <span className="font-semibold">fail</span> with a
              message like{" "}
              <span className="font-mono">
                "API action '…' is not allowed"
              </span>
              , open{" "}
              <span className="font-mono">
                WHMCS → Setup → Staff Management → API Roles
              </span>{" "}
              and enable the listed permission on the role assigned to this API
              identifier.
            </div>
          </div>
        ) : (
          <div className="text-sm text-slate-500">
            Click <span className="font-semibold">Probe all actions</span> to run
            a diagnostic across every WHMCS action the dashboard uses (profile,
            services, invoices, domains, tickets, emails, departments, domain
            whois). Optionally pass a real client email to also test
            client-scoped endpoints against that user.
          </div>
        )}
      </SectionCard>

      <SectionCard
        title="Filters"
        description="Narrow the log list by action name, status, or user."
        actions={refreshAction}
      >
        <div className="grid grid-cols-1 gap-4 md:grid-cols-3">
          <Field label="Action">
            <TextInput
              placeholder="e.g. GetClientsDetails"
              value={actionFilter}
              onChange={(e) => {
                setPage(0);
                setActionFilter(e.target.value);
              }}
            />
          </Field>
          <Field label="Status">
            <Select
              value={statusFilter}
              onChange={(e) => {
                setPage(0);
                setStatusFilter(e.target.value);
              }}
            >
              <option value="all">All</option>
              <option value="success">Success</option>
              <option value="error">Error</option>
            </Select>
          </Field>
          <Field label="User email">
            <TextInput
              placeholder="contains…"
              value={emailFilter}
              onChange={(e) => {
                setPage(0);
                setEmailFilter(e.target.value);
              }}
            />
          </Field>
        </div>
      </SectionCard>

      <div className="mt-6 bg-white rounded-2xl shadow-sm border border-slate-200 overflow-hidden">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead className="w-40">Time</TableHead>
              <TableHead>Action</TableHead>
              <TableHead>User</TableHead>
              <TableHead className="w-24">Status</TableHead>
              <TableHead className="w-20">HTTP</TableHead>
              <TableHead className="w-28">Duration</TableHead>
              <TableHead>Error</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {loading ? (
              <TableRow>
                <TableCell colSpan={7} className="py-8 text-center text-slate-500">
                  Loading…
                </TableCell>
              </TableRow>
            ) : items.length === 0 ? (
              <TableRow>
                <TableCell colSpan={7} className="py-8 text-center text-slate-500">
                  No logs found for the current filters.
                </TableCell>
              </TableRow>
            ) : (
              items.map((row) => (
                <TableRow key={row.id}>
                  <TableCell className="whitespace-nowrap text-xs">
                    {formatDate(row.created_at)}
                  </TableCell>
                  <TableCell className="font-mono text-xs">{row.action}</TableCell>
                  <TableCell className="text-xs">{row.user_email || "—"}</TableCell>
                  <TableCell>
                    <Badge tone={row.status === "success" ? "green" : "red"}>
                      {row.status}
                    </Badge>
                  </TableCell>
                  <TableCell className="text-xs">{row.http_status ?? "—"}</TableCell>
                  <TableCell className="text-xs">
                    {row.duration_ms != null ? `${row.duration_ms} ms` : "—"}
                  </TableCell>
                  <TableCell
                    className="max-w-sm truncate text-xs text-red-600"
                    title={row.error ?? ""}
                  >
                    {row.error ?? ""}
                  </TableCell>
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </div>

      <div className="mt-4 flex items-center justify-between text-sm text-slate-500">
        <div>
          Showing {items.length === 0 ? 0 : page * PAGE_SIZE + 1}–
          {page * PAGE_SIZE + items.length} of {total}
        </div>
        <div className="flex items-center gap-2">
          <button
            type="button"
            disabled={page === 0 || loading}
            onClick={() => setPage((p) => Math.max(0, p - 1))}
            className="px-3 py-1.5 rounded-lg border border-slate-300 text-slate-700 text-xs font-semibold bg-white hover:bg-slate-50 transition disabled:opacity-40"
          >
            Previous
          </button>
          <span className="px-2 py-1 text-xs">
            Page {page + 1} / {totalPages}
          </span>
          <button
            type="button"
            disabled={page + 1 >= totalPages || loading}
            onClick={() => setPage((p) => p + 1)}
            className="px-3 py-1.5 rounded-lg border border-slate-300 text-slate-700 text-xs font-semibold bg-white hover:bg-slate-50 transition disabled:opacity-40"
          >
            Next
          </button>
        </div>
      </div>
    </CmsLayout>
  );
}