import { jsx, jsxs } from 'react/jsx-runtime';
import { memo, useRef, useMemo, Fragment, Suspense } from 'react';
import isDeepEqual from '../../../../../../../_virtual/index.mjs';
import { ElementSelector } from '../components/element-selector.mjs';
import { DropPlaceholder } from '../dnd/drop-zone.mjs';
import '../../../../../../../node_modules/.pnpm/@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.mjs';
import '../../../../lib/ui-builder/context/dnd-context-colission-utils.mjs';
import { useDndContext } from '../../../../lib/ui-builder/context/dnd-contexts.mjs';
import 'react-dom';
import { useLayerStore } from '../../../../lib/ui-builder/store/layer-store.mjs';
import { canLayerAcceptChildren, hasLayerChildren, findLayerRecursive } from '../../../../lib/ui-builder/store/layer-utils.mjs';
import { useEditorStore } from '../../../../lib/ui-builder/store/editor-store.mjs';
import { ErrorBoundary } from 'react-error-boundary';
import { ErrorFallback } from '../components/error-fallback.mjs';
import { isPrimitiveComponent } from '../../../../lib/ui-builder/store/editor-utils.mjs';
import { DevProfiler } from '../components/dev-profiler.mjs';
import { isVariableReference } from '../../types.mjs';
import { resolveVariableReferences, resolveChildrenVariableReference } from '../../../../lib/ui-builder/utils/variable-resolver.mjs';

const POSITION_CLASSES = ["static", "fixed", "absolute", "relative", "sticky"];
function hasPositionClass(className) {
  const classes = className.split(/\s+/);
  return POSITION_CLASSES.some((posClass) => classes.includes(posClass));
}
function isLayerBeingDraggedOrDescendant(layerId, activeLayerId, pages) {
  if (!activeLayerId) return false;
  if (layerId === activeLayerId) return true;
  if (!pages || !Array.isArray(pages) || pages.length === 0) return false;
  const draggedLayer = findLayerRecursive(pages, activeLayerId);
  if (!draggedLayer) return false;
  if (hasLayerChildren(draggedLayer)) {
    const foundInDragged = findLayerRecursive([draggedLayer], layerId);
    return !!foundInDragged;
  }
  return false;
}
const RenderLayer = memo(
  ({ layer, componentRegistry, editorConfig, variables, variableValues, functionRegistry }) => {
    const storeVariables = useLayerStore((state) => state.variables);
    const pages = useLayerStore((state) => state.pages);
    const isLayerAPage = useLayerStore((state) => state.isLayerAPage(layer.id));
    const registry = useEditorStore((state) => state.registry);
    const storeFunctionRegistry = useEditorStore((state) => state.functionRegistry);
    const dndContext = useDndContext();
    const effectiveFunctionRegistry = functionRegistry ?? storeFunctionRegistry;
    const effectiveVariables = variables || storeVariables;
    const componentDefinition = componentRegistry[layer.type];
    const prevLayer = useRef(layer);
    const infoData = useMemo(() => ({
      layerType: layer.type,
      layerId: layer.id,
      layerName: layer.name,
      availableComponents: Object.keys(componentRegistry),
      layer
    }), [layer, componentRegistry]);
    const resolvedProps = useMemo(
      () => resolveVariableReferences(layer.props, effectiveVariables, variableValues, effectiveFunctionRegistry),
      [layer.props, effectiveVariables, variableValues, effectiveFunctionRegistry]
    );
    const childEditorConfig = useMemo(() => {
      return editorConfig ? { ...editorConfig, zIndex: editorConfig.zIndex + 1, parentUpdated: editorConfig.parentUpdated || !isDeepEqual(prevLayer.current, layer) } : void 0;
    }, [editorConfig, layer]);
    const isBeingDragged = useMemo(
      () => isLayerBeingDraggedOrDescendant(layer.id, dndContext.activeLayerId, pages),
      [layer.id, dndContext.activeLayerId, pages]
    );
    const isRootDraggedLayer = layer.id === dndContext.activeLayerId;
    const canAcceptChildren = useMemo(() => canLayerAcceptChildren(layer, registry), [layer, registry]);
    const showDropZones = useMemo(
      () => editorConfig && dndContext.isDragging && canAcceptChildren && !isBeingDragged,
      [editorConfig, dndContext.isDragging, canAcceptChildren, isBeingDragged]
    );
    const childProps = useMemo(() => {
      const props = {};
      for (const [key, value] of Object.entries(resolvedProps)) {
        if (!key.startsWith("__function_")) {
          props[key] = value;
        }
      }
      if (showDropZones && hasLayerChildren(layer)) {
        const existingClassName = props.className || "";
        if (!hasPositionClass(existingClassName)) {
          props.className = existingClassName ? `${existingClassName} relative` : "relative";
        }
      }
      return props;
    }, [resolvedProps, showDropZones, layer]);
    if (!componentDefinition) {
      console.error(
        `[UIBuilder] Component definition not found in registry:`,
        infoData
      );
      return null;
    }
    let Component = componentDefinition.component;
    let isPrimitive = false;
    if (isPrimitiveComponent(componentDefinition)) {
      Component = layer.type;
      isPrimitive = true;
    }
    if (!Component) return null;
    if (hasLayerChildren(layer) && layer.children.length > 0) {
      const childElements = layer.children.map((child, index) => {
        const childElement = /* @__PURE__ */ jsx(
          RenderLayer,
          {
            componentRegistry,
            layer: child,
            variables,
            variableValues,
            editorConfig: childEditorConfig,
            functionRegistry
          },
          child.id
        );
        if (showDropZones) {
          return /* @__PURE__ */ jsxs(Fragment, { children: [
            /* @__PURE__ */ jsx(
              DropPlaceholder,
              {
                parentId: layer.id,
                position: index,
                isActive: true
              }
            ),
            childElement
          ] }, child.id);
        }
        return childElement;
      });
      if (showDropZones) {
        childElements.push(
          /* @__PURE__ */ jsx(
            DropPlaceholder,
            {
              parentId: layer.id,
              position: layer.children.length,
              isActive: true
            },
            `drop-${layer.id}-${layer.children.length}`
          )
        );
      }
      childProps.children = childElements;
    } else if (isVariableReference(layer.children)) {
      const resolvedChildren = resolveChildrenVariableReference(
        layer.children,
        effectiveVariables,
        variableValues
      );
      childProps.children = resolvedChildren;
    } else if (typeof layer.children === "string") {
      childProps.children = layer.children;
    } else if (showDropZones && hasLayerChildren(layer)) {
      childProps.children = /* @__PURE__ */ jsx("div", { className: "min-h-[2rem] w-full", children: /* @__PURE__ */ jsx(
        DropPlaceholder,
        {
          parentId: layer.id,
          position: 0,
          isActive: true
        }
      ) });
    }
    const WrappedComponent = isPrimitive ? /* @__PURE__ */ jsx(Component, { id: layer.id, "data-testid": layer.id, "data-layer-id": layer.id, ...childProps }) : /* @__PURE__ */ jsx(ErrorSuspenseWrapper, { id: layer.id, children: /* @__PURE__ */ jsx(Component, { "data-testid": layer.id, "data-layer-id": layer.id, ...childProps }) }, layer.id);
    const DragFeedbackWrapper = isRootDraggedLayer ? /* @__PURE__ */ jsxs(
      "div",
      {
        className: "relative opacity-50 pointer-events-none",
        "data-dragging": "true",
        children: [
          /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-primary/20 rounded pointer-events-none z-10" }),
          WrappedComponent
        ]
      }
    ) : WrappedComponent;
    if (!editorConfig) {
      return DragFeedbackWrapper;
    } else {
      const {
        zIndex,
        totalLayers,
        selectedLayer,
        onSelectElement
      } = editorConfig;
      return /* @__PURE__ */ jsx(
        DevProfiler,
        {
          id: layer.type,
          threshold: 20,
          children: /* @__PURE__ */ jsx(
            ElementSelector,
            {
              layer,
              zIndex,
              isSelected: layer.id === selectedLayer?.id,
              onSelectElement,
              isPageLayer: isLayerAPage,
              totalLayers,
              children: DragFeedbackWrapper
            },
            layer.id
          )
        }
      );
    }
  },
  (prevProps, nextProps) => {
    if (nextProps.editorConfig?.parentUpdated) {
      return false;
    }
    const editorConfigEqual = isDeepEqual(
      prevProps.editorConfig?.selectedLayer?.id,
      nextProps.editorConfig?.selectedLayer?.id
    );
    const layerEqual = isDeepEqual(prevProps.layer, nextProps.layer);
    const variablesEqual = isDeepEqual(prevProps.variables, nextProps.variables);
    const variableValuesEqual = isDeepEqual(prevProps.variableValues, nextProps.variableValues);
    const functionRegistryEqual = prevProps.functionRegistry === nextProps.functionRegistry;
    return editorConfigEqual && layerEqual && variablesEqual && variableValuesEqual && functionRegistryEqual;
  }
);
RenderLayer.displayName = "RenderLayer";
const ErrorSuspenseWrapper = ({ children }) => {
  const loadingFallback = useMemo(() => /* @__PURE__ */ jsx(LoadingComponent, {}), []);
  return /* @__PURE__ */ jsx(ErrorBoundary, { fallbackRender: ErrorFallback, children: /* @__PURE__ */ jsx(Suspense, { fallback: loadingFallback, children }) });
};
const LoadingComponent = () => /* @__PURE__ */ jsx("div", { children: "Loading..." });

export { RenderLayer, hasPositionClass };
