// @File: src/pages/admin/cms/CmsSyncLogs.tsx
// @Desc: Cross-module sync log viewer. Lists the latest entries from
//        ``module_sync_logs`` with filters for module / type / status,
//        and a row-level "View raw" action that opens the masked raw
//        response in a modal.
import { useCallback, useEffect, useState } from "react";
import { Loader2, ScrollText, X, RefreshCw } from "lucide-react";
import { toast } from "sonner";
import CmsLayout from "./CmsLayout";
import { PageHeader, SectionCard } from "./ui";
import {
  getLog,
  listLogs,
  type ModuleSyncLogDetail,
  type ModuleSyncLogItem,
  type SyncStatus,
} from "@/lib/moduleSyncApi";

const MODULES = [
  { value: "", label: "All modules" },
  { value: "uptimerobot", label: "UptimeRobot" },
  { value: "bizmail360", label: "Bizmail360" },
  { value: "whatsapp", label: "WhatsApp" },
];

const TYPES = [
  { value: "", label: "All types" },
  { value: "clients", label: "Clients" },
  { value: "accounts", label: "Accounts" },
  { value: "domains", label: "Domains" },
];

const STATUSES: { value: "" | SyncStatus; label: string }[] = [
  { value: "", label: "All statuses" },
  { value: "ok", label: "OK" },
  { value: "failed", label: "Failed" },
  { value: "skipped", label: "Skipped" },
];

function fmt(dt: string | null): string {
  if (!dt) return "—";
  try {
    return new Date(dt).toLocaleString();
  } catch {
    return dt;
  }
}

function statusClass(status: string): string {
  if (status === "ok") return "bg-emerald-100 text-emerald-700 border-emerald-200";
  if (status === "failed") return "bg-red-100 text-red-700 border-red-200";
  return "bg-slate-100 text-slate-600 border-slate-200";
}

export default function CmsSyncLogs() {
  const [module, setModule] = useState("");
  const [syncType, setSyncType] = useState("");
  const [status, setStatus] = useState<"" | SyncStatus>("");
  const [items, setItems] = useState<ModuleSyncLogItem[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [detail, setDetail] = useState<ModuleSyncLogDetail | null>(null);
  const [loadingDetail, setLoadingDetail] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const res = await listLogs({
        module_name: module || undefined,
        sync_type: syncType || undefined,
        status: (status || undefined) as SyncStatus | undefined,
        limit: 200,
      });
      setItems(res.items);
      setTotal(res.total);
    } catch (e) {
      toast.error(`Load failed: ${e instanceof Error ? e.message : e}`);
    } finally {
      setLoading(false);
    }
  }, [module, syncType, status]);

  useEffect(() => {
    void load();
  }, [load]);

  const openDetail = async (id: number) => {
    setLoadingDetail(true);
    try {
      const d = await getLog(id);
      setDetail(d);
    } catch (e) {
      toast.error(`Load detail failed: ${e instanceof Error ? e.message : e}`);
    } finally {
      setLoadingDetail(false);
    }
  };

  return (
    <CmsLayout>
      <PageHeader
        title="Module Sync Logs"
        description="Every automatic or manual sync across all reseller modules."
        icon={<ScrollText className="h-6 w-6" />}
      />

      <SectionCard
        title="Sync History"
        description={`${total} total entries — showing up to 200 most recent.`}
        actions={
          <button
            type="button"
            onClick={() => void load()}
            className="inline-flex items-center gap-2 rounded-md border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50"
          >
            <RefreshCw className="h-4 w-4" /> Refresh
          </button>
        }
      >
        <div className="flex flex-wrap gap-3">
          <select
            className="rounded-md border border-slate-300 px-3 py-2 text-sm"
            value={module}
            onChange={(e) => setModule(e.target.value)}
          >
            {MODULES.map((o) => (
              <option key={o.value} value={o.value}>
                {o.label}
              </option>
            ))}
          </select>
          <select
            className="rounded-md border border-slate-300 px-3 py-2 text-sm"
            value={syncType}
            onChange={(e) => setSyncType(e.target.value)}
          >
            {TYPES.map((o) => (
              <option key={o.value} value={o.value}>
                {o.label}
              </option>
            ))}
          </select>
          <select
            className="rounded-md border border-slate-300 px-3 py-2 text-sm"
            value={status}
            onChange={(e) => setStatus(e.target.value as "" | SyncStatus)}
          >
            {STATUSES.map((o) => (
              <option key={o.value} value={o.value}>
                {o.label}
              </option>
            ))}
          </select>
        </div>

        <div className="overflow-auto rounded-md border border-slate-200 bg-white">
          {loading ? (
            <div className="flex items-center gap-2 p-6 text-slate-500">
              <Loader2 className="h-4 w-4 animate-spin" /> Loading…
            </div>
          ) : items.length === 0 ? (
            <div className="p-6 text-sm text-slate-500">No log entries match the filters.</div>
          ) : (
            <table className="min-w-full text-left text-sm">
              <thead className="border-b border-slate-200 bg-slate-50 text-xs uppercase text-slate-500">
                <tr>
                  <th className="px-3 py-2">Started</th>
                  <th className="px-3 py-2">Module</th>
                  <th className="px-3 py-2">Type</th>
                  <th className="px-3 py-2">Status</th>
                  <th className="px-3 py-2">Items</th>
                  <th className="px-3 py-2">Source</th>
                  <th className="px-3 py-2">Actor</th>
                  <th className="px-3 py-2">Duration</th>
                  <th className="px-3 py-2">Error</th>
                  <th className="px-3 py-2"></th>
                </tr>
              </thead>
              <tbody className="divide-y divide-slate-100 text-slate-700">
                {items.map((l) => (
                  <tr key={l.id}>
                    <td className="whitespace-nowrap px-3 py-2">{fmt(l.started_at)}</td>
                    <td className="px-3 py-2 font-medium">{l.module_name}</td>
                    <td className="px-3 py-2">{l.sync_type}</td>
                    <td className="px-3 py-2">
                      <span className={`inline-flex rounded-full border px-2 py-0.5 text-xs ${statusClass(l.status)}`}>
                        {l.status}
                      </span>
                    </td>
                    <td className="px-3 py-2">{l.items_fetched}</td>
                    <td className="px-3 py-2">{l.triggered_by}</td>
                    <td className="px-3 py-2">{l.actor_email ?? "—"}</td>
                    <td className="px-3 py-2">{l.duration_ms} ms</td>
                    <td className="px-3 py-2 text-red-600">{l.error_message ?? ""}</td>
                    <td className="px-3 py-2">
                      <button
                        type="button"
                        onClick={() => void openDetail(l.id)}
                        className="rounded-md border border-slate-300 px-2 py-1 text-xs text-slate-700 hover:bg-slate-50"
                      >
                        View raw
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </SectionCard>

      {detail ? (
        <div className="fixed inset-0 z-40 flex items-center justify-center bg-black/40 p-4">
          <div className="max-h-[85vh] w-full max-w-3xl overflow-hidden rounded-lg bg-white shadow-xl">
            <div className="flex items-center justify-between border-b border-slate-200 px-4 py-3">
              <div>
                <h4 className="text-sm font-semibold text-slate-800">
                  Log #{detail.id} — {detail.module_name} / {detail.sync_type}
                </h4>
                <p className="text-xs text-slate-500">
                  {fmt(detail.started_at)} · {detail.status} · {detail.items_fetched} items · {detail.duration_ms} ms
                </p>
              </div>
              <button
                type="button"
                onClick={() => setDetail(null)}
                className="rounded p-1 text-slate-500 hover:bg-slate-100"
                aria-label="Close"
              >
                <X className="h-4 w-4" />
              </button>
            </div>
            <div className="max-h-[70vh] overflow-auto p-4 text-xs">
              {loadingDetail ? (
                <div className="flex items-center gap-2 text-slate-500">
                  <Loader2 className="h-4 w-4 animate-spin" /> Loading…
                </div>
              ) : (
                <>
                  {detail.error_message ? (
                    <div className="mb-3 rounded-md border border-red-200 bg-red-50 p-3 text-red-700">
                      <span className="font-semibold">Error:</span> {detail.error_message}
                    </div>
                  ) : null}
                  <pre className="whitespace-pre-wrap break-words rounded-md bg-slate-900 p-3 text-slate-100">
                    {detail.raw_response || "(no raw response captured)"}
                  </pre>
                  <p className="mt-2 text-[11px] text-slate-500">
                    Tokens, API keys and password-like values are automatically masked in this view.
                  </p>
                </>
              )}
            </div>
          </div>
        </div>
      ) : null}
    </CmsLayout>
  );
}