"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { ArrowLeft, ArrowRight, ArrowUpDown, ChevronDown, ChevronUp, Clock3 } from "lucide-react";
import { extractChangeRows } from "@open-mercato/core/modules/audit_logs/lib/changeRows";
import { deriveActionLogActionType, deriveActionLogSource } from "@open-mercato/core/modules/audit_logs/lib/projections";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { apiCallOrThrow, readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
import { flash } from "@open-mercato/ui/backend/FlashMessages";
import { Button } from "@open-mercato/ui/primitives/button";
import { Badge } from "@open-mercato/ui/primitives/badge";
import { ErrorMessage, LoadingMessage, TabEmptyState } from "@open-mercato/ui/backend/detail";
import { ChangelogFilters } from "./ChangelogFilters.js";
import { ChangelogKpiCards } from "./ChangelogKpiCards.js";
import { ChangelogEntryRow } from "./ChangelogEntryRow.js";
import { formatChangelogValue } from "./changelogValues.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
const PAGE_SIZE = 50;
const ACTION_OPTIONS = [
  { value: "create", key: "customers.changelog.actions.create", fallback: "Create" },
  { value: "edit", key: "customers.changelog.actions.edit", fallback: "Edit" },
  { value: "delete", key: "customers.changelog.actions.delete", fallback: "Delete" },
  { value: "assign", key: "customers.changelog.actions.assign", fallback: "Assign" }
];
const CRITICAL_FIELDS = ["status", "lifecycleStage", "ownerUserId", "temperature", "source", "renewalQuarter"];
const HEADER_COLUMNS = [
  { field: "createdAt", key: "customers.changelog.col.when", fallback: "When" },
  { field: "user", key: "customers.changelog.col.user", fallback: "User" },
  { field: "action", key: "customers.changelog.col.action", fallback: "Action" },
  { field: "field", key: "customers.changelog.col.change", fallback: "What changed" },
  { field: "source", key: "customers.changelog.col.source", fallback: "Source", align: "right" }
];
function formatFieldLabel(fieldName) {
  return fieldName.replace(/\./g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().replace(/^\w/, (char) => char.toUpperCase());
}
function mergeFilterOptions(...groups) {
  const options = /* @__PURE__ */ new Map();
  groups.flat().forEach((option) => {
    options.set(option.value, option);
  });
  return Array.from(options.values()).sort(
    (left, right) => left.label.localeCompare(right.label, void 0, { sensitivity: "base" })
  );
}
function mapAuditActionToEntry(action) {
  const changes = extractChangeRows(action.changes, action.snapshotBefore).map((change) => ({
    fieldName: change.field,
    oldValue: formatChangelogValue(change.from),
    newValue: formatChangelogValue(change.to)
  }));
  return {
    id: action.id,
    createdAt: action.createdAt,
    actorUserId: action.actorUserId,
    actorUserName: action.actorUserName,
    actionType: deriveActionLogActionType(action),
    source: deriveActionLogSource(action.context, action.actorUserId),
    description: action.actionLabel,
    changes
  };
}
function startOfDay(daysAgo = 0) {
  const date = /* @__PURE__ */ new Date();
  date.setHours(0, 0, 0, 0);
  if (daysAgo > 0) date.setDate(date.getDate() - daysAgo);
  return date;
}
function computeRangeStart(range) {
  const days = Number.parseInt(range.replace("d", ""), 10);
  const date = /* @__PURE__ */ new Date();
  date.setHours(0, 0, 0, 0);
  date.setDate(date.getDate() - (Number.isFinite(days) ? days : 90));
  return date;
}
function buildQueryUrl({
  entityId,
  entityType,
  dateRange,
  filters,
  limit,
  offset,
  sorting,
  includeTotal,
  before,
  after
}) {
  const params = new URLSearchParams({
    resourceKind: `customers.${entityType}`,
    resourceId: entityId,
    includeRelated: "true",
    limit: String(limit),
    offset: String(offset ?? 0),
    sortField: sorting?.field ?? "createdAt",
    sortDir: sorting?.dir ?? "desc",
    after: after ?? computeRangeStart(dateRange).toISOString()
  });
  if (includeTotal) params.set("includeTotal", "true");
  if (before) params.set("before", before);
  if (filters.fieldNames.length > 0) params.set("fieldName", filters.fieldNames.join(","));
  if (filters.actorUserIds.length > 0) params.set("actorUserId", filters.actorUserIds.join(","));
  if (filters.actionTypes.length > 0) params.set("actionType", filters.actionTypes.join(","));
  return `/api/audit_logs/audit-logs/actions?${params.toString()}`;
}
function buildExportUrl({
  entityId,
  entityType,
  filters,
  dateRange,
  sorting
}) {
  const params = new URLSearchParams({
    resourceKind: `customers.${entityType}`,
    resourceId: entityId,
    includeRelated: "true",
    limit: "1000",
    sortField: sorting.field,
    sortDir: sorting.dir,
    after: computeRangeStart(dateRange).toISOString()
  });
  if (filters.fieldNames.length > 0) params.set("fieldName", filters.fieldNames.join(","));
  if (filters.actorUserIds.length > 0) params.set("actorUserId", filters.actorUserIds.join(","));
  if (filters.actionTypes.length > 0) params.set("actionType", filters.actionTypes.join(","));
  return `/api/audit_logs/audit-logs/actions/export?${params.toString()}`;
}
function groupEntriesByDay(entries, t) {
  const groups = /* @__PURE__ */ new Map();
  entries.forEach((entry) => {
    const date = new Date(entry.createdAt);
    const key = Number.isNaN(date.getTime()) ? entry.createdAt : date.toDateString();
    const bucket = groups.get(key) ?? [];
    bucket.push(entry);
    groups.set(key, bucket);
  });
  const today = (/* @__PURE__ */ new Date()).toDateString();
  const yesterdayDate = /* @__PURE__ */ new Date();
  yesterdayDate.setDate(yesterdayDate.getDate() - 1);
  const yesterday = yesterdayDate.toDateString();
  return Array.from(groups.entries()).map(([key, items]) => ({
    key,
    label: key === today ? t("customers.changelog.groupLabel.today", "TODAY") : key === yesterday ? t("customers.changelog.groupLabel.yesterday", "YESTERDAY") : new Date(key).toLocaleDateString(void 0, {
      weekday: "long",
      day: "numeric",
      month: "long",
      year: "numeric"
    }).toUpperCase(),
    items
  }));
}
function SortIcon({ active, dir }) {
  if (!active) return /* @__PURE__ */ jsx(ArrowUpDown, { className: "size-3 text-muted-foreground" });
  return dir === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { className: "size-3 text-foreground" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "size-3 text-foreground" });
}
function ChangelogTab({ entityId, entityType }) {
  const t = useT();
  const [filters, setFilters] = React.useState({
    fieldNames: [],
    actorUserIds: [],
    actionTypes: [],
    dateRange: "90d"
  });
  const [entries, setEntries] = React.useState([]);
  const [totalCount, setTotalCount] = React.useState(0);
  const [todayCount, setTodayCount] = React.useState(0);
  const [yesterdayCount, setYesterdayCount] = React.useState(0);
  const [fieldOptions, setFieldOptions] = React.useState([]);
  const [userOptions, setUserOptions] = React.useState([]);
  const [actionOptions, setActionOptions] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [exporting, setExporting] = React.useState(false);
  const [pageIndex, setPageIndex] = React.useState(0);
  const [sorting, setSorting] = React.useState({
    field: "createdAt",
    dir: "desc"
  });
  const days = React.useMemo(() => Number.parseInt(filters.dateRange.replace("d", ""), 10) || 90, [filters.dateRange]);
  const loadTab = React.useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const todayStart = startOfDay(0).toISOString();
      const yesterdayStart = startOfDay(1).toISOString();
      const [mainResponse, todayResponse, yesterdayResponse] = await Promise.all([
        readApiResultOrThrow(
          buildQueryUrl({
            entityId,
            entityType,
            dateRange: filters.dateRange,
            filters,
            limit: PAGE_SIZE,
            offset: pageIndex * PAGE_SIZE,
            sorting,
            includeTotal: true
          })
        ),
        readApiResultOrThrow(
          buildQueryUrl({
            entityId,
            entityType,
            dateRange: filters.dateRange,
            filters,
            limit: 1,
            sorting,
            includeTotal: true,
            after: todayStart
          })
        ).catch(() => ({ items: [], total: 0 })),
        readApiResultOrThrow(
          buildQueryUrl({
            entityId,
            entityType,
            dateRange: filters.dateRange,
            filters,
            limit: 1,
            sorting,
            includeTotal: true,
            after: yesterdayStart,
            before: todayStart
          })
        ).catch(() => ({ items: [], total: 0 }))
      ]);
      const mappedEntries = Array.isArray(mainResponse.items) ? mainResponse.items.map(mapAuditActionToEntry) : [];
      setEntries(mappedEntries);
      setTotalCount(typeof mainResponse.total === "number" ? mainResponse.total : mappedEntries.length);
      setTodayCount(typeof todayResponse.total === "number" ? todayResponse.total : 0);
      setYesterdayCount(typeof yesterdayResponse.total === "number" ? yesterdayResponse.total : 0);
      const nextFieldOptions = mergeFilterOptions(
        filters.fieldNames.map((fieldName) => ({ value: fieldName, label: formatFieldLabel(fieldName) })),
        Array.from(
          new Set(
            mappedEntries.flatMap((entry) => entry.changes.map((change) => change.fieldName))
          )
        ).sort((left, right) => left.localeCompare(right)).map((fieldName) => ({ value: fieldName, label: formatFieldLabel(fieldName) }))
      );
      const nextActionOptions = ACTION_OPTIONS.filter((option) => filters.actionTypes.includes(option.value) || mappedEntries.some((entry) => entry.actionType === option.value)).map((option) => ({
        value: option.value,
        label: t(option.key, option.fallback)
      }));
      setFieldOptions(nextFieldOptions);
      setUserOptions(
        (current) => mergeFilterOptions(
          current.filter((option) => filters.actorUserIds.includes(option.value)),
          Array.from(
            new Map(
              mappedEntries.filter((entry) => entry.actorUserId && entry.actorUserName).map((entry) => [entry.actorUserId, entry.actorUserName])
            ).entries()
          ).map(([value, label]) => ({ value, label }))
        )
      );
      setActionOptions(nextActionOptions);
    } catch (loadError) {
      setEntries([]);
      setTotalCount(0);
      setTodayCount(0);
      setYesterdayCount(0);
      setFieldOptions([]);
      setUserOptions([]);
      setActionOptions([]);
      setError(t("customers.changelog.error", "Failed to load change log"));
    } finally {
      setLoading(false);
    }
  }, [entityId, entityType, filters, pageIndex, sorting, t]);
  React.useEffect(() => {
    void loadTab();
  }, [loadTab]);
  const showGroupedEntries = sorting.field === "createdAt";
  const groupedEntries = React.useMemo(() => groupEntriesByDay(entries, t), [entries, t]);
  const uniqueUsers = React.useMemo(
    () => new Set(entries.map((entry) => entry.actorUserId).filter((value) => Boolean(value))).size,
    [entries]
  );
  const criticalFieldCount = React.useMemo(
    () => entries.filter((entry) => entry.changes.some((change) => CRITICAL_FIELDS.includes(change.fieldName))).length,
    [entries]
  );
  const criticalFieldLabel = React.useMemo(
    () => CRITICAL_FIELDS.map((fieldName) => formatFieldLabel(fieldName)).slice(0, 3).join(", "),
    []
  );
  const previousPageLabel = React.useMemo(() => {
    if (sorting.field !== "createdAt") return t("customers.changelog.previous", "Previous");
    return sorting.dir === "desc" ? t("customers.changelog.newer", "Newer") : t("customers.changelog.older", "Older");
  }, [sorting, t]);
  const nextPageLabel = React.useMemo(() => {
    if (sorting.field !== "createdAt") return t("customers.changelog.next", "Next");
    return sorting.dir === "desc" ? t("customers.changelog.older", "Older") : t("customers.changelog.newer", "Newer");
  }, [sorting, t]);
  const shownCount = entries.length;
  const hasOlder = (pageIndex + 1) * PAGE_SIZE < totalCount;
  const hasNewer = pageIndex > 0;
  const updateFilters = React.useCallback((partial) => {
    setFilters((current) => ({ ...current, ...partial }));
    setPageIndex(0);
  }, []);
  const handleOlder = React.useCallback(() => {
    if (!hasOlder) return;
    setPageIndex((current) => current + 1);
  }, [hasOlder]);
  const handleNewer = React.useCallback(() => {
    if (!hasNewer) return;
    setPageIndex((current) => Math.max(current - 1, 0));
  }, [hasNewer]);
  const handleSort = React.useCallback((field) => {
    setSorting((current) => {
      if (current.field === field) {
        return {
          field,
          dir: current.dir === "desc" ? "asc" : "desc"
        };
      }
      return {
        field,
        dir: field === "createdAt" ? "desc" : "asc"
      };
    });
    setPageIndex(0);
  }, []);
  const handleExport = React.useCallback(async () => {
    setExporting(true);
    try {
      const response = await apiCallOrThrow(
        buildExportUrl({
          entityId,
          entityType,
          filters,
          dateRange: filters.dateRange,
          sorting
        }),
        void 0,
        {
          parse: async (res) => res.text()
        }
      );
      const body = response.result ?? "";
      const blob = new Blob([body], { type: "text/csv;charset=utf-8" });
      const blobUrl = URL.createObjectURL(blob);
      const anchor = document.createElement("a");
      anchor.href = blobUrl;
      anchor.download = "changelog-export.csv";
      document.body.appendChild(anchor);
      anchor.click();
      anchor.remove();
      URL.revokeObjectURL(blobUrl);
    } catch (exportError) {
      logger.error("customers.changelog.export failed", { exportError });
      flash(t("customers.changelog.exportError", "Failed to export change log"), "error");
    } finally {
      setExporting(false);
    }
  }, [entityId, entityType, filters, sorting, t]);
  return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
    /* @__PURE__ */ jsx(
      ChangelogFilters,
      {
        dateRange: filters.dateRange,
        fieldNames: filters.fieldNames,
        actorUserIds: filters.actorUserIds,
        actionTypes: filters.actionTypes,
        fieldOptions,
        userOptions,
        actionOptions,
        exportDisabled: exporting,
        onDateRangeChange: (value) => updateFilters({ dateRange: value }),
        onFieldNamesChange: (value) => updateFilters({ fieldNames: value }),
        onActorUserIdsChange: (value) => updateFilters({ actorUserIds: value }),
        onActionTypesChange: (value) => updateFilters({ actionTypes: value }),
        onExport: handleExport
      }
    ),
    /* @__PURE__ */ jsx(
      ChangelogKpiCards,
      {
        loading,
        totalCount,
        todayCount,
        yesterdayCount,
        uniqueUsers,
        criticalFieldCount,
        criticalFieldLabel,
        dateRangeDays: days
      }
    ),
    /* @__PURE__ */ jsxs("div", { className: "overflow-hidden rounded-xl border bg-card", children: [
      /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b px-5 py-4", children: [
        /* @__PURE__ */ jsx(Clock3, { className: "size-4 text-muted-foreground" }),
        /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-foreground", children: t("customers.changelog.title", "Change log") }),
        /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: totalCount })
      ] }),
      /* @__PURE__ */ jsx("div", { className: "grid grid-cols-[92px_190px_120px_1fr_80px] gap-3 border-b bg-muted/20 px-5 py-2 text-overline font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: HEADER_COLUMNS.map((column) => {
        const isActive = sorting.field === column.field;
        return /* @__PURE__ */ jsxs(
          Button,
          {
            type: "button",
            variant: "ghost",
            size: "sm",
            onClick: () => handleSort(column.field),
            className: `h-auto gap-1 rounded-none px-0 py-0 text-overline font-semibold uppercase tracking-[0.12em] text-muted-foreground hover:bg-transparent ${column.align === "right" ? "justify-end" : "justify-start"}`,
            children: [
              /* @__PURE__ */ jsx("span", { children: t(column.key, column.fallback) }),
              /* @__PURE__ */ jsx(SortIcon, { active: isActive, dir: sorting.dir })
            ]
          },
          column.field
        );
      }) }),
      loading && entries.length === 0 ? /* @__PURE__ */ jsx(LoadingMessage, { label: t("customers.changelog.loading", "Loading changes..."), className: "min-h-[220px] justify-center" }) : error ? /* @__PURE__ */ jsx(ErrorMessage, { label: error, className: "m-5" }) : entries.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-5", children: /* @__PURE__ */ jsx(
        TabEmptyState,
        {
          title: t("customers.changelog.emptyTitle", "No changes in this period"),
          description: t("customers.changelog.empty", "No changes recorded in this period.")
        }
      ) }) : /* @__PURE__ */ jsx("div", { children: showGroupedEntries ? groupedEntries.map((group) => /* @__PURE__ */ jsxs("div", { children: [
        /* @__PURE__ */ jsx("div", { className: "border-b bg-muted/10 px-5 py-2 text-overline font-semibold uppercase tracking-[0.12em] text-muted-foreground", children: group.label }),
        group.items.map((entry) => /* @__PURE__ */ jsx("div", { className: "border-b last:border-b-0", children: /* @__PURE__ */ jsx(ChangelogEntryRow, { entry }) }, entry.id))
      ] }, group.key)) : entries.map((entry) => /* @__PURE__ */ jsx("div", { className: "border-b last:border-b-0", children: /* @__PURE__ */ jsx(ChangelogEntryRow, { entry }) }, entry.id)) }),
      /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 border-t px-5 py-4 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between", children: [
        /* @__PURE__ */ jsx("span", { children: t("customers.changelog.showingWithPeriod", "Showing {{shown}} of {{total}} entries \xB7 last {{days}} days", {
          shown: shownCount,
          total: totalCount,
          days
        }) }),
        /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
          /* @__PURE__ */ jsxs(
            Button,
            {
              type: "button",
              variant: "outline",
              size: "sm",
              onClick: handleNewer,
              disabled: !hasNewer || loading,
              className: "h-8 rounded-lg px-3 text-xs",
              children: [
                /* @__PURE__ */ jsx(ArrowLeft, { className: "mr-1.5 size-3.5" }),
                previousPageLabel
              ]
            }
          ),
          /* @__PURE__ */ jsxs(
            Button,
            {
              type: "button",
              variant: "outline",
              size: "sm",
              onClick: handleOlder,
              disabled: !hasOlder || loading,
              className: "h-8 rounded-lg px-3 text-xs",
              children: [
                nextPageLabel,
                /* @__PURE__ */ jsx(ArrowRight, { className: "ml-1.5 size-3.5" })
              ]
            }
          )
        ] })
      ] })
    ] })
  ] });
}
var ChangelogTab_default = ChangelogTab;
export {
  ChangelogTab,
  ChangelogTab_default as default
};
//# sourceMappingURL=ChangelogTab.js.map
