"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { useQueryClient } from "@tanstack/react-query";
import { Button } from "../../primitives/button.js";
import { Spinner } from "../../primitives/spinner.js";
import { ErrorNotice } from "../../primitives/ErrorNotice.js";
import { flash } from "../FlashMessages.js";
import { apiCall, readApiResultOrThrow } from "../utils/apiCall.js";
import { raiseCrudError } from "../utils/serverErrors.js";
import { invalidateCustomFieldDefs } from "../utils/customFieldDefs.js";
import { FieldDefinitionsEditor } from "./FieldDefinitionsEditor.js";
import { upsertCustomFieldDefSchema } from "@open-mercato/shared/modules/entities/validators";
import { useT } from "@open-mercato/shared/lib/i18n/context";
function normalizeGroupPayload(value) {
  if (!value) return null;
  if (typeof value === "string") {
    const code2 = value.trim();
    return code2 ? { code: code2 } : null;
  }
  if (typeof value !== "object") return null;
  const entry = value;
  const code = typeof entry.code === "string" ? entry.code.trim() : "";
  if (!code) return null;
  const group = { code };
  if (typeof entry.title === "string" && entry.title.trim()) group.title = entry.title.trim();
  if (typeof entry.hint === "string" && entry.hint.trim()) group.hint = entry.hint.trim();
  return group;
}
const FieldDefinitionsManager = React.forwardRef(
  function FieldDefinitionsManager2({ entityId, initialFieldset = null, onClose, onSaved, fullEditorHref }, ref) {
    const t = useT();
    const queryClient = useQueryClient();
    const [loading, setLoading] = React.useState(true);
    const [saving, setSaving] = React.useState(false);
    const [statusError, setStatusError] = React.useState(null);
    const [defs, setDefs] = React.useState([]);
    const [deletedKeys, setDeletedKeys] = React.useState([]);
    const [defErrors, setDefErrors] = React.useState({});
    const [fieldsets, setFieldsets] = React.useState([]);
    const [activeFieldset, setActiveFieldset] = React.useState(initialFieldset);
    const [singleFieldsetPerRecord, setSingleFieldsetPerRecord] = React.useState(true);
    const [isDirty, setIsDirty] = React.useState(false);
    const [orderDirty, setOrderDirty] = React.useState(false);
    const loadDefinitions = React.useCallback(async () => {
      if (!entityId) return;
      setLoading(true);
      setStatusError(null);
      try {
        const json = await readApiResultOrThrow(
          `/api/entities/definitions.manage?entityId=${encodeURIComponent(entityId)}`,
          void 0,
          { errorMessage: t("entities.customFields.errors.loadFailed", "Failed to load field definitions"), fallback: { items: [], deletedKeys: [] } }
        );
        const loaded = (json.items || []).map((d) => ({
          key: d.key,
          kind: d.kind,
          configJson: d.configJson || {},
          isActive: d.isActive !== false
        }));
        loaded.sort(
          (a, b) => Number(a.configJson?.priority ?? 0) - Number(b.configJson?.priority ?? 0)
        );
        setDefs(loaded);
        setDeletedKeys(Array.isArray(json.deletedKeys) ? json.deletedKeys : []);
        const loadedFieldsets = Array.isArray(json.fieldsets) ? json.fieldsets : [];
        setFieldsets(loadedFieldsets);
        setActiveFieldset((current) => {
          if (initialFieldset && loadedFieldsets.some((fs) => fs.code === initialFieldset)) {
            return initialFieldset;
          }
          if (current && loadedFieldsets.some((fs) => fs.code === current)) return current;
          return loadedFieldsets[0]?.code ?? null;
        });
        setSingleFieldsetPerRecord(json.settings?.singleFieldsetPerRecord !== false);
        setDefErrors({});
        setIsDirty(false);
        setOrderDirty(false);
      } catch (err) {
        const message = err instanceof Error ? err.message : t("entities.customFields.errors.loadFailed", "Failed to load field definitions");
        setStatusError(message);
      } finally {
        setLoading(false);
      }
    }, [entityId, initialFieldset, t]);
    React.useEffect(() => {
      loadDefinitions().catch(() => {
      });
    }, [loadDefinitions]);
    const buildFieldsetPayload = React.useCallback(() => {
      const groupMap = /* @__PURE__ */ new Map();
      defs.forEach((definition) => {
        const code = typeof definition.configJson?.fieldset === "string" ? definition.configJson.fieldset : null;
        if (!code) return;
        const normalized = normalizeGroupPayload(definition.configJson?.group);
        if (!normalized) return;
        const list = groupMap.get(code) ?? [];
        if (!list.some((entry) => entry.code === normalized.code)) {
          list.push(normalized);
          groupMap.set(code, list);
        }
      });
      return fieldsets.map((fs) => ({
        ...fs,
        groups: groupMap.get(fs.code) ?? []
      }));
    }, [defs, fieldsets]);
    const validateDef = React.useCallback(
      (definition) => {
        const parsed = upsertCustomFieldDefSchema.safeParse({
          entityId,
          key: definition.key,
          kind: definition.kind,
          configJson: definition.configJson,
          isActive: definition.isActive
        });
        if (parsed.success) return {};
        const errs = {};
        for (const issue of parsed.error.issues) {
          if (issue.path.includes("key")) errs.key = issue.message;
          if (issue.path.includes("kind")) errs.kind = issue.message;
        }
        return errs;
      },
      [entityId]
    );
    const validateAll = React.useCallback(() => {
      const nextErrors = {};
      defs.forEach((definition, index) => {
        nextErrors[index] = validateDef(definition);
      });
      setDefErrors(nextErrors);
      return Object.values(nextErrors).every((entry) => !entry.key && !entry.kind);
    }, [defs, validateDef]);
    const handleDefinitionChange = React.useCallback((index, nextDef) => {
      setDefs((arr) => arr.map((entry, idx) => idx === index ? nextDef : entry));
      setDefErrors((prev) => ({ ...prev, [index]: validateDef(nextDef) }));
      setIsDirty(true);
    }, [validateDef]);
    const handleAddField = React.useCallback(() => {
      setDefs((arr) => [
        ...arr,
        {
          key: "",
          kind: "text",
          configJson: activeFieldset ? { fieldset: activeFieldset } : {},
          isActive: true
        }
      ]);
      setIsDirty(true);
    }, [activeFieldset]);
    const handleRemoveField = React.useCallback(async (index) => {
      const def = defs[index];
      if (!def) return;
      if (def.key) {
        try {
          const call = await apiCall("/api/entities/definitions", {
            method: "DELETE",
            headers: { "content-type": "application/json" },
            body: JSON.stringify({ entityId, key: def.key })
          });
          if (!call.ok) {
            await raiseCrudError(call.response, t("entities.customFields.errors.deleteFailed", "Failed to delete field"));
          }
        } catch (error) {
          const message = error instanceof Error ? error.message : t("entities.customFields.errors.deleteFailed", "Failed to delete field");
          flash(message, "error");
          return;
        }
      }
      setDefs((arr) => arr.filter((_, idx) => idx !== index));
      setIsDirty(true);
    }, [defs, entityId, t]);
    const handleRestoreField = React.useCallback(async (key) => {
      try {
        const call = await apiCall("/api/entities/definitions.restore", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({ entityId, key })
        });
        if (!call.ok) {
          await raiseCrudError(call.response, t("entities.customFields.errors.restoreFailed", "Failed to restore field"));
        }
        flash(t("entities.customFields.flash.restored", "Field restored"), "success");
        await loadDefinitions();
      } catch (error) {
        const message = error instanceof Error ? error.message : t("entities.customFields.errors.restoreFailed", "Failed to restore field");
        flash(message, "error");
      }
    }, [entityId, loadDefinitions, t]);
    const handleReorder = React.useCallback((from, to) => {
      setDefs((arr) => {
        const next = [...arr];
        const [moved] = next.splice(from, 1);
        next.splice(to, 0, moved);
        return next;
      });
      setIsDirty(true);
      setOrderDirty(true);
    }, []);
    const handleFieldsetsChange = React.useCallback((next) => {
      setFieldsets(next);
      if (!next.some((fs) => fs.code === activeFieldset)) {
        setActiveFieldset(next[0]?.code ?? null);
      }
      setIsDirty(true);
    }, [activeFieldset]);
    const handleFieldsetCodeChange = React.useCallback((previousCode, nextCode) => {
      if (!previousCode || !nextCode || previousCode === nextCode) return;
      setDefs(
        (arr) => arr.map((entry) => {
          const current = typeof entry.configJson?.fieldset === "string" ? entry.configJson.fieldset : void 0;
          if (current !== previousCode) return entry;
          const nextConfig = { ...entry.configJson || {} };
          nextConfig.fieldset = nextCode;
          return { ...entry, configJson: nextConfig };
        })
      );
      setActiveFieldset((current) => current === previousCode ? nextCode : current);
      setIsDirty(true);
    }, []);
    const handleFieldsetRemoved = React.useCallback((code) => {
      if (!code) return;
      setDefs(
        (arr) => arr.map((entry) => {
          const current = typeof entry.configJson?.fieldset === "string" ? entry.configJson.fieldset : void 0;
          if (current !== code) return entry;
          const nextConfig = { ...entry.configJson || {} };
          delete nextConfig.fieldset;
          delete nextConfig.group;
          return { ...entry, configJson: nextConfig };
        })
      );
      setIsDirty(true);
    }, []);
    const submit = React.useCallback(async () => {
      if (!entityId) return;
      setSaving(true);
      setStatusError(null);
      try {
        if (!validateAll()) {
          flash(t("entities.customFields.errors.validation", "Please fix validation errors"), "error");
          throw new Error(t("entities.customFields.errors.validation", "Validation failed"));
        }
        const payload = {
          entityId,
          definitions: defs.filter((d) => !!d.key).map((d) => ({
            key: d.key,
            kind: d.kind,
            configJson: d.configJson,
            isActive: d.isActive !== false
          })),
          fieldsets: buildFieldsetPayload(),
          singleFieldsetPerRecord
        };
        const call = await apiCall("/api/entities/definitions.batch", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify(payload)
        });
        if (!call.ok) {
          await raiseCrudError(call.response, t("entities.customFields.errors.saveFailed", "Failed to save definitions"));
        }
        await invalidateCustomFieldDefs(queryClient, entityId);
        flash(t("entities.customFields.flash.saved", "Definitions saved"), "success");
        setIsDirty(false);
        setOrderDirty(false);
        if (onSaved) await onSaved();
        onClose();
      } catch (err) {
        const message = err instanceof Error ? err.message : t("entities.customFields.errors.saveFailed", "Failed to save definitions");
        setStatusError(message);
      } finally {
        setSaving(false);
      }
    }, [buildFieldsetPayload, defs, entityId, onClose, onSaved, queryClient, singleFieldsetPerRecord, t, validateAll]);
    React.useImperativeHandle(ref, () => ({ submit }), [submit]);
    const cancelLabel = t("ui.forms.actions.cancel", "Cancel");
    const saveLabel = saving ? t("ui.forms.status.saving", "Saving...") : t("ui.forms.actions.save", "Save");
    const openFullLabel = t("entities.customFields.openInNewTab", "Open full editor");
    const handleOpenFullEditor = React.useCallback(() => {
      if (!fullEditorHref || typeof window === "undefined") return;
      window.open(fullEditorHref, "_blank", "noopener,noreferrer");
    }, [fullEditorHref]);
    const content = loading ? /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, { size: "lg" }) }) : /* @__PURE__ */ jsx(
      FieldDefinitionsEditor,
      {
        definitions: defs,
        errors: defErrors,
        deletedKeys,
        fieldsets,
        activeFieldset,
        onActiveFieldsetChange: setActiveFieldset,
        onFieldsetsChange: handleFieldsetsChange,
        onFieldsetCodeChange: handleFieldsetCodeChange,
        onFieldsetRemoved: handleFieldsetRemoved,
        singleFieldsetPerRecord,
        onSingleFieldsetPerRecordChange: (value) => {
          setSingleFieldsetPerRecord(value);
          setIsDirty(true);
        },
        onAddField: handleAddField,
        onRemoveField: (index) => {
          void handleRemoveField(index);
        },
        onDefinitionChange: handleDefinitionChange,
        onRestoreField: (key) => {
          void handleRestoreField(key);
        },
        onReorder: handleReorder,
        orderNotice: orderDirty ? { dirty: true, message: t("entities.customFields.orderNotice", "Reordered \u2014 remember to save") } : void 0,
        translate: t
      }
    );
    return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:gap-4", children: [
      statusError ? /* @__PURE__ */ jsx(ErrorNotice, { title: t("entities.customFields.errors.title", "Something went wrong"), message: statusError }) : null,
      /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-card p-3 sm:p-4 max-h-[70vh] overflow-y-auto", children: content }),
      /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
        fullEditorHref ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: handleOpenFullEditor, children: openFullLabel }) : null,
        /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: onClose, disabled: saving, children: cancelLabel }),
        /* @__PURE__ */ jsx(Button, { type: "button", onClick: () => {
          void submit();
        }, disabled: saving || !isDirty, children: saveLabel })
      ] })
    ] });
  }
);
FieldDefinitionsManager.displayName = "FieldDefinitionsManager";
export {
  FieldDefinitionsManager
};
//# sourceMappingURL=FieldDefinitionsManager.js.map
