"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { Pencil, Plus, Trash2, Truck } from "lucide-react";
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 { flash } from "@open-mercato/ui/backend/FlashMessages";
import { apiCall, withScopedApiRequestHeaders } from "@open-mercato/ui/backend/utils/apiCall";
import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimisticLock";
import { deleteCrud } from "@open-mercato/ui/backend/utils/crud";
import { useOrganizationScopeDetail } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
import {
  emitSalesDocumentTotalsRefresh,
  subscribeSalesDocumentTotalsRefresh
} from "@open-mercato/core/modules/sales/lib/frontend/documentTotalsEvents";
import { generateTempId } from "@open-mercato/core/modules/customers/lib/detailHelpers";
import { formatAddressString } from "@open-mercato/core/modules/customers/utils/addressFormat";
import { ShipmentDialog } from "./ShipmentDialog.js";
import { handleSectionMutationError, readRowUpdatedAt } from "./optimisticLock.js";
import { extractCustomFieldValues } from "./customFieldHelpers.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("sales");
const ADDRESS_SNAPSHOT_KEY = "shipmentAddressSnapshot";
const ADDRESS_FORMAT = "line_first";
function formatDisplayDate(value) {
  if (!value) return null;
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return null;
  return new Intl.DateTimeFormat(void 0, { dateStyle: "medium" }).format(date);
}
const formatShipmentAddress = (metadata) => {
  if (!metadata || typeof metadata !== "object") return null;
  const snapshot = metadata[ADDRESS_SNAPSHOT_KEY];
  if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot)) return null;
  const read = (key) => {
    const value = snapshot[key];
    return typeof value === "string" && value.trim().length ? value.trim() : null;
  };
  const addressValue = {
    addressLine1: read("addressLine1") ?? read("address_line1"),
    addressLine2: read("addressLine2") ?? read("address_line2"),
    buildingNumber: read("buildingNumber") ?? read("building_number"),
    flatNumber: read("flatNumber") ?? read("flat_number"),
    city: read("city"),
    region: read("region"),
    postalCode: read("postalCode") ?? read("postal_code"),
    country: read("country"),
    companyName: read("companyName") ?? read("company_name")
  };
  const summary = formatAddressString(addressValue, ADDRESS_FORMAT);
  return summary && summary.trim().length ? summary : null;
};
const resolveLineThumbnail = (item) => {
  const pickThumbnail = (...candidates) => {
    const found = candidates.find(
      (candidate) => typeof candidate === "string" && candidate.trim().length > 0
    );
    return found ?? null;
  };
  const metadata = typeof item.metadata === "object" && item.metadata !== null ? item.metadata : null;
  const snapshot = typeof item.catalog_snapshot === "object" && item.catalog_snapshot !== null ? item.catalog_snapshot : null;
  const productSnapshot = snapshot && typeof snapshot.product === "object" ? snapshot.product : null;
  const variantSnapshot = snapshot && typeof snapshot.variant === "object" ? snapshot.variant : null;
  const productThumb = pickThumbnail(
    metadata ? metadata.productThumbnail : null,
    productSnapshot ? productSnapshot.thumbnailUrl : null,
    productSnapshot ? productSnapshot.thumbnail_url : null
  );
  const variantThumb = pickThumbnail(
    metadata ? metadata.variantThumbnail : null,
    variantSnapshot ? variantSnapshot.thumbnailUrl : null,
    variantSnapshot ? variantSnapshot.thumbnail_url : null
  );
  const snapshotThumb = pickThumbnail(
    snapshot ? snapshot.thumbnailUrl : null,
    snapshot ? snapshot.thumbnail_url : null
  );
  return variantThumb ?? productThumb ?? snapshotThumb ?? null;
};
function SalesShipmentsSection({
  orderId,
  currencyCode,
  shippingAddressSnapshot,
  organizationId: organizationIdProp,
  tenantId: tenantIdProp,
  documentUpdatedAt,
  onActionChange,
  onAddComment
}) {
  const t = useT();
  const { organizationId, tenantId } = useOrganizationScopeDetail();
  const { confirm, ConfirmDialogElement } = useConfirmDialog();
  const resolvedOrganizationId = organizationIdProp ?? organizationId ?? null;
  const resolvedTenantId = tenantIdProp ?? tenantId ?? null;
  const addShipmentLabel = React.useMemo(
    () => t("sales.documents.shipments.add", "Add shipment"),
    [t]
  );
  const [shipments, setShipments] = React.useState([]);
  const [lines, setLines] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [dialogState, setDialogState] = React.useState(null);
  const lineMap = React.useMemo(() => new Map(lines.map((line) => [line.id, line])), [lines]);
  const shippedTotals = React.useMemo(() => {
    const totals = /* @__PURE__ */ new Map();
    shipments.forEach((shipment) => {
      shipment.items.forEach((item) => {
        const current = totals.get(item.orderLineId) ?? 0;
        totals.set(item.orderLineId, current + (Number.isFinite(item.quantity) ? item.quantity : 0));
      });
    });
    return totals;
  }, [shipments]);
  const computeAvailable = React.useCallback(
    (lineId, excludeShipmentId) => {
      const line = lineMap.get(lineId);
      if (!line) return 0;
      const shipped = shippedTotals.get(lineId) ?? 0;
      const editingShipment = excludeShipmentId ? shipments.find((entry) => entry.id === excludeShipmentId) : null;
      const editingQty = editingShipment?.items.filter((item) => item.orderLineId === lineId).reduce((acc, item) => acc + (Number.isFinite(item.quantity) ? item.quantity : 0), 0) ?? 0;
      const remaining = line.quantity - (shipped - editingQty);
      return remaining < 0 ? 0 : remaining;
    },
    [lineMap, shipments, shippedTotals]
  );
  const loadLines = React.useCallback(async () => {
    const params = new URLSearchParams({ page: "1", pageSize: "100", orderId });
    const response = await apiCall(
      `/api/sales/order-lines?${params.toString()}`,
      void 0,
      { fallback: { items: [] } }
    );
    const items = Array.isArray(response.result?.items) ? response.result?.items ?? [] : [];
    const mapped = items.map((item) => {
      const id = typeof item.id === "string" ? item.id : null;
      if (!id) return null;
      const name = typeof item.name === "string" ? item.name : typeof item.catalog_snapshot === "object" && item.catalog_snapshot && typeof item.catalog_snapshot.name === "string" ? item.catalog_snapshot.name : null;
      const lineNumber = typeof item.line_number === "number" ? item.line_number : typeof item.lineNumber === "number" ? item.lineNumber : null;
      const quantity = typeof item.quantity === "number" ? item.quantity : typeof item.quantity === "string" ? Number(item.quantity) : 0;
      return {
        id,
        title: name ?? id,
        lineNumber,
        quantity: Number.isFinite(quantity) ? quantity : 0,
        thumbnail: resolveLineThumbnail(item)
      };
    }).filter((entry) => Boolean(entry?.id));
    setLines(mapped);
  }, [orderId]);
  const loadShipments = React.useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const params = new URLSearchParams({ page: "1", pageSize: "100", orderId });
      const response = await apiCall(
        `/api/sales/shipments?${params.toString()}`,
        void 0,
        { fallback: { items: [] } }
      );
      const items = Array.isArray(response.result?.items) ? response.result?.items ?? [] : [];
      const mapped = items.map((item) => {
        const id = typeof item.id === "string" ? item.id : null;
        if (!id) return null;
        const snapshotItemsRaw = Array.isArray(item.items_snapshot) ? item.items_snapshot : [];
        const responseItems = Array.isArray(item.items) ? item.items : [];
        const itemsRaw = responseItems.length ? responseItems : snapshotItemsRaw;
        const shipmentItems = itemsRaw.map((entry) => {
          const lineId = typeof entry.orderLineId === "string" ? entry.orderLineId : typeof entry.order_line_id === "string" ? entry.order_line_id : null;
          if (!lineId) return null;
          const quantity = typeof entry.quantity === "number" ? entry.quantity : typeof entry.quantity === "string" ? Number(entry.quantity) : 0;
          return {
            id: typeof entry.id === "string" ? entry.id : generateTempId(),
            orderLineId: lineId,
            orderLineName: typeof entry.orderLineName === "string" ? entry.orderLineName : typeof entry.order_line_name === "string" ? entry.order_line_name : null,
            orderLineNumber: typeof entry.orderLineNumber === "number" ? entry.orderLineNumber : typeof entry.order_line_number === "number" ? entry.order_line_number : null,
            quantity: Number.isFinite(quantity) ? quantity : 0,
            metadata: entry.metadata ?? null
          };
        }).filter((entry) => Boolean(entry));
        const tracking = Array.isArray(item.tracking_numbers) && item.tracking_numbers.length ? item.tracking_numbers : [];
        const customValues = extractCustomFieldValues(item);
        return {
          id,
          updatedAt: readRowUpdatedAt(item),
          shipmentNumber: typeof item.shipment_number === "string" ? item.shipment_number : typeof item.shipmentNumber === "string" ? item.shipmentNumber : null,
          shippingMethodId: typeof item.shipping_method_id === "string" ? item.shipping_method_id : typeof item.shippingMethodId === "string" ? item.shippingMethodId : null,
          shippingMethodCode: typeof item.shipping_method_code === "string" ? item.shipping_method_code : typeof item.shippingMethodCode === "string" ? item.shippingMethodCode : null,
          shippingMethodName: typeof item.shipping_method_name === "string" ? item.shipping_method_name : typeof item.shippingMethodName === "string" ? item.shippingMethodName : null,
          status: typeof item.status === "string" ? item.status : typeof item.status === "string" ? item.status : null,
          statusLabel: typeof item.status_label === "string" ? item.status_label : typeof item.statusLabel === "string" ? item.statusLabel : null,
          statusEntryId: typeof item.status_entry_id === "string" ? item.status_entry_id : typeof item.statusEntryId === "string" ? item.statusEntryId : null,
          carrierName: typeof item.carrier_name === "string" ? item.carrier_name : typeof item.carrierName === "string" ? item.carrierName : null,
          trackingNumbers: tracking,
          shippedAt: typeof item.shipped_at === "string" ? item.shipped_at : typeof item.shippedAt === "string" ? item.shippedAt : null,
          deliveredAt: typeof item.delivered_at === "string" ? item.delivered_at : typeof item.deliveredAt === "string" ? item.deliveredAt : null,
          notes: typeof item.notes === "string" ? item.notes : typeof item.notesText === "string" ? item.notesText : null,
          metadata: item?.metadata ?? null,
          customValues: Object.keys(customValues).length ? customValues : null,
          items: shipmentItems,
          createdAt: typeof item.created_at === "string" ? item.created_at : typeof item.createdAt === "string" ? item.createdAt : null
        };
      }).filter((entry) => Boolean(entry));
      setShipments(mapped);
    } catch (err) {
      logger.error("sales.shipments.load", { err });
      setError(t("sales.documents.shipments.errorLoad", "Failed to load shipments."));
    } finally {
      setLoading(false);
    }
  }, [orderId, t]);
  React.useEffect(() => {
    void loadLines();
    void loadShipments();
  }, [loadLines, loadShipments]);
  React.useEffect(
    () => subscribeSalesDocumentTotalsRefresh((detail) => {
      if (detail.documentId !== orderId) return;
      if (detail.kind && detail.kind !== "order") return;
      void loadLines();
      void loadShipments();
    }),
    [loadLines, loadShipments, orderId]
  );
  const handleOpenCreate = React.useCallback(() => {
    setDialogState({ mode: "create", shipment: null });
  }, []);
  React.useEffect(() => {
    if (!onActionChange) return;
    onActionChange({
      label: addShipmentLabel,
      onClick: handleOpenCreate,
      disabled: false
    });
    return () => onActionChange(null);
  }, [addShipmentLabel, handleOpenCreate, onActionChange]);
  const handleEdit = React.useCallback((shipment) => {
    setDialogState({ mode: "edit", shipment });
  }, []);
  const handleDelete = React.useCallback(
    async (shipment) => {
      const confirmed = await confirm({
        title: t("sales.documents.shipments.confirmDelete", "Delete this shipment?"),
        variant: "default"
      });
      if (!confirmed) return;
      try {
        const result = await withScopedApiRequestHeaders(
          // The server guards the PARENT order's aggregate version (Gap B), so
          // send the order's `updated_at`, not the shipment row's.
          buildOptimisticLockHeader(documentUpdatedAt ?? void 0),
          () => deleteCrud("sales/shipments", {
            body: {
              id: shipment.id,
              orderId,
              organizationId: resolvedOrganizationId,
              tenantId: resolvedTenantId
            },
            errorMessage: t("sales.documents.shipments.errorDelete", "Failed to delete shipment.")
          })
        );
        if (result.ok) {
          await loadShipments();
          emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: "order" });
        }
      } catch (err) {
        if (handleSectionMutationError(err, t, () => void loadShipments())) {
          return;
        }
        logger.error("sales.shipments.delete", { err });
        flash(t("sales.documents.shipments.errorDelete", "Failed to delete shipment."), "error");
      }
    },
    [confirm, documentUpdatedAt, loadShipments, orderId, resolvedOrganizationId, resolvedTenantId, t]
  );
  const renderItemList = (items) => /* @__PURE__ */ jsx("ul", { className: "space-y-1 text-sm text-muted-foreground", children: items.map((item) => {
    const label = item.orderLineNumber ? `#${item.orderLineNumber}` : "";
    return /* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-2", children: [
      /* @__PURE__ */ jsxs("span", { className: "truncate", children: [
        label ? `${label} \xB7 ` : null,
        item.orderLineName ?? item.orderLineId
      ] }),
      /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: item.quantity })
    ] }, item.id);
  }) });
  if (loading) {
    return /* @__PURE__ */ jsx(
      LoadingMessage,
      {
        label: t("sales.documents.shipments.loading", "Loading shipments\u2026"),
        className: "border-0 bg-transparent p-0 py-8 justify-center"
      }
    );
  }
  if (error) {
    return /* @__PURE__ */ jsx(ErrorMessage, { label: error });
  }
  const empty = !shipments.length;
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
    empty ? /* @__PURE__ */ jsx(
      TabEmptyState,
      {
        title: t("sales.documents.shipments.empty.title", "No shipments yet."),
        description: t(
          "sales.documents.shipments.empty.description",
          "Add shipments for this document to let the user track the order."
        ),
        action: {
          label: addShipmentLabel,
          onClick: handleOpenCreate,
          icon: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4", "aria-hidden": true }),
          disabled: loading
        }
      }
    ) : /* @__PURE__ */ jsx("div", { className: "grid gap-3 md:grid-cols-2", children: shipments.map((shipment) => {
      const shippedAt = formatDisplayDate(shipment.shippedAt);
      const deliveredAt = formatDisplayDate(shipment.deliveredAt);
      const addressSummary = formatShipmentAddress(shipment.metadata);
      const statusLabel = shipment.statusLabel ?? shipment.status ?? t("sales.documents.shipments.statusMissing", "Status pending");
      return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-4 shadow-sm", children: [
        /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
          /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
            /* @__PURE__ */ jsx("div", { className: "flex h-9 w-9 items-center justify-center rounded-full bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(Truck, { className: "h-5 w-5" }) }),
            /* @__PURE__ */ jsxs("div", { children: [
              /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: shipment.shipmentNumber ? t("sales.documents.shipments.numberLabel", "Shipment {{number}}", {
                number: shipment.shipmentNumber
              }) : t("sales.documents.shipments.fallbackNumber", "Shipment {{id}}", {
                id: shipment.id.slice(0, 6)
              }) }),
              /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: statusLabel })
            ] })
          ] }),
          /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
            /* @__PURE__ */ jsx(
              Button,
              {
                variant: "ghost",
                size: "icon",
                className: "h-8 w-8",
                onClick: () => handleEdit(shipment),
                children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
              }
            ),
            /* @__PURE__ */ jsx(
              Button,
              {
                variant: "ghost",
                size: "icon",
                className: "h-8 w-8 text-destructive",
                onClick: () => void handleDelete(shipment),
                children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
              }
            )
          ] })
        ] }),
        /* @__PURE__ */ jsxs("div", { className: "mt-3 space-y-2 text-sm", children: [
          /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 text-muted-foreground", children: [
            shipment.carrierName ? /* @__PURE__ */ jsx(Badge, { variant: "outline", children: shipment.carrierName }) : null,
            shipment.trackingNumbers.length ? /* @__PURE__ */ jsxs("span", { className: "truncate", children: [
              t("sales.documents.shipments.tracking", "Tracking"),
              ": ",
              shipment.trackingNumbers.join(", ")
            ] }) : null
          ] }),
          shippedAt ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("sales.documents.shipments.shippedOn", "Shipped on {{date}}", { date: shippedAt }) }) : null,
          deliveredAt ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: t("sales.documents.shipments.deliveredOn", "Delivered on {{date}}", { date: deliveredAt }) }) : null,
          addressSummary ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: addressSummary }) : null,
          shipment.notes ? /* @__PURE__ */ jsx("p", { className: "rounded-md bg-muted px-3 py-2 text-muted-foreground", children: shipment.notes }) : null,
          renderItemList(shipment.items)
        ] })
      ] }, shipment.id);
    }) }),
    /* @__PURE__ */ jsx(
      ShipmentDialog,
      {
        open: dialogState !== null,
        mode: dialogState?.mode ?? "create",
        shipment: dialogState?.shipment ?? null,
        lines,
        orderId,
        currencyCode,
        organizationId: resolvedOrganizationId,
        tenantId: resolvedTenantId,
        documentUpdatedAt: documentUpdatedAt ?? null,
        computeAvailable,
        shippingAddressSnapshot,
        onClose: () => setDialogState(null),
        onSaved: async () => {
          setDialogState(null);
          await loadShipments();
          emitSalesDocumentTotalsRefresh({ documentId: orderId, kind: "order" });
        },
        onAddComment
      }
    ),
    ConfirmDialogElement
  ] });
}
export {
  SalesShipmentsSection
};
//# sourceMappingURL=ShipmentsSection.js.map
