"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { usePathname, useRouter } from "next/navigation";
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
import { FormHeader } from "@open-mercato/ui/backend/forms";
import { Card, CardHeader, CardTitle, CardContent } from "@open-mercato/ui/primitives/card";
import { Badge } from "@open-mercato/ui/primitives/badge";
import { StatusBadge } from "@open-mercato/ui/primitives/status-badge";
import { Button } from "@open-mercato/ui/primitives/button";
import { LogList } from "@open-mercato/ui/backend/LogList";
import { Progress } from "@open-mercato/ui/primitives/progress";
import { Pagination } from "@open-mercato/ui/primitives/pagination";
import { Spinner } from "@open-mercato/ui/primitives/spinner";
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
import { useGuardedMutation } from "@open-mercato/ui/backend/injection/useGuardedMutation";
import { flash } from "@open-mercato/ui/backend/FlashMessages";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { LoadingMessage, ErrorMessage, RecordNotFoundState } from "@open-mercato/ui/backend/detail";
import { useAppEvent } from "@open-mercato/ui/backend/injection/useAppEvent";
import { RotateCcw, XCircle } from "lucide-react";
import { getSyncRunStatusVariant } from "../../../../lib/syncRunStatus.js";
function formatEtaSeconds(seconds) {
  if (seconds < 60) return `${seconds}s`;
  if (seconds < 3600) return `${Math.ceil(seconds / 60)}m`;
  const hours = Math.floor(seconds / 3600);
  const minutes = Math.ceil(seconds % 3600 / 60);
  return `${hours}h ${minutes}m`;
}
function resolveRouteId(value) {
  if (Array.isArray(value)) return value[0];
  return value;
}
function resolvePathnameId(pathname) {
  const parts = pathname.split("/").filter(Boolean);
  const runId = parts.at(-1);
  if (!runId || runId === "runs" || runId === "data-sync") return void 0;
  return decodeURIComponent(runId);
}
const LOG_PAGE_SIZE = 50;
function SyncRunDetailPage({ params }) {
  const pathname = usePathname();
  const router = useRouter();
  const runId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname);
  const t = useT();
  const { runMutation } = useGuardedMutation({
    contextId: "data_sync.runDetail"
  });
  const [run, setRun] = React.useState(null);
  const [isLoading, setIsLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [isNotFound, setIsNotFound] = React.useState(false);
  const [logs, setLogs] = React.useState([]);
  const [isLoadingLogs, setIsLoadingLogs] = React.useState(false);
  const [logsTotal, setLogsTotal] = React.useState(0);
  const [logsPage, setLogsPage] = React.useState(1);
  const logsPageRef = React.useRef(1);
  const resolveCurrentRunId = React.useCallback(() => {
    return runId ?? (typeof window !== "undefined" ? resolvePathnameId(window.location.pathname) : void 0);
  }, [runId]);
  const loadRun = React.useCallback(async () => {
    const currentRunId = resolveCurrentRunId();
    if (!currentRunId) {
      setError(t("data_sync.runs.detail.loadError"));
      setIsLoading(false);
      return;
    }
    setIsNotFound(false);
    const call = await apiCall(
      `/api/data_sync/runs/${encodeURIComponent(currentRunId)}`,
      void 0,
      { fallback: null }
    );
    if (!call.ok || !call.result) {
      if (call.status === 404) {
        setIsNotFound(true);
      } else {
        setError(t("data_sync.runs.detail.loadError"));
      }
      setIsLoading(false);
      return;
    }
    setRun(call.result);
    setIsLoading(false);
  }, [resolveCurrentRunId, t]);
  const loadLogs = React.useCallback(async (page) => {
    const currentRunId = resolveCurrentRunId();
    if (!currentRunId) return;
    const targetPage = page ?? logsPageRef.current;
    setIsLoadingLogs(true);
    const params2 = new URLSearchParams({ runId: currentRunId, pageSize: String(LOG_PAGE_SIZE), page: String(targetPage) });
    const call = await apiCall(
      `/api/integrations/logs?${params2.toString()}`,
      void 0,
      { fallback: { items: [], total: 0 } }
    );
    if (call.ok && call.result) {
      setLogs(call.result.items);
      if (typeof call.result.total === "number") setLogsTotal(call.result.total);
      logsPageRef.current = targetPage;
      setLogsPage(targetPage);
    }
    setIsLoadingLogs(false);
  }, [resolveCurrentRunId]);
  React.useEffect(() => {
    void loadRun();
    void loadLogs();
  }, [loadRun, loadLogs]);
  const handleProgressEvent = React.useCallback((payload) => {
    const eventJobId = typeof payload.jobId === "string" ? payload.jobId : null;
    if (!eventJobId) return;
    setRun((current) => {
      if (!current?.progressJobId || current.progressJobId !== eventJobId) return current;
      return {
        ...current,
        status: payload.status ?? current.status,
        progressJob: {
          id: eventJobId,
          status: payload.status ?? current.progressJob?.status ?? current.status,
          progressPercent: payload.progressPercent ?? current.progressJob?.progressPercent ?? 0,
          processedCount: payload.processedCount ?? current.progressJob?.processedCount ?? 0,
          totalCount: payload.totalCount ?? current.progressJob?.totalCount ?? null,
          etaSeconds: payload.etaSeconds ?? current.progressJob?.etaSeconds ?? null,
          meta: payload.meta ?? current.progressJob?.meta ?? null
        }
      };
    });
  }, []);
  useAppEvent("progress.job.updated", (event) => {
    handleProgressEvent(event.payload);
  }, [handleProgressEvent]);
  useAppEvent("progress.job.started", (event) => {
    handleProgressEvent(event.payload);
  }, [handleProgressEvent]);
  useAppEvent("progress.job.completed", (event) => {
    handleProgressEvent(event.payload);
    void loadRun();
    void loadLogs();
  }, [handleProgressEvent, loadLogs, loadRun]);
  useAppEvent("progress.job.failed", (event) => {
    handleProgressEvent(event.payload);
    void loadRun();
    void loadLogs();
  }, [handleProgressEvent, loadLogs, loadRun]);
  useAppEvent("progress.job.cancelled", (event) => {
    handleProgressEvent(event.payload);
    void loadRun();
    void loadLogs();
  }, [handleProgressEvent, loadLogs, loadRun]);
  useAppEvent("om:bridge:reconnected", () => {
    void loadRun();
    void loadLogs();
  }, [loadLogs, loadRun]);
  const handleCancel = React.useCallback(async () => {
    const currentRunId = resolveCurrentRunId();
    if (!currentRunId) return;
    const call = await runMutation({
      // optimistic-lock-exempt: run lifecycle action endpoint (cancel), not a concurrent record edit
      operation: () => apiCall(`/api/data_sync/runs/${encodeURIComponent(currentRunId)}/cancel`, {
        method: "POST"
      }, { fallback: null }),
      mutationPayload: { runId: currentRunId },
      context: {
        operation: "update",
        actionId: "cancel-sync-run",
        runId: currentRunId
      }
    });
    if (call.ok) {
      flash(t("data_sync.runs.detail.cancelSuccess"), "success");
      void loadRun();
    } else {
      flash(t("data_sync.runs.detail.cancelError"), "error");
    }
  }, [resolveCurrentRunId, runMutation, t, loadRun]);
  const handleRetry = React.useCallback(async () => {
    const currentRunId = resolveCurrentRunId();
    if (!currentRunId) return;
    const call = await runMutation({
      // optimistic-lock-exempt: starts a new retry run (create), not a concurrent record edit
      operation: () => apiCall(`/api/data_sync/runs/${encodeURIComponent(currentRunId)}/retry`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ fromBeginning: false })
      }, { fallback: null }),
      mutationPayload: { runId: currentRunId, fromBeginning: false },
      context: {
        operation: "create",
        actionId: "retry-sync-run",
        runId: currentRunId
      }
    });
    if (call.ok && call.result) {
      flash(t("data_sync.runs.detail.retrySuccess"), "success");
      router.push(`/backend/data-sync/runs/${encodeURIComponent(call.result.id)}`);
    } else {
      flash(t("data_sync.runs.detail.retryError"), "error");
    }
  }, [resolveCurrentRunId, router, runMutation, t]);
  if (isLoading) return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(LoadingMessage, { label: t("data_sync.runs.detail.title") }) }) });
  if (isNotFound) {
    return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
      RecordNotFoundState,
      {
        label: t("data_sync.runs.detail.notFound", "Sync run not found."),
        backHref: "/backend/data-sync",
        backLabel: t("data_sync.runs.detail.back")
      }
    ) }) });
  }
  if (error || !run) return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(ErrorMessage, { label: error ?? t("data_sync.runs.detail.loadError") }) }) });
  const totalProcessed = run.createdCount + run.updatedCount + run.skippedCount + run.failedCount;
  const progressPercent = run.progressJob?.progressPercent ?? (run.status === "completed" ? 100 : 0);
  const progressStatus = run.progressJob?.status ?? run.status;
  const processedCount = run.progressJob?.processedCount ?? totalProcessed;
  const hasProgressTotal = typeof run.progressJob?.totalCount === "number" && run.progressJob.totalCount > 0;
  const etaLabel = run.progressJob?.etaSeconds && run.progressJob.etaSeconds > 0 ? formatEtaSeconds(run.progressJob.etaSeconds) : null;
  return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsxs(PageBody, { className: "space-y-6", children: [
    /* @__PURE__ */ jsx(
      FormHeader,
      {
        mode: "detail",
        backHref: "/backend/data-sync",
        backLabel: t("data_sync.runs.detail.back"),
        entityTypeLabel: t("data_sync.runs.detail.title"),
        title: `${run.integrationId} \u2014 ${run.entityType}`,
        statusBadge: /* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap gap-2", children: [
          /* @__PURE__ */ jsx(Badge, { variant: "outline", children: t(`data_sync.dashboard.direction.${run.direction}`) }),
          /* @__PURE__ */ jsx(StatusBadge, { variant: getSyncRunStatusVariant(run.status), children: t(`data_sync.dashboard.status.${run.status}`) }),
          run.triggeredBy ? /* @__PURE__ */ jsx(Badge, { variant: "outline", children: run.triggeredBy }) : null
        ] }),
        actionsContent: /* @__PURE__ */ jsxs(Fragment, { children: [
          run.status === "running" || run.status === "pending" ? /* @__PURE__ */ jsxs(Button, { type: "button", variant: "destructive", size: "sm", onClick: () => void handleCancel(), children: [
            /* @__PURE__ */ jsx(XCircle, { className: "mr-2 h-4 w-4" }),
            t("data_sync.runs.detail.cancel")
          ] }) : null,
          run.status === "failed" ? /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => void handleRetry(), children: [
            /* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4" }),
            t("data_sync.runs.detail.retry")
          ] }) : null
        ] })
      }
    ),
    /* @__PURE__ */ jsxs(Card, { children: [
      /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
        /* @__PURE__ */ jsx(CardTitle, { children: t("data_sync.runs.detail.progress") }),
        /* @__PURE__ */ jsx(StatusBadge, { variant: getSyncRunStatusVariant(progressStatus), children: t(`data_sync.dashboard.status.${progressStatus}`) })
      ] }) }),
      /* @__PURE__ */ jsxs(CardContent, { className: "space-y-3", children: [
        /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [
          /* @__PURE__ */ jsx("span", { className: "font-medium", children: hasProgressTotal ? t("data_sync.runs.detail.progress.percent", { percent: progressPercent }) : t("data_sync.runs.detail.progress.itemsProcessed", { count: processedCount }) }),
          etaLabel ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: t("data_sync.runs.detail.progress.eta", { eta: etaLabel }) }) : null
        ] }),
        hasProgressTotal ? /* @__PURE__ */ jsx(Progress, { value: progressPercent, className: "h-3" }) : /* @__PURE__ */ jsxs("div", { className: "relative h-3 w-full overflow-hidden rounded-full bg-secondary", children: [
          /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 w-1/2 animate-pulse rounded-full bg-primary/80" }),
          /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 w-1/3 rounded-full bg-primary/10" })
        ] }),
        /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 text-sm text-muted-foreground", children: [
          /* @__PURE__ */ jsx("span", { children: hasProgressTotal ? t("data_sync.runs.detail.progress.itemsProcessedTotal", {
            processed: processedCount,
            total: run.progressJob?.totalCount ?? 0
          }) : t("data_sync.runs.detail.progress.itemsProcessed", { count: processedCount }) }),
          /* @__PURE__ */ jsx("span", { children: t("data_sync.runs.detail.progress.batches", { count: run.batchesCompleted }) })
        ] })
      ] })
    ] }),
    /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-4", children: [
      /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { className: "pt-6 text-center", children: [
        /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-status-success-text", children: run.createdCount }),
        /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("data_sync.runs.detail.counters.created") })
      ] }) }),
      /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { className: "pt-6 text-center", children: [
        /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-status-info-text", children: run.updatedCount }),
        /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("data_sync.runs.detail.counters.updated") })
      ] }) }),
      /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { className: "pt-6 text-center", children: [
        /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-muted-foreground", children: run.skippedCount }),
        /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("data_sync.runs.detail.counters.skipped") })
      ] }) }),
      /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { className: "pt-6 text-center", children: [
        /* @__PURE__ */ jsx("div", { className: "text-2xl font-bold text-status-error-text", children: run.failedCount }),
        /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("data_sync.runs.detail.counters.failed") })
      ] }) })
    ] }),
    run.lastError && /* @__PURE__ */ jsxs(Card, { className: "border-status-error-border bg-status-error-bg", children: [
      /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { className: "text-status-error-text", children: t("data_sync.runs.detail.error") }) }),
      /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("pre", { className: "text-sm text-status-error-text whitespace-pre-wrap", children: run.lastError }) })
    ] }),
    /* @__PURE__ */ jsxs(Card, { children: [
      /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: t("data_sync.runs.detail.logs") }) }),
      /* @__PURE__ */ jsxs(CardContent, { children: [
        isLoadingLogs ? /* @__PURE__ */ jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(
          LogList,
          {
            entries: logs.map((log) => ({
              id: log.id,
              time: new Date(log.createdAt).toLocaleString(),
              level: log.level,
              message: log.message,
              body: log.payload ? /* @__PURE__ */ jsx("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md border bg-card p-3 text-xs", children: log.payload.kind === "export-item-failure" && typeof log.payload.summary === "string" ? log.payload.summary : JSON.stringify(log.payload, null, 2) }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("data_sync.runs.detail.logs.noPayload", "No payload recorded for this log entry.") })
            })),
            emptyMessage: t("data_sync.runs.detail.noLogs")
          }
        ),
        logsTotal > LOG_PAGE_SIZE && /* @__PURE__ */ jsx(
          Pagination,
          {
            className: "mt-4",
            page: logsPage,
            pageSize: LOG_PAGE_SIZE,
            total: logsTotal,
            onPageChange: (next) => {
              void loadLogs(next);
            }
          }
        )
      ] })
    ] })
  ] }) });
}
export {
  SyncRunDetailPage as default
};
//# sourceMappingURL=page.js.map
