/**
 * StepEditor — Step management + per-step field editing for Multi-Step mode.
 *
 * Left sidebar:  Elements palette / Design settings / Inline field settings.
 * Right canvas:  Step tabs + field grid (supports sections with columns).
 *
 * @package ArraySubsPro
 */
import React, { useState, useCallback, useMemo, useEffect } from "react";
import {
  DndContext,
  DragOverlay,
  KeyboardSensor,
  PointerSensor,
  pointerWithin,
  closestCenter,
  useDroppable,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import {
  SortableContext,
  arrayMove,
  rectSortingStrategy,
  sortableKeyboardCoordinates,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { __ } from "@wordpress/i18n";
import { Plus, Trash2, GripVertical, Pencil, Check, X } from "lucide-react";
import FieldCard from "./FieldCard";
import FieldSettingsPanel from "./FieldSettingsPanel";
import DesignPanel from "./DesignPanel";
import ElementPalette from "./ElementPalette";
import SectionContainer, {
  SEC_COL_PREFIX,
  COL_ITEM_PREFIX,
  isColItemId,
  isSecColId,
  parseColItemId,
  parseSecColId,
} from "./SectionContainer";
import {
  generateStepId,
  generateUniqueFieldKey,
  CHECKOUT_COUPON_NOTICES_KEY,
  CHECKOUT_COUPON_NOTICES_TYPE,
  ORDER_INFO_PAYMENT_KEY,
  ORDER_INFO_PAYMENT_TYPE,
  ORDER_NOTES_KEY,
  ORDER_NOTES_TYPE,
  createCheckoutCouponNoticesElement,
  createOrderInfoPaymentElement,
  createOrderNotesElement,
  createDraftFieldFromType,
} from "./utils";

const PALETTE_PREFIX = "palette:";

/**
 * Custom collision detection: prefer section-column droppables when pointer
 * is inside one, otherwise fall back to closestCenter for the top-level grid.
 */
const builderCollision = (args) => {
  const pointer = pointerWithin(args);
  const secCols = pointer.filter(
    (c) => isSecColId(String(c.id)) || isColItemId(String(c.id)),
  );
  if (secCols.length > 0) return secCols;
  return closestCenter(args);
};

/* ── Droppable step grid ────────────────────────────────── */

const StepGrid = ({ id, children }) => {
  const { setNodeRef, isOver } = useDroppable({ id });

  return (
    <div
      ref={setNodeRef}
      className={`arraysubs-cb-step-editor__grid${
        isOver ? " arraysubs-cb-step-editor__grid--over" : ""
      }`}
    >
      {children}
    </div>
  );
};

/* ── Sortable top-level field card ──────────────────────── */

const SortableFieldCard = ({ field, onEdit, onRemove }) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: field.key });

  return (
    <FieldCard
      field={field}
      onEdit={onEdit}
      onRemove={onRemove}
      innerRef={setNodeRef}
      draggableProps={{
        style: {
          transform: CSS.Transform.toString(transform),
          transition,
          opacity: isDragging ? 0.4 : 1,
        },
      }}
      dragHandleProps={{
        ...attributes,
        ...listeners,
      }}
    />
  );
};

/* ── Sortable section within the step grid ──────────────── */

const SortableSection = ({
  section,
  stepId,
  onEdit,
  onRemove,
  onFieldEdit,
  onFieldRemove,
}) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: section.key });

  return (
    <SectionContainer
      section={section}
      stepId={stepId}
      onEdit={onEdit}
      onRemove={onRemove}
      onFieldEdit={onFieldEdit}
      onFieldRemove={onFieldRemove}
      innerRef={setNodeRef}
      draggableProps={{
        style: {
          transform: CSS.Transform.toString(transform),
          transition,
          opacity: isDragging ? 0.4 : 1,
        },
      }}
      dragHandleProps={{
        ...attributes,
        ...listeners,
      }}
    />
  );
};

/* ── Sortable step tab ──────────────────────────────────── */

const SortableStepTab = ({
  step,
  index,
  isActive,
  editingStepName,
  tempStepName,
  setTempStepName,
  handleStepNameSave,
  handleStepNameCancel,
  setActiveStepId,
  handleStepNameEdit,
  handleRemoveStep,
  stepsLength,
}) => {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({ id: step.id });

  return (
    <div
      ref={setNodeRef}
      style={{
        transform: CSS.Transform.toString(transform),
        transition,
      }}
      className={`arraysubs-cb-step-tab${
        isActive ? " arraysubs-cb-step-tab--active" : ""
      }`}
    >
      <div
        className="arraysubs-cb-step-tab__drag"
        {...attributes}
        {...listeners}
      >
        <GripVertical size={12} />
      </div>

      {editingStepName === step.id ? (
        <div className="arraysubs-cb-step-tab__edit">
          <input
            type="text"
            value={tempStepName}
            onChange={(e) => setTempStepName(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === "Enter") handleStepNameSave(step.id);
              if (e.key === "Escape") handleStepNameCancel();
            }}
            className="arraysubs-cb-step-tab__input"
            autoFocus
          />
          <button
            type="button"
            onClick={() => handleStepNameSave(step.id)}
            className="arraysubs-cb-step-tab__btn"
          >
            <Check size={12} />
          </button>
          <button
            type="button"
            onClick={handleStepNameCancel}
            className="arraysubs-cb-step-tab__btn"
          >
            <X size={12} />
          </button>
        </div>
      ) : (
        <button
          type="button"
          className="arraysubs-cb-step-tab__label"
          onClick={() => setActiveStepId(step.id)}
        >
          <span className="arraysubs-cb-step-tab__number">{index + 1}</span>
          {step.name}
        </button>
      )}

      <div className="arraysubs-cb-step-tab__actions">
        <button
          type="button"
          className="arraysubs-cb-step-tab__btn"
          onClick={() => handleStepNameEdit(step.id)}
          title={__("Rename", "arraysubs")}
        >
          <Pencil size={10} />
        </button>
        {stepsLength > 1 && (
          <button
            type="button"
            className="arraysubs-cb-step-tab__btn arraysubs-cb-step-tab__btn--delete"
            onClick={() => handleRemoveStep(step.id)}
            title={__("Delete Step", "arraysubs")}
          >
            <Trash2 size={10} />
          </button>
        )}
      </div>
    </div>
  );
};

/* ── Drag overlay preview ───────────────────────────────── */

const DragPreview = ({ item }) => {
  if (!item) return null;

  return (
    <div className="arraysubs-cb-drag-preview">
      <GripVertical size={14} />
      <span>{item.label}</span>
    </div>
  );
};

/* ================================================================
 * Main StepEditor
 * ================================================================ */

const StepEditor = ({
  steps,
  onStepsChange,
  design,
  onDesignChange,
  fieldTypes,
  wcDefaults,
}) => {
  /* ── State ──────────────────────────────────────────── */

  const [activeStepId, setActiveStepId] = useState(steps[0]?.id || null);
  const [editingStepName, setEditingStepName] = useState(null);
  const [tempStepName, setTempStepName] = useState("");

  // Sidebar editing
  const [editingField, setEditingField] = useState(null);
  const [editContext, setEditContext] = useState(null);
  const [sidebarTab, setSidebarTab] = useState("elements");

  // DnD
  const [activeDrag, setActiveDrag] = useState(null);

  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    }),
  );

  /* ── Derived data ──────────────────────────────────── */

  const allFields = useMemo(() => {
    const collect = (fields) =>
      (fields || []).flatMap((f) => {
        if (f.type === "section" && f.children) {
          return [f, ...f.children.flatMap((col) => col || [])];
        }
        return [f];
      });
    return steps.flatMap((s) => collect(s.fields));
  }, [steps]);

  const activeStep = steps.find((s) => s.id === activeStepId) || steps[0];
  const stepFields = activeStep?.fields || [];
  const activeStepGridId = activeStep
    ? `step-grid:${activeStep.id}`
    : "step-grid";

  useEffect(() => {
    if (!steps.length) {
      setActiveStepId(null);
      return;
    }
    if (!steps.some((step) => step.id === activeStepId)) {
      setActiveStepId(steps[0].id);
    }
  }, [steps, activeStepId]);

  /* ── Step operations ──────────────────────────────── */

  const handleAddStep = useCallback(() => {
    const newStep = {
      id: generateStepId(),
      name: __("New Step", "arraysubs"),
      icon: "",
      fields: [],
    };
    onStepsChange([...steps, newStep]);
    setActiveStepId(newStep.id);
  }, [steps, onStepsChange]);

  const handleRemoveStep = useCallback(
    (stepId) => {
      if (steps.length <= 1) return;
      const updated = steps.filter((s) => s.id !== stepId);
      if (activeStepId === stepId) setActiveStepId(updated[0]?.id || null);
      onStepsChange(updated);
    },
    [steps, activeStepId, onStepsChange],
  );

  const handleStepNameEdit = useCallback(
    (stepId) => {
      const step = steps.find((s) => s.id === stepId);
      setEditingStepName(stepId);
      setTempStepName(step?.name || "");
    },
    [steps],
  );

  const handleStepNameSave = useCallback(
    (stepId) => {
      const updated = steps.map((s) =>
        s.id === stepId ? { ...s, name: tempStepName || s.name } : s,
      );
      onStepsChange(updated);
      setEditingStepName(null);
    },
    [steps, tempStepName, onStepsChange],
  );

  const handleStepNameCancel = useCallback(() => {
    setEditingStepName(null);
  }, []);

  const handleStepsDragEnd = useCallback(
    ({ active, over }) => {
      if (!over || active.id === over.id) return;
      const oldIndex = steps.findIndex((step) => step.id === active.id);
      const newIndex = steps.findIndex((step) => step.id === over.id);
      if (oldIndex < 0 || newIndex < 0) return;
      onStepsChange(arrayMove(steps, oldIndex, newIndex));
    },
    [steps, onStepsChange],
  );

  /* ── Sidebar editing helpers ──────────────────────── */

  const closeSettings = useCallback(() => {
    setEditingField(null);
    setEditContext(null);
  }, []);

  const getContextStepId = useCallback(
    (ctx = null) => ctx?.stepId || activeStep?.id || null,
    [activeStep],
  );

  const getContextFieldKey = useCallback(
    (field, ctx = null) => ctx?.fieldKey || field?.key || null,
    [],
  );

  const openFieldEdit = useCallback(
    (field, ctx = null) => {
      setEditingField(field);
      setEditContext(
        ctx
          ? { ...ctx, fieldKey: ctx.fieldKey || field?.key || null }
          : {
              location: "top-level",
              stepId: activeStep?.id || null,
              fieldKey: field?.key || null,
            },
      );
    },
    [activeStep],
  );

  /**
   * Immediately insert a new field from palette into the step.
   * The field gets a default label and auto-generated unique key.
   */
  const insertFieldImmediate = useCallback(
    (type, label, ctx = null, index = null) => {
      if (!activeStep) return;

      const draft = createDraftFieldFromType(type, label);

      // Deduplicate the key against all existing keys.
      const existingKeys = allFields.map((f) => f.key);
      if (!draft.is_builtin && !draft.key.startsWith("_arraysubs_cf_")) {
        const baseKey = generateUniqueFieldKey(
          draft.label,
          existingKeys.map((k) => k.replace(/^_arraysubs_cf_/, "")),
        );
        draft.key = `_arraysubs_cf_${baseKey}`;
      }

      // For order_info_payment, ensure there's only one.
      if (type === ORDER_INFO_PAYMENT_TYPE) {
        Object.assign(draft, createOrderInfoPaymentElement());
      }

      // For checkout_coupon_notices, ensure there's only one.
      if (type === CHECKOUT_COUPON_NOTICES_TYPE) {
        Object.assign(draft, createCheckoutCouponNoticesElement());
      }

      // For order_notes, ensure there's only one.
      if (type === ORDER_NOTES_TYPE) {
        Object.assign(draft, createOrderNotesElement());
      }

      const location = ctx?.location || "top-level";

      // Sections cannot be nested inside other sections.
      if (
        location === "section-column" &&
        (type === "section" || type === CHECKOUT_COUPON_NOTICES_TYPE)
      ) {
        return;
      }

      if (location === "section-column") {
        const targetStepId = ctx?.stepId || activeStep.id;
        const updated = steps.map((s) => {
          if (s.id !== targetStepId) return s;
          return {
            ...s,
            fields: (s.fields || []).map((f) => {
              if (f.key !== ctx.sectionKey || f.type !== "section") return f;
              const cols = (f.children || [[]]).map((col, ci) => {
                if (ci !== ctx.colIndex) return col;
                return [...(col || []), draft];
              });
              return { ...f, children: cols };
            }),
          };
        });
        onStepsChange(updated);
        // Open settings panel so user can refine if desired.
        setEditingField(draft);
        setEditContext({
          ...ctx,
          stepId: targetStepId,
          fieldKey: draft.key,
        });
        return;
      }

      // Top-level insertion.
      const targetStepId = ctx?.stepId || activeStep.id;
      const updated = steps.map((s) => {
        let fields = [...(s.fields || [])];

        // Remove duplicate order_info_payment.
        if (type === ORDER_INFO_PAYMENT_TYPE) {
          fields = fields.filter((f) => f.key !== ORDER_INFO_PAYMENT_KEY);
        }

        // Remove duplicate checkout_coupon_notices.
        if (type === CHECKOUT_COUPON_NOTICES_TYPE) {
          fields = fields.filter((f) => f.key !== CHECKOUT_COUPON_NOTICES_KEY);
        }

        // Remove duplicate order_notes.
        if (type === ORDER_NOTES_TYPE) {
          fields = fields.filter((f) => f.key !== ORDER_NOTES_KEY);
        }

        if (s.id !== targetStepId) return { ...s, fields };

        const insertIdx =
          index != null
            ? Math.min(Math.max(index, 0), fields.length)
            : fields.length;
        fields.splice(insertIdx, 0, draft);
        return { ...s, fields };
      });
      onStepsChange(updated);
      // Open settings panel so user can refine.
      setEditingField(draft);
      setEditContext(
        ctx || {
          location: "top-level",
          stepId: targetStepId,
          fieldKey: draft.key,
        },
      );
    },
    [steps, activeStep, allFields, onStepsChange],
  );

  /* ── Field operations ─────────────────────────────── */

  const handleFieldEdit = useCallback(
    (field, ctx) => openFieldEdit(field, ctx),
    [openFieldEdit],
  );

  const handleFieldRemove = useCallback(
    (fieldKey, ctx) => {
      const targetStepId = getContextStepId(ctx);
      if (!targetStepId) return;

      if (ctx?.location === "section-column") {
        const updated = steps.map((s) => {
          if (s.id !== targetStepId) return s;
          return {
            ...s,
            fields: (s.fields || []).map((f) => {
              if (f.key !== ctx.sectionKey || f.type !== "section") return f;
              const cols = (f.children || [[]]).map((col, ci) =>
                ci === ctx.colIndex
                  ? (col || []).filter((c) => c.key !== fieldKey)
                  : col,
              );
              return { ...f, children: cols };
            }),
          };
        });
        onStepsChange(updated);
        return;
      }

      const updated = steps.map((s) =>
        s.id === targetStepId
          ? { ...s, fields: (s.fields || []).filter((f) => f.key !== fieldKey) }
          : s,
      );
      onStepsChange(updated);
    },
    [steps, getContextStepId, onStepsChange],
  );

  const handleFieldSave = useCallback(
    (updatedField) => {
      const targetStepId = getContextStepId(editContext);
      const sourceFieldKey = getContextFieldKey(updatedField, editContext);
      if (!targetStepId) return;

      const normalizedField =
        updatedField.type === CHECKOUT_COUPON_NOTICES_TYPE
          ? createCheckoutCouponNoticesElement({
              ...updatedField,
              key: CHECKOUT_COUPON_NOTICES_KEY,
            })
          : updatedField.type === ORDER_INFO_PAYMENT_TYPE
          ? createOrderInfoPaymentElement({
              ...updatedField,
              key: ORDER_INFO_PAYMENT_KEY,
            })
          : updatedField.type === ORDER_NOTES_TYPE
          ? createOrderNotesElement({
              ...updatedField,
              key: ORDER_NOTES_KEY,
            })
          : updatedField;

      // Save into a section column.
      if (editContext?.location === "section-column") {
        const updated = steps.map((s) => {
          if (s.id !== targetStepId) return s;
          return {
            ...s,
            fields: (s.fields || []).map((f) => {
              if (f.key !== editContext.sectionKey || f.type !== "section")
                return f;
              const cols = (f.children || [[]]).map((col, ci) => {
                if (ci !== editContext.colIndex) return col;
                const arr = [...(col || [])];
                const idx = arr.findIndex((c) => c.key === sourceFieldKey);
                if (idx >= 0) arr[idx] = normalizedField;
                return arr;
              });
              return { ...f, children: cols };
            }),
          };
        });
        onStepsChange(updated);
        setEditingField(normalizedField);
        setEditContext((prev) =>
          prev ? { ...prev, fieldKey: normalizedField.key } : prev,
        );
        return;
      }

      // Save to top-level fields (always update in-place).
      const updated = steps.map((s) => {
        let fields = [...(s.fields || [])];

        if (normalizedField.type === CHECKOUT_COUPON_NOTICES_TYPE) {
          fields = fields.filter(
            (field) => field.key !== CHECKOUT_COUPON_NOTICES_KEY,
          );
        }

        if (normalizedField.type === ORDER_INFO_PAYMENT_TYPE) {
          fields = fields.filter(
            (field) => field.key !== ORDER_INFO_PAYMENT_KEY,
          );
        }

        if (s.id !== targetStepId) return { ...s, fields };

        fields = fields.map((f) =>
          f.key === sourceFieldKey ? normalizedField : f,
        );

        if (
          normalizedField.type === CHECKOUT_COUPON_NOTICES_TYPE &&
          !fields.some((field) => field.key === CHECKOUT_COUPON_NOTICES_KEY)
        ) {
          fields.push(normalizedField);
        }

        if (
          normalizedField.type === ORDER_INFO_PAYMENT_TYPE &&
          !fields.some((field) => field.key === ORDER_INFO_PAYMENT_KEY)
        ) {
          fields.push(normalizedField);
        }

        return { ...s, fields };
      });

      onStepsChange(updated);
      setEditingField(normalizedField);
      setEditContext((prev) =>
        prev ? { ...prev, fieldKey: normalizedField.key } : prev,
      );
    },
    [steps, editContext, getContextFieldKey, getContextStepId, onStepsChange],
  );

  /* ── DnD handlers ─────────────────────────────────── */

  const handleDragStart = useCallback(
    ({ active }) => {
      const id = String(active.id);

      if (id.startsWith(PALETTE_PREFIX)) {
        setActiveDrag({
          type: "palette",
          label: active.data.current?.fieldLabel || "",
        });
      } else if (isColItemId(id)) {
        const parsed = parseColItemId(id);
        const section = stepFields.find((f) => f.key === parsed.sectionKey);
        const field = section?.children?.[parsed.colIndex]?.find(
          (f) => f.key === parsed.fieldKey,
        );
        setActiveDrag({
          type: "column-item",
          label: field?.label || parsed.fieldKey,
        });
      } else {
        const field = stepFields.find((f) => f.key === id);
        setActiveDrag({
          type: "field",
          label: field?.label || field?.key || id,
        });
      }
    },
    [stepFields],
  );

  const handleDragCancel = useCallback(() => setActiveDrag(null), []);

  const handleFieldsDragEnd = useCallback(
    ({ active, over }) => {
      setActiveDrag(null);
      if (!activeStep || !over) return;

      const activeId = String(active.id);
      const overId = String(over.id);
      const isPalette = activeId.startsWith(PALETTE_PREFIX);
      const activeIsColItem = isColItemId(activeId);
      const overIsSecCol = isSecColId(overId);
      const overIsColItem = isColItemId(overId);

      /* ── Palette drops ─────────────────────────────── */

      if (isPalette) {
        const type = active.data.current?.fieldType;
        const label = active.data.current?.fieldLabel || "";
        if (!type) return;

        // Drop into a section column.
        if (overIsSecCol || overIsColItem) {
          const parsed = overIsSecCol
            ? parseSecColId(overId)
            : parseColItemId(overId);
          insertFieldImmediate(type, label, {
            location: "section-column",
            stepId: activeStep.id,
            sectionKey: parsed.sectionKey,
            colIndex: parsed.colIndex,
          });
          return;
        }

        // Drop into top-level grid.
        const newIndex =
          overId === activeStepGridId
            ? stepFields.length
            : stepFields.findIndex((f) => f.key === overId);
        insertFieldImmediate(
          type,
          label,
          { location: "top-level", stepId: activeStep.id },
          newIndex >= 0 ? newIndex : stepFields.length,
        );
        return;
      }

      /* ── Top-level field → section column ───────── */

      if (!activeIsColItem && !isPalette && (overIsSecCol || overIsColItem)) {
        const draggedField = stepFields.find((f) => f.key === activeId);
        if (!draggedField) return;

        // Sections cannot be nested inside other sections.
        if (draggedField.type === "section") return;

        const parsed = overIsSecCol
          ? parseSecColId(overId)
          : parseColItemId(overId);

        const updated = steps.map((s) => {
          if (s.id !== activeStep.id) return s;
          // Remove from top-level and insert into section column.
          const withoutDragged = (s.fields || []).filter(
            (f) => f.key !== activeId,
          );
          return {
            ...s,
            fields: withoutDragged.map((f) => {
              if (f.key !== parsed.sectionKey || f.type !== "section") return f;
              const cols = (f.children || [[]]).map((col, ci) => {
                if (ci !== parsed.colIndex) return col;
                return [...(col || []), draggedField];
              });
              return { ...f, children: cols };
            }),
          };
        });
        onStepsChange(updated);
        return;
      }

      /* ── Column item reorder ───────────────────────── */

      if (activeIsColItem && (overIsColItem || overIsSecCol)) {
        const src = parseColItemId(activeId);
        const dst = overIsColItem
          ? parseColItemId(overId)
          : parseSecColId(overId);

        if (src.sectionKey !== dst.sectionKey) return;

        if (src.colIndex === dst.colIndex) {
          // Reorder within the same column.
          const updated = steps.map((s) => {
            if (s.id !== activeStep.id) return s;
            return {
              ...s,
              fields: (s.fields || []).map((f) => {
                if (f.key !== src.sectionKey || f.type !== "section") return f;
                const cols = (f.children || [[]]).map((col, ci) => {
                  if (ci !== src.colIndex) return col;
                  const arr = [...(col || [])];
                  const oldIdx = arr.findIndex((c) => c.key === src.fieldKey);
                  const newIdx = overIsColItem
                    ? arr.findIndex((c) => c.key === dst.fieldKey)
                    : arr.length - 1;
                  if (oldIdx < 0 || newIdx < 0) return col;
                  return arrayMove(arr, oldIdx, newIdx);
                });
                return { ...f, children: cols };
              }),
            };
          });
          onStepsChange(updated);
        }
        return;
      }

      /* ── Top-level field reorder ───────────────────── */

      if (activeId === overId) return;
      const oldIndex = stepFields.findIndex((f) => f.key === activeId);
      const newIndex =
        overId === activeStepGridId
          ? stepFields.length - 1
          : stepFields.findIndex((f) => f.key === overId);
      if (oldIndex < 0 || newIndex < 0) return;

      const reordered = arrayMove(stepFields, oldIndex, newIndex);
      const updated = steps.map((step) =>
        step.id === activeStep.id ? { ...step, fields: reordered } : step,
      );
      onStepsChange(updated);
    },
    [
      steps,
      activeStep,
      activeStepGridId,
      stepFields,
      onStepsChange,
      insertFieldImmediate,
    ],
  );

  /* ── Step navigation layout ───────────────────────── */

  const stepPosition = design?.step_position || "top";
  const stepSortingStrategy =
    stepPosition === "left" ? verticalListSortingStrategy : rectSortingStrategy;

  /* ── Sidebar content ──────────────────────────────── */

  const sidebarContent = editingField ? (
    <FieldSettingsPanel
      field={editingField}
      allFields={allFields}
      onSave={handleFieldSave}
      onClose={closeSettings}
      wcDefaults={wcDefaults}
    />
  ) : (
    <>
      <div className="arraysubs-cb-builder-sidebar__tabs">
        <button
          type="button"
          className={`arraysubs-cb-builder-sidebar__tab${
            sidebarTab === "elements"
              ? " arraysubs-cb-builder-sidebar__tab--active"
              : ""
          }`}
          onClick={() => setSidebarTab("elements")}
        >
          {__("Elements", "arraysubs")}
        </button>
        <button
          type="button"
          className={`arraysubs-cb-builder-sidebar__tab${
            sidebarTab === "design"
              ? " arraysubs-cb-builder-sidebar__tab--active"
              : ""
          }`}
          onClick={() => setSidebarTab("design")}
        >
          {__("Design", "arraysubs")}
        </button>
      </div>

      <div className="arraysubs-cb-builder-sidebar__panel">
        {sidebarTab === "elements" ? (
          <ElementPalette fieldTypes={fieldTypes} />
        ) : (
          <DesignPanel design={design} onChange={onDesignChange} />
        )}
      </div>
    </>
  );

  /* ── Render ───────────────────────────────────────── */

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={builderCollision}
      onDragStart={handleDragStart}
      onDragEnd={handleFieldsDragEnd}
      onDragCancel={handleDragCancel}
    >
      <div className="arraysubs-cb-builder-workspace">
        {/* LEFT SIDEBAR */}
        <aside className="arraysubs-cb-builder-sidebar">{sidebarContent}</aside>

        {/* WORKSPACE */}
        <div
          className={`arraysubs-cb-step-editor arraysubs-cb-step-editor--nav-${stepPosition}`}
        >
          <DndContext
            sensors={sensors}
            collisionDetection={closestCenter}
            onDragEnd={handleStepsDragEnd}
          >
            <SortableContext
              items={steps.map((step) => step.id)}
              strategy={stepSortingStrategy}
            >
              <div className="arraysubs-cb-step-editor__nav">
                {steps.map((step, index) => (
                  <SortableStepTab
                    key={step.id}
                    step={step}
                    index={index}
                    isActive={activeStepId === step.id}
                    editingStepName={editingStepName}
                    tempStepName={tempStepName}
                    setTempStepName={setTempStepName}
                    handleStepNameSave={handleStepNameSave}
                    handleStepNameCancel={handleStepNameCancel}
                    setActiveStepId={setActiveStepId}
                    handleStepNameEdit={handleStepNameEdit}
                    handleRemoveStep={handleRemoveStep}
                    stepsLength={steps.length}
                  />
                ))}

                <button
                  type="button"
                  className="arraysubs-cb-step-editor__add-step"
                  onClick={handleAddStep}
                >
                  <Plus size={14} />
                  {__("Add Step", "arraysubs")}
                </button>
              </div>
            </SortableContext>
          </DndContext>

          <div className="arraysubs-cb-step-editor__content">
            {activeStep ? (
              <>
                <div className="arraysubs-cb-step-editor__header">
                  <h3>{activeStep.name}</h3>
                  <span className="arraysubs-cb-step-editor__count">
                    {stepFields.length}{" "}
                    {stepFields.length === 1
                      ? __("element", "arraysubs")
                      : __("elements", "arraysubs")}
                  </span>
                </div>

                <SortableContext
                  items={stepFields.map((f) => f.key)}
                  strategy={verticalListSortingStrategy}
                >
                  <StepGrid id={activeStepGridId}>
                    {stepFields.map((field) =>
                      field.type === "section" ? (
                        <SortableSection
                          key={field.key}
                          section={field}
                          stepId={activeStep.id}
                          onEdit={handleFieldEdit}
                          onRemove={handleFieldRemove}
                          onFieldEdit={handleFieldEdit}
                          onFieldRemove={handleFieldRemove}
                        />
                      ) : (
                        <SortableFieldCard
                          key={field.key}
                          field={field}
                          onEdit={(item) =>
                            handleFieldEdit(item, {
                              location: "top-level",
                              stepId: activeStep.id,
                            })
                          }
                          onRemove={(fieldKey) =>
                            handleFieldRemove(fieldKey, {
                              location: "top-level",
                              stepId: activeStep.id,
                            })
                          }
                        />
                      ),
                    )}

                    {stepFields.length === 0 && (
                      <p className="arraysubs-cb-step-editor__empty">
                        {__(
                          "Drag elements from the sidebar to get started.",
                          "arraysubs",
                        )}
                      </p>
                    )}
                  </StepGrid>
                </SortableContext>
              </>
            ) : (
              <p className="arraysubs-cb-step-editor__empty">
                {__("Select a step to edit its elements.", "arraysubs")}
              </p>
            )}
          </div>
        </div>
      </div>

      {/* Drag overlay for visual feedback */}
      <DragOverlay dropAnimation={{ duration: 200, easing: "ease" }}>
        {activeDrag && <DragPreview item={activeDrag} />}
      </DragOverlay>
    </DndContext>
  );
};

export default StepEditor;
