import {
  DataGrid,
  createDataGridHelper
} from "./chunk-KAJOSTJ2.mjs";
import "./chunk-DK4WIVY6.mjs";
import "./chunk-IUCDCPJU.mjs";
import {
  KeyboundForm
} from "./chunk-6HTZNHPT.mjs";
import "./chunk-OV6YUU3D.mjs";
import {
  RouteFocusModal,
  useRouteModal
} from "./chunk-ULMMKZ3U.mjs";
import {
  useFeatureFlag
} from "./chunk-PJU3RODH.mjs";
import "./chunk-LPEUYMRK.mjs";
import "./chunk-OC7BQLYI.mjs";
import "./chunk-S4DMV3ZT.mjs";
import "./chunk-OBQI23QM.mjs";
import "./chunk-OW2UL5FI.mjs";
import "./chunk-5DUV4AET.mjs";
import {
  useBatchTranslations,
  useReferenceTranslations,
  useTranslationSettings
} from "./chunk-FAB3VINY.mjs";
import "./chunk-Q7YBE4IP.mjs";
import "./chunk-HI6URQ7H.mjs";
import "./chunk-6CLQKVAU.mjs";
import "./chunk-KI7TOXBR.mjs";
import "./chunk-QBIQEVTU.mjs";
import "./chunk-WAXMT4IY.mjs";
import "./chunk-DYDGGABK.mjs";
import "./chunk-LGNTHZ5Y.mjs";
import "./chunk-CN7JXSGW.mjs";
import "./chunk-AO2USOOE.mjs";
import "./chunk-KWWLGCSY.mjs";
import "./chunk-5AFMB7XQ.mjs";
import "./chunk-5U6AZEO7.mjs";
import "./chunk-A63RZVX6.mjs";
import "./chunk-HBXV7ENS.mjs";
import "./chunk-ZBMENGLV.mjs";
import "./chunk-LGLPAUIO.mjs";
import "./chunk-CDORR33H.mjs";
import "./chunk-DE44HCDH.mjs";
import "./chunk-MUOBXNL6.mjs";
import "./chunk-BEQ5XTWH.mjs";
import "./chunk-HP2JH45P.mjs";
import {
  useStore
} from "./chunk-VCSSQVPD.mjs";
import "./chunk-SQDIZZDW.mjs";
import "./chunk-LA2ILUXH.mjs";
import "./chunk-7AXHHXCX.mjs";
import "./chunk-FXYH54JP.mjs";
import "./chunk-774WSTCC.mjs";
import "./chunk-NFEK63OE.mjs";
import "./chunk-QZ7TP4HQ.mjs";

// src/routes/translations/translations-edit/translations-edit.tsx
import { keepPreviousData } from "@tanstack/react-query";
import { useEffect as useEffect2 } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";

// src/routes/translations/translations-edit/components/translations-edit-form/translations-edit-form.tsx
import { zodResolver } from "@hookform/resolvers/zod";
import { Button, Copy, Prompt, Select, toast, Text } from "@medusajs/ui";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { z } from "zod";
import { jsx, jsxs } from "react/jsx-runtime";
var EntityTranslationsSchema = z.object({
  id: z.string().nullish(),
  fields: z.record(z.string(), z.string().optional())
});
var TranslationsFormSchema = z.object({
  entities: z.record(z.string(), EntityTranslationsSchema)
});
function isEntityRow(row) {
  return row._type === "entity";
}
function buildLocaleSnapshot(translations, references, localeCode, translatableFields) {
  const referenceTranslations = /* @__PURE__ */ new Map();
  for (const t of translations) {
    if (t.locale_code === localeCode) {
      referenceTranslations.set(t.reference_id, t);
    }
  }
  const entities = {};
  for (const ref of references) {
    const existing = referenceTranslations.get(ref.id);
    const fields = {};
    for (const fieldName of translatableFields) {
      fields[fieldName] = existing?.translations?.[fieldName] ?? "";
    }
    entities[ref.id] = {
      id: existing?.id ?? null,
      fields
    };
  }
  return { localeCode, entities };
}
function extendSnapshot(snapshot, translations, newReferences, translatableFields) {
  const referenceTranslations = /* @__PURE__ */ new Map();
  for (const t of translations) {
    if (t.locale_code === snapshot.localeCode) {
      referenceTranslations.set(t.reference_id, t);
    }
  }
  const extendedEntities = { ...snapshot.entities };
  for (const ref of newReferences) {
    if (!extendedEntities[ref.id]) {
      const existing = referenceTranslations.get(ref.id);
      const fields = {};
      for (const fieldName of translatableFields) {
        fields[fieldName] = existing?.translations?.[fieldName] ?? "";
      }
      extendedEntities[ref.id] = {
        id: existing?.id ?? null,
        fields
      };
    }
  }
  return { ...snapshot, entities: extendedEntities };
}
function snapshotToFormValues(snapshot) {
  return { entities: snapshot.entities };
}
function computeChanges(currentState, snapshot, entityType, localeCode) {
  const payload = {
    create: [],
    update: [],
    delete: []
  };
  for (const [entityId, _entityData] of Object.entries(currentState.entities)) {
    const entityData = _entityData;
    const baseline = snapshot.entities[entityId];
    if (!baseline) {
      continue;
    }
    const hasContent = Object.values(entityData.fields).some(
      (v) => v !== void 0 && v.trim() !== ""
    );
    const hadContent = Object.values(baseline.fields).some(
      (v) => v !== void 0 && v.trim() !== ""
    );
    const hasChanged = JSON.stringify(entityData.fields) !== JSON.stringify(baseline.fields);
    if (!entityData.id && hasContent) {
      payload.create.push({
        reference_id: entityId,
        reference: entityType,
        locale_code: localeCode,
        translations: entityData.fields
      });
    } else if (entityData.id && hasContent && hasChanged) {
      payload.update.push({
        id: entityData.id,
        translations: entityData.fields
      });
    } else if (entityData.id && !hasContent && hadContent) {
      payload.delete.push(entityData.id);
    }
  }
  const hasChanges = payload.create.length > 0 || payload.update.length > 0 || payload.delete.length > 0;
  return { hasChanges, payload };
}
var columnHelper = createDataGridHelper();
var FIELD_COLUMN_WIDTH = 350;
function buildTranslationRows(references, translatableFields) {
  return references.map((reference) => ({
    _type: "entity",
    reference_id: reference.id,
    subRows: translatableFields.map((fieldName) => ({
      _type: "field",
      reference_id: reference.id,
      field_name: fieldName
    }))
  }));
}
function useTranslationsGridColumns({
  entities,
  availableLocales,
  selectedLocale,
  dynamicColumnWidth
}) {
  const { t } = useTranslation();
  return useMemo(() => {
    const selectedLocaleData = availableLocales.find(
      (l) => l.locale_code === selectedLocale
    );
    const columns = [
      columnHelper.column({
        id: "field",
        name: "field",
        size: FIELD_COLUMN_WIDTH,
        header: void 0,
        cell: (context) => {
          const row = context.row.original;
          if (isEntityRow(row)) {
            return /* @__PURE__ */ jsx(DataGrid.ReadonlyCell, { context });
          }
          return /* @__PURE__ */ jsx(DataGrid.ReadonlyCell, { context, color: "normal", children: /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center gap-x-2 overflow-hidden", children: /* @__PURE__ */ jsx(
            Text,
            {
              className: "text-ui-fg-subtle truncate",
              weight: "plus",
              size: "small",
              children: t(`fields.${row.field_name}`, {
                defaultValue: row.field_name
              })
            }
          ) }) });
        },
        disableHiding: true
      }),
      columnHelper.column({
        id: "original",
        name: "original",
        size: dynamicColumnWidth,
        header: () => /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-base", weight: "plus", size: "small", children: t("general.original") }),
        disableHiding: true,
        cell: (context) => {
          const row = context.row.original;
          if (isEntityRow(row)) {
            return /* @__PURE__ */ jsx(DataGrid.ReadonlyCell, { context });
          }
          const entity = entities.find((e) => e.id === row.reference_id);
          if (!entity) {
            return null;
          }
          const rawOriginalValue = entity[row.field_name];
          const originalValue = typeof rawOriginalValue === "string" ? rawOriginalValue : "";
          return /* @__PURE__ */ jsx(DataGrid.ReadonlyCell, { color: "normal", context, isMultiLine: true, children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-start justify-between gap-x-2", children: [
            /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", weight: "plus", size: "small", children: originalValue }),
            originalValue.trim() && /* @__PURE__ */ jsx(
              Copy,
              {
                content: originalValue,
                variant: "mini",
                className: "cursor-pointer"
              }
            )
          ] }) });
        }
      })
    ];
    if (selectedLocaleData) {
      columns.push(
        columnHelper.column({
          id: selectedLocaleData.locale_code,
          name: selectedLocaleData.locale.name,
          size: dynamicColumnWidth,
          header: () => /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-base", weight: "plus", size: "small", children: selectedLocaleData.locale.name }),
          cell: (context) => {
            const row = context.row.original;
            if (isEntityRow(row)) {
              return /* @__PURE__ */ jsx(DataGrid.ReadonlyCell, { context, isMultiLine: true });
            }
            return /* @__PURE__ */ jsx(DataGrid.MultilineCell, { context });
          },
          field: (context) => {
            const row = context.row.original;
            if (isEntityRow(row)) {
              return null;
            }
            return `entities.${row.reference_id}.fields.${row.field_name}`;
          },
          type: "multiline-text"
        })
      );
    }
    return columns;
  }, [t, availableLocales, selectedLocale, entities, dynamicColumnWidth]);
}
var TranslationsEditForm = ({
  translations,
  references,
  entityType,
  availableLocales,
  translatableFields,
  fetchNextPage,
  hasNextPage,
  isFetchingNextPage,
  referenceCount
}) => {
  const { t } = useTranslation();
  const { handleSuccess, setCloseOnEscape } = useRouteModal();
  const containerRef = useRef(null);
  const [dynamicColumnWidth, setDynamicColumnWidth] = useState(400);
  useEffect(() => {
    const calculateColumnWidth = () => {
      if (containerRef.current) {
        const containerWidth = containerRef.current.offsetWidth;
        const availableWidth = containerWidth - FIELD_COLUMN_WIDTH - 16;
        const columnWidth = Math.max(300, Math.floor(availableWidth / 2));
        setDynamicColumnWidth(columnWidth);
      }
    };
    calculateColumnWidth();
    const resizeObserver = new ResizeObserver(calculateColumnWidth);
    if (containerRef.current) {
      resizeObserver.observe(containerRef.current);
    }
    return () => resizeObserver.disconnect();
  }, []);
  const [selectedLocale, setSelectedLocale] = useState(
    availableLocales[0]?.locale_code ?? ""
  );
  const [showUnsavedPrompt, setShowUnsavedPrompt] = useState(false);
  const [pendingLocale, setPendingLocale] = useState(null);
  const [isSwitchingLocale, setIsSwitchingLocale] = useState(false);
  const snapshotRef = useRef(
    buildLocaleSnapshot(
      translations,
      references,
      selectedLocale,
      translatableFields
    )
  );
  const knownEntityIdsRef = useRef(
    new Set(references.map((r) => r.id))
  );
  const latestPropsRef = useRef({ translations, references });
  useEffect(() => {
    latestPropsRef.current = { translations, references };
  }, [translations, references]);
  const form = useForm({
    resolver: zodResolver(TranslationsFormSchema),
    defaultValues: snapshotToFormValues(snapshotRef.current)
  });
  useEffect(() => {
    const currentIds = new Set(references.map((r) => r.id));
    const newReferences = references.filter(
      (r) => !knownEntityIdsRef.current.has(r.id)
    );
    if (newReferences.length === 0) {
      return;
    }
    knownEntityIdsRef.current = currentIds;
    snapshotRef.current = extendSnapshot(
      snapshotRef.current,
      translations,
      newReferences,
      translatableFields
    );
    const currentValues = form.getValues();
    const newFormValues = {
      entities: { ...currentValues.entities }
    };
    for (const ref of newReferences) {
      if (!newFormValues.entities[ref.id]) {
        newFormValues.entities[ref.id] = snapshotRef.current.entities[ref.id];
      }
    }
    form.reset(newFormValues, {
      keepDirty: true,
      keepDirtyValues: true
    });
  }, [references, translations, translatableFields, form]);
  const rows = useMemo(
    () => buildTranslationRows(references, translatableFields),
    [references, translatableFields]
  );
  const totalRowCount = useMemo(
    () => referenceCount * (translatableFields.length + 1),
    [referenceCount, translatableFields]
  );
  const selectedLocaleDisplay = useMemo(
    () => availableLocales.find((l) => l.locale_code === selectedLocale)?.locale.name,
    [availableLocales, selectedLocale]
  );
  const columns = useTranslationsGridColumns({
    entities: references,
    availableLocales,
    selectedLocale,
    dynamicColumnWidth
  });
  const { mutateAsync, isPending, invalidateQueries } = useBatchTranslations(entityType);
  const saveCurrentLocale = useCallback(async () => {
    const currentValues = form.getValues();
    const { hasChanges, payload } = computeChanges(
      currentValues,
      snapshotRef.current,
      entityType,
      selectedLocale
    );
    if (!hasChanges) {
      return true;
    }
    try {
      const BATCH_SIZE = 150;
      const totalItems = payload.create.length + payload.update.length + payload.delete.length;
      const batchCount = Math.ceil(totalItems / BATCH_SIZE);
      for (let i = 0; i < batchCount; i++) {
        let currentBatchAvailable = BATCH_SIZE;
        const currentBatch = {
          create: [],
          update: [],
          delete: []
        };
        if (payload.create.length > 0) {
          currentBatch.create = payload.create.splice(0, currentBatchAvailable);
          currentBatchAvailable -= currentBatch.create.length;
        }
        if (payload.update.length > 0) {
          currentBatch.update = payload.update.splice(0, currentBatchAvailable);
          currentBatchAvailable -= currentBatch.update.length;
        }
        if (payload.delete.length > 0) {
          currentBatch.delete = payload.delete.splice(0, currentBatchAvailable);
        }
        const response = await mutateAsync(currentBatch, {
          onError: (error) => {
            toast.error(error.message);
          }
        });
        if (response.created) {
          for (const created of response.created) {
            form.setValue(`entities.${created.reference_id}.id`, created.id, {
              shouldDirty: false
            });
            if (snapshotRef.current.entities[created.reference_id]) {
              snapshotRef.current.entities[created.reference_id].id = created.id;
            }
          }
        }
      }
      const savedValues = form.getValues();
      for (const entityId of Object.keys(savedValues.entities)) {
        if (snapshotRef.current.entities[entityId]) {
          snapshotRef.current.entities[entityId] = {
            ...savedValues.entities[entityId]
          };
        }
      }
      form.reset(savedValues);
      return true;
    } catch (error) {
      toast.error(
        error instanceof Error ? error.message : "Failed to save translations"
      );
      return false;
    }
  }, [form, entityType, selectedLocale, mutateAsync]);
  const switchToLocale = useCallback(
    async (newLocale) => {
      setIsSwitchingLocale(true);
      try {
        await invalidateQueries();
        await new Promise((resolve) => requestAnimationFrame(resolve));
        const { translations: translations2, references: references2 } = latestPropsRef.current;
        const newSnapshot = buildLocaleSnapshot(
          translations2,
          references2,
          newLocale,
          translatableFields
        );
        snapshotRef.current = newSnapshot;
        knownEntityIdsRef.current = new Set(references2.map((r) => r.id));
        form.reset(snapshotToFormValues(newSnapshot));
        setSelectedLocale(newLocale);
      } finally {
        setIsSwitchingLocale(false);
      }
    },
    [translatableFields, form, invalidateQueries]
  );
  const handleLocaleChange = useCallback(
    (newLocale) => {
      if (newLocale === selectedLocale) {
        return;
      }
      const currentValues = form.getValues();
      const { hasChanges } = computeChanges(
        currentValues,
        snapshotRef.current,
        entityType,
        selectedLocale
      );
      if (hasChanges) {
        setPendingLocale(newLocale);
        setShowUnsavedPrompt(true);
      } else {
        switchToLocale(newLocale);
      }
    },
    [selectedLocale, form, entityType, switchToLocale]
  );
  const handleSaveAndSwitch = useCallback(async () => {
    const success = await saveCurrentLocale();
    if (success && pendingLocale) {
      toast.success(t("translations.edit.successToast"));
      await switchToLocale(pendingLocale);
    }
    setShowUnsavedPrompt(false);
    setPendingLocale(null);
  }, [saveCurrentLocale, pendingLocale, t, switchToLocale]);
  const handleCancelSwitch = useCallback(() => {
    setShowUnsavedPrompt(false);
    setPendingLocale(null);
  }, []);
  const handleSave = useCallback(
    async (closeOnSuccess = false) => {
      const success = await saveCurrentLocale();
      if (success) {
        toast.success(t("translations.edit.successToast"));
        if (closeOnSuccess) {
          handleSuccess();
        }
      }
    },
    [saveCurrentLocale, t, handleSuccess]
  );
  const handleClose = useCallback(() => {
    invalidateQueries();
  }, [invalidateQueries]);
  const isLoading = isPending || isSwitchingLocale;
  return /* @__PURE__ */ jsxs(RouteFocusModal.Form, { form, onClose: handleClose, children: [
    /* @__PURE__ */ jsxs(
      KeyboundForm,
      {
        onSubmit: () => handleSave(true),
        className: "flex h-full flex-col overflow-hidden",
        children: [
          /* @__PURE__ */ jsx(RouteFocusModal.Header, {}),
          /* @__PURE__ */ jsx(RouteFocusModal.Body, { className: "size-full overflow-hidden", children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "size-full", children: /* @__PURE__ */ jsx(
            DataGrid,
            {
              showColumnsDropdown: false,
              columns,
              data: rows,
              getSubRows: (row) => {
                if (isEntityRow(row)) {
                  return row.subRows;
                }
              },
              state: form,
              onEditingChange: (editing) => setCloseOnEscape(!editing),
              totalRowCount,
              onFetchMore: fetchNextPage,
              isFetchingMore: isFetchingNextPage,
              hasNextPage,
              headerContent: /* @__PURE__ */ jsxs(
                Select,
                {
                  disabled: isLoading,
                  value: selectedLocale,
                  onValueChange: handleLocaleChange,
                  size: "small",
                  children: [
                    /* @__PURE__ */ jsx(Select.Trigger, { className: "bg-ui-bg-base w-[200px]", children: /* @__PURE__ */ jsx(Select.Value, { children: selectedLocaleDisplay }) }),
                    /* @__PURE__ */ jsx(Select.Content, { children: availableLocales.map((locale) => /* @__PURE__ */ jsx(
                      Select.Item,
                      {
                        value: locale.locale_code,
                        children: locale.locale.name
                      },
                      locale.locale_code
                    )) })
                  ]
                }
              )
            }
          ) }) }),
          /* @__PURE__ */ jsx(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
            /* @__PURE__ */ jsx(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx(
              Button,
              {
                type: "button",
                size: "small",
                variant: "secondary",
                isLoading,
                children: t("actions.cancel")
              }
            ) }),
            /* @__PURE__ */ jsx(
              Button,
              {
                size: "small",
                type: "button",
                variant: "secondary",
                onClick: () => handleSave(false),
                isLoading,
                children: t("actions.saveChanges")
              }
            ),
            /* @__PURE__ */ jsx(Button, { size: "small", type: "submit", isLoading, children: t("actions.saveAndClose") })
          ] }) })
        ]
      }
    ),
    /* @__PURE__ */ jsx(Prompt, { open: showUnsavedPrompt, variant: "confirmation", children: /* @__PURE__ */ jsxs(Prompt.Content, { children: [
      /* @__PURE__ */ jsxs(Prompt.Header, { children: [
        /* @__PURE__ */ jsx(Prompt.Title, { children: t("translations.edit.unsavedChanges.title") }),
        /* @__PURE__ */ jsx(Prompt.Description, { children: t("translations.edit.unsavedChanges.description") })
      ] }),
      /* @__PURE__ */ jsxs(Prompt.Footer, { children: [
        /* @__PURE__ */ jsx(
          Button,
          {
            size: "small",
            variant: "secondary",
            onClick: handleCancelSwitch,
            type: "button",
            children: t("actions.close")
          }
        ),
        /* @__PURE__ */ jsx(
          Button,
          {
            size: "small",
            onClick: handleSaveAndSwitch,
            type: "button",
            isLoading,
            children: t("actions.saveChanges")
          }
        )
      ] })
    ] }) })
  ] });
};

// src/routes/translations/translations-edit/translations-edit.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var TranslationsEdit = () => {
  const isTranslationsEnabled = useFeatureFlag("translation");
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const reference = searchParams.get("reference");
  const referenceIdParam = searchParams.getAll("reference_id");
  useEffect2(() => {
    if (!reference || !isTranslationsEnabled) {
      navigate(-1);
      return;
    }
  }, [reference, navigate, isTranslationsEnabled]);
  const {
    translation_settings,
    isPending: isTranslationSettingsPending,
    isError: isTranslationSettingsError,
    error: translationSettingsError
  } = useTranslationSettings({ entity_type: reference });
  const {
    translations,
    references,
    fetchNextPage,
    count,
    isFetchingNextPage,
    hasNextPage,
    isPending,
    isError,
    error
  } = useReferenceTranslations(reference, referenceIdParam, {
    enabled: !!reference,
    placeholderData: keepPreviousData
  });
  const {
    store,
    isPending: isStorePending,
    isError: isStoreError,
    error: storeError
  } = useStore();
  const ready = !isPending && !!translations && !!translation_settings && !isTranslationSettingsPending && !!references && !isStorePending && !!store;
  if (isError || isStoreError || isTranslationSettingsError) {
    throw error || storeError || translationSettingsError;
  }
  return /* @__PURE__ */ jsx2(RouteFocusModal, { prev: referenceIdParam.length ? -1 : "..", children: ready && /* @__PURE__ */ jsx2(
    TranslationsEditForm,
    {
      translations,
      references,
      entityType: reference,
      availableLocales: store?.supported_locales ?? [],
      translatableFields: translation_settings[reference]?.fields ?? [],
      fetchNextPage,
      hasNextPage,
      isFetchingNextPage,
      referenceCount: count
    }
  ) });
};
export {
  TranslationsEdit as Component
};
