"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import Link from "next/link";
import { Pencil, X } from "lucide-react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { Button } from "@open-mercato/ui/primitives/button";
import { DataLoader } from "@open-mercato/ui/primitives/DataLoader";
import { CrudForm } from "@open-mercato/ui/backend/CrudForm";
import { fetchCustomFieldFormFieldsWithDefinitions } from "@open-mercato/ui/backend/utils/customFieldForms";
import {
  DictionaryValue
} from "@open-mercato/core/modules/dictionaries/components/dictionaryAppearance";
import { ensureDictionaryEntries } from "@open-mercato/core/modules/dictionaries/components/hooks/useDictionaryEntries";
import {
  collectRelationValueIds,
  extractOptionLookupKey,
  extractInlineOptionLabel,
  parseRelationOptionsMetadata,
  getRelationHrefContextFields,
  buildRelationHref,
  fetchRelationRecordDisplays
} from "@open-mercato/ui/backend/utils/customFieldRelationDisplay";
import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
import { cn } from "@open-mercato/shared/lib/utils";
import { ComponentReplacementHandles } from "@open-mercato/shared/modules/widgets/component-registry";
import { MarkdownPreview } from "../markdown/index.js";
import { useRegisteredComponent } from "../injection/useRegisteredComponent.js";
const isTestEnv = typeof process !== "undefined" && process.env.NODE_ENV === "test";
let markdownPluginsPromise = null;
async function loadMarkdownPlugins() {
  if (isTestEnv) return [];
  if (!markdownPluginsPromise) {
    markdownPluginsPromise = import("remark-gfm").then((mod) => [mod.default ?? mod]).catch(() => []);
  }
  return markdownPluginsPromise;
}
const MARKDOWN_FIELD_TYPES = /* @__PURE__ */ new Set(["text", "textarea", "richtext"]);
const MARKDOWN_CLASSNAME = "text-sm text-foreground break-words [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs";
function renderMarkdownValue(content, remarkPlugins) {
  return /* @__PURE__ */ jsx(MarkdownPreview, { remarkPlugins, className: MARKDOWN_CLASSNAME, children: content });
}
function extractDictionaryValue(entry) {
  if (typeof entry === "string") {
    const trimmed = entry.trim();
    return trimmed.length ? trimmed : null;
  }
  if (!entry || typeof entry !== "object") return null;
  const record = entry;
  const candidate = record.value ?? record.name ?? record.id ?? record.key ?? record.label;
  if (typeof candidate === "string") {
    const trimmed = candidate.trim();
    return trimmed.length ? trimmed : null;
  }
  return null;
}
function formatFieldValue(field, value, emptyLabel, dictionaryMap, remarkPlugins = [], resolvedDisplays) {
  if (dictionaryMap) {
    if (value === void 0 || value === null || value === "") {
      return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel });
    }
    if (Array.isArray(value)) {
      const normalizedValues = value.map((entry) => extractDictionaryValue(entry)).filter((entry) => typeof entry === "string" && entry.length > 0);
      if (!normalizedValues.length) {
        return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel });
      }
      return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: normalizedValues.map((entry, index) => /* @__PURE__ */ jsx(
        DictionaryValue,
        {
          value: entry,
          map: dictionaryMap,
          className: "inline-flex items-center gap-1 rounded-full border border-border bg-card px-2 py-1 text-xs",
          iconWrapperClassName: "inline-flex h-4 w-4 items-center justify-center rounded-full border border-border bg-background",
          iconClassName: "h-3 w-3",
          colorClassName: "h-2.5 w-2.5 rounded-full"
        },
        `${field.id}-${entry}-${index}`
      )) });
    }
    const resolved2 = extractDictionaryValue(value);
    if (!resolved2) {
      return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel });
    }
    return /* @__PURE__ */ jsx(
      DictionaryValue,
      {
        value: resolved2,
        map: dictionaryMap,
        className: "inline-flex items-center gap-2 text-sm",
        fallback: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel }),
        iconWrapperClassName: "inline-flex h-6 w-6 items-center justify-center rounded border border-border bg-card",
        iconClassName: "h-4 w-4",
        colorClassName: "h-3 w-3 rounded-full"
      }
    );
  }
  const optionMap = "options" in field && Array.isArray(field.options) ? field.options.reduce((acc, option) => {
    acc.set(option.value, option.label);
    return acc;
  }, /* @__PURE__ */ new Map()) : null;
  const resolveOptionDisplay = (entry) => {
    const lookupKey = extractOptionLookupKey(entry);
    if (lookupKey && resolvedDisplays?.[lookupKey]) {
      return resolvedDisplays[lookupKey];
    }
    const inlineLabel = extractInlineOptionLabel(entry);
    if (lookupKey) {
      return {
        label: inlineLabel ?? optionMap?.get(lookupKey) ?? lookupKey
      };
    }
    if (inlineLabel) {
      return { label: inlineLabel };
    }
    return null;
  };
  const renderResolvedDisplay = (display) => {
    if (!display.href) return display.label;
    return /* @__PURE__ */ jsx(
      Link,
      {
        href: display.href,
        className: "font-medium text-primary underline-offset-2 hover:underline focus-visible:underline",
        onClick: (event) => event.stopPropagation(),
        onKeyDown: (event) => event.stopPropagation(),
        children: display.label
      }
    );
  };
  if (value === void 0 || value === null || value === "") {
    return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel });
  }
  if (Array.isArray(value)) {
    if (!value.length) return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel });
    return value.map((entry, index) => /* @__PURE__ */ jsx(
      "span",
      {
        className: "mr-1 inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-xs",
        children: (() => {
          const display = resolveOptionDisplay(entry);
          if (!display) return emptyLabel;
          return renderResolvedDisplay(display);
        })()
      },
      `${field.id}-${index}`
    ));
  }
  if (typeof value === "boolean") {
    return value ? "Yes" : "No";
  }
  if (resolvedDisplays && Object.keys(resolvedDisplays).length > 0) {
    const resolvedDisplay = resolveOptionDisplay(value);
    if (resolvedDisplay) {
      return renderResolvedDisplay(resolvedDisplay);
    }
  }
  if (typeof value === "object") {
    try {
      return JSON.stringify(value);
    } catch {
      return String(value);
    }
  }
  const resolved = optionMap?.get(String(value)) ?? String(value);
  if (typeof value === "string" && MARKDOWN_FIELD_TYPES.has(field.type)) {
    if (!resolved.trim().length) {
      return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel });
    }
    return renderMarkdownValue(value, remarkPlugins);
  }
  if (!resolved.length) return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: emptyLabel });
  return resolved;
}
function CustomDataSectionImpl({
  entityId,
  entityIds,
  values,
  onSubmit,
  title,
  scopeVersion: scopeVersionProp,
  loadFields,
  labels,
  definitionHref: explicitDefinitionHref
}) {
  const queryClient = useQueryClient();
  const defaultScopeVersion = useOrganizationScopeVersion();
  const scopeVersion = scopeVersionProp ?? defaultScopeVersion;
  const resolvedScopeVersion = React.useMemo(
    () => typeof scopeVersion === "number" ? scopeVersion : Number(scopeVersion) || 0,
    [scopeVersion]
  );
  const [dictionaryMapsByField, setDictionaryMapsByField] = React.useState({});
  const [resolvedDisplaysByField, setResolvedDisplaysByField] = React.useState({});
  const [editing, setEditing] = React.useState(false);
  const sectionRef = React.useRef(null);
  const [markdownPlugins, setMarkdownPlugins] = React.useState([]);
  React.useEffect(() => {
    if (isTestEnv) return;
    let mounted = true;
    void loadMarkdownPlugins().then((plugins) => {
      if (!mounted) return;
      setMarkdownPlugins(plugins);
    });
    return () => {
      mounted = false;
    };
  }, []);
  const resolvedEntityIds = React.useMemo(() => {
    if (Array.isArray(entityIds) && entityIds.length) {
      const dedup = /* @__PURE__ */ new Set();
      const list = [];
      entityIds.forEach((id) => {
        const trimmed = typeof id === "string" ? id.trim() : "";
        if (!trimmed || dedup.has(trimmed)) return;
        dedup.add(trimmed);
        list.push(trimmed);
      });
      return list;
    }
    if (typeof entityId === "string" && entityId.trim().length > 0) {
      return [entityId.trim()];
    }
    return [];
  }, [entityId, entityIds]);
  const primaryEntityId = resolvedEntityIds.length ? resolvedEntityIds[0] : void 0;
  const customFieldFormsQuery = useQuery({
    queryKey: ["customFieldForms", resolvedScopeVersion, ...resolvedEntityIds],
    enabled: resolvedEntityIds.length > 0,
    staleTime: 5 * 60 * 1e3,
    gcTime: 30 * 60 * 1e3,
    queryFn: async () => {
      const loader = loadFields ?? fetchCustomFieldFormFieldsWithDefinitions;
      return loader(resolvedEntityIds);
    }
  });
  const fields = React.useMemo(() => customFieldFormsQuery.data?.fields ?? [], [customFieldFormsQuery.data]);
  const definitions = React.useMemo(
    () => customFieldFormsQuery.data?.definitions ?? [],
    [customFieldFormsQuery.data]
  );
  const [dictionaryLoading, setDictionaryLoading] = React.useState(false);
  const [relationLoading, setRelationLoading] = React.useState(false);
  const loading = customFieldFormsQuery.isLoading || dictionaryLoading || relationLoading;
  const hasFields = fields.length > 0;
  const definitionHref = explicitDefinitionHref ?? (primaryEntityId ? `/backend/entities/system/${encodeURIComponent(primaryEntityId)}` : void 0);
  React.useEffect(() => {
    if (!hasFields && editing) {
      setEditing(false);
    }
  }, [editing, hasFields]);
  const submitActiveForm = React.useCallback(() => {
    const node = sectionRef.current?.querySelector("form");
    if (!node) return;
    const form = node;
    if (typeof form.requestSubmit === "function") {
      form.requestSubmit();
      return;
    }
    form.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));
  }, []);
  const handleEditingKeyDown = React.useCallback(
    (event) => {
      if (!editing) return;
      if (event.key === "Escape") {
        event.preventDefault();
        setEditing(false);
        return;
      }
      if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
        event.preventDefault();
        submitActiveForm();
      }
    },
    [editing, submitActiveForm]
  );
  const handleActivate = React.useCallback(() => {
    if (loading || editing || !hasFields) return;
    setEditing(true);
  }, [editing, hasFields, loading]);
  const handleReadOnlyKeyDown = React.useCallback(
    (event) => {
      if (loading || editing || !hasFields) return;
      if (event.key === "Enter" || event.key === " ") {
        event.preventDefault();
        setEditing(true);
      }
    },
    [editing, hasFields, loading]
  );
  React.useEffect(() => {
    if (!resolvedEntityIds.length || !definitions.length) {
      setDictionaryLoading((prev) => prev ? false : prev);
      setDictionaryMapsByField((prev) => Object.keys(prev).length ? {} : prev);
      return;
    }
    let cancelled = false;
    const load = async () => {
      setDictionaryLoading(true);
      try {
        const dictionaryDefs = definitions.map((def) => {
          const rawId = typeof def.dictionaryId === "string" ? def.dictionaryId.trim() : "";
          if (!rawId) return null;
          return { keyLower: def.key.toLowerCase(), dictionaryId: rawId };
        }).filter((entry) => !!entry);
        if (!dictionaryDefs.length) {
          if (!cancelled) {
            setDictionaryMapsByField((prev) => Object.keys(prev).length ? {} : prev);
          }
          return;
        }
        const uniqueDictionaryIds = Array.from(new Set(dictionaryDefs.map((entry) => entry.dictionaryId)));
        const mapsByDictionaryId = {};
        await Promise.all(
          uniqueDictionaryIds.map(async (dictionaryId) => {
            try {
              const data = await ensureDictionaryEntries(queryClient, dictionaryId, resolvedScopeVersion);
              mapsByDictionaryId[dictionaryId] = data.map;
            } catch {
              mapsByDictionaryId[dictionaryId] = {};
            }
          })
        );
        const dictionaryByKey = dictionaryDefs.reduce((acc, entry) => {
          acc.set(entry.keyLower, entry.dictionaryId);
          return acc;
        }, /* @__PURE__ */ new Map());
        const nextMaps = {};
        fields.forEach((field) => {
          const id = typeof field.id === "string" ? field.id : "";
          if (!id) return;
          const normalizedKey = id.startsWith("cf_") ? id.slice(3) : id;
          const keyLower = normalizedKey.toLowerCase();
          if (!keyLower) return;
          const dictionaryId = dictionaryByKey.get(keyLower);
          if (!dictionaryId) return;
          nextMaps[id] = mapsByDictionaryId[dictionaryId] ?? {};
        });
        if (!cancelled) {
          setDictionaryMapsByField((prev) => {
            const prevKeys = Object.keys(prev);
            const nextKeys = Object.keys(nextMaps);
            if (prevKeys.length === nextKeys.length && prevKeys.every((key) => prev[key] === nextMaps[key])) {
              return prev;
            }
            return nextMaps;
          });
        }
      } catch {
        if (!cancelled) {
          setDictionaryMapsByField((prev) => Object.keys(prev).length ? {} : prev);
        }
      } finally {
        if (!cancelled) {
          setDictionaryLoading(false);
        }
      }
    };
    load().catch(() => {
    });
    return () => {
      cancelled = true;
    };
  }, [definitions, fields, queryClient, resolvedEntityIds, resolvedScopeVersion]);
  React.useEffect(() => {
    if (!definitions.length || !fields.length) {
      setRelationLoading((prev) => prev ? false : prev);
      setResolvedDisplaysByField((prev) => Object.keys(prev).length ? {} : prev);
      return;
    }
    const definitionsByKey = definitions.reduce((acc, definition) => {
      acc.set(definition.key.toLowerCase(), definition);
      return acc;
    }, /* @__PURE__ */ new Map());
    const relationFields = fields.map((field) => {
      const normalizedKey = field.id.startsWith("cf_") ? field.id.slice(3) : field.id;
      const definition = definitionsByKey.get(normalizedKey.toLowerCase());
      if (!definition || definition.kind !== "relation") return null;
      const relationIds = collectRelationValueIds(values?.[field.id]);
      if (!relationIds.length) return null;
      return { field, definition, relationIds };
    }).filter((entry) => !!entry);
    if (!relationFields.length) {
      setRelationLoading((prev) => prev ? false : prev);
      setResolvedDisplaysByField((prev) => Object.keys(prev).length ? {} : prev);
      return;
    }
    const abortController = new AbortController();
    const load = async () => {
      setRelationLoading(true);
      try {
        const nextDisplays = {};
        await Promise.all(
          relationFields.map(async ({ field, definition, relationIds }) => {
            const displays = {};
            if ("options" in field && Array.isArray(field.options)) {
              field.options.forEach((option) => {
                displays[option.value] = { label: option.label };
              });
            }
            if ("loadOptions" in field && typeof field.loadOptions === "function") {
              try {
                const remoteOptions = await field.loadOptions();
                remoteOptions.forEach((option) => {
                  const href = (() => {
                    const relation2 = parseRelationOptionsMetadata(definition.optionsUrl);
                    return relation2 ? buildRelationHref(relation2.entityId, option.value) : void 0;
                  })();
                  displays[option.value] = { label: option.label, href };
                });
              } catch (error) {
                console.debug("[CustomDataSection] Failed to load remote options for field", field.id, error);
              }
            }
            const relation = parseRelationOptionsMetadata(definition.optionsUrl);
            const needsRouteContext = relation ? getRelationHrefContextFields(relation.entityId).length > 0 : false;
            const unresolvedIds = relationIds.filter((relationId) => {
              const display = displays[relationId];
              if (!display) return true;
              return needsRouteContext && !display.href;
            });
            if (relation && unresolvedIds.length) {
              try {
                const fetchedDisplays = await fetchRelationRecordDisplays(definition.optionsUrl, relation, unresolvedIds, abortController.signal);
                Object.assign(displays, fetchedDisplays);
              } catch (error) {
                console.debug("[CustomDataSection] Failed to fetch relation record displays for field", field.id, error);
                unresolvedIds.forEach((relationId) => {
                  if (!displays[relationId]) {
                    displays[relationId] = {
                      label: relationId,
                      href: buildRelationHref(relation.entityId, relationId)
                    };
                  }
                });
              }
            }
            if (Object.keys(displays).length > 0) {
              nextDisplays[field.id] = displays;
            }
          })
        );
        if (!abortController.signal.aborted) {
          setResolvedDisplaysByField((prev) => {
            const previousKeys = Object.keys(prev);
            const nextKeys = Object.keys(nextDisplays);
            if (previousKeys.length === nextKeys.length && previousKeys.every((key) => JSON.stringify(prev[key]) === JSON.stringify(nextDisplays[key]))) {
              return prev;
            }
            return nextDisplays;
          });
        }
      } finally {
        if (!abortController.signal.aborted) {
          setRelationLoading(false);
        }
      }
    };
    void load();
    return () => {
      abortController.abort();
    };
  }, [definitions, fields, values]);
  const handleSubmit = React.useCallback(
    async (input) => {
      await onSubmit(input);
      setEditing(false);
    },
    [onSubmit]
  );
  return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
    /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between group", children: [
      /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: title }),
      /* @__PURE__ */ jsxs(
        Button,
        {
          type: "button",
          variant: "ghost",
          size: "icon",
          onClick: () => {
            if (!hasFields || loading) return;
            setEditing((prev) => !prev);
          },
          disabled: loading || !hasFields,
          className: editing ? "opacity-100 transition-opacity duration-150" : "opacity-100 md:opacity-0 transition-opacity duration-150 md:group-hover:opacity-100 focus-visible:opacity-100",
          children: [
            editing ? /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" }),
            /* @__PURE__ */ jsx("span", { className: "sr-only", children: editing ? labels.cancel ?? "Cancel" : labels.edit ?? "Edit" })
          ]
        }
      )
    ] }),
    /* @__PURE__ */ jsx(
      DataLoader,
      {
        isLoading: loading,
        loadingMessage: labels.loading,
        spinnerSize: "md",
        className: "min-h-[120px]",
        children: editing ? /* @__PURE__ */ jsx(
          "div",
          {
            ref: sectionRef,
            className: "rounded-lg border bg-card p-3 sm:p-4",
            onKeyDown: handleEditingKeyDown,
            children: /* @__PURE__ */ jsx(
              CrudForm,
              {
                embedded: true,
                entityId: primaryEntityId,
                entityIds: resolvedEntityIds,
                fields,
                initialValues: values,
                onSubmit: handleSubmit,
                submitLabel: labels.saveShortcut,
                isLoading: loading
              }
            )
          }
        ) : /* @__PURE__ */ jsx(
          "div",
          {
            className: cn(
              "rounded-lg border bg-muted/20 p-3 sm:p-4 space-y-2 sm:space-y-3 transition hover:border-border/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary",
              hasFields && !loading ? "cursor-pointer" : "cursor-default"
            ),
            role: hasFields && !loading ? "button" : void 0,
            tabIndex: hasFields && !loading ? 0 : -1,
            onClick: hasFields && !loading ? handleActivate : void 0,
            onKeyDown: hasFields && !loading ? handleReadOnlyKeyDown : void 0,
            children: !hasFields ? /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
              labels.noFields,
              " ",
              definitionHref && labels.defineFields ? /* @__PURE__ */ jsx(
                Link,
                {
                  href: definitionHref,
                  className: "font-medium text-primary underline-offset-2 hover:underline focus-visible:underline",
                  children: labels.defineFields
                }
              ) : null
            ] }) : fields.map((field) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
              /* @__PURE__ */ jsx("p", { className: "text-xs uppercase tracking-wide text-muted-foreground", children: field.label }),
              /* @__PURE__ */ jsx("div", { className: "text-sm break-words", children: formatFieldValue(
                field,
                values?.[field.id],
                labels.emptyValue,
                dictionaryMapsByField[field.id],
                markdownPlugins,
                resolvedDisplaysByField[field.id]
              ) })
            ] }, field.id))
          }
        )
      }
    )
  ] });
}
function CustomDataSection(props) {
  const handle = ComponentReplacementHandles.section("ui.detail", "CustomDataSection");
  const Resolved = useRegisteredComponent(
    handle,
    CustomDataSectionImpl
  );
  return /* @__PURE__ */ jsx("div", { "data-component-handle": handle, children: /* @__PURE__ */ jsx(Resolved, { ...props }) });
}
var CustomDataSection_default = CustomDataSection;
export {
  CustomDataSection,
  CustomDataSection_default as default
};
//# sourceMappingURL=CustomDataSection.js.map
