import { memo } from "react";
import { Layer, Group } from "react-konva";
import Konva from "konva";
import ObjectRenderer from "./ObjectRenderer";
import TransformerControls from "./TransformerControls";
import GroupMaskButtons from "./GroupMaskButtons";
import type { EditorObject } from "../../store/editorStore";

interface ObjectsLayerProps {
    layerRef: React.RefObject<Konva.Layer | null>;
    objects: EditorObject[];
    selectedObjectIds: string[];
    selectedCellId: string | null;
    tool: string;
    transformerRef: React.RefObject<Konva.Transformer | null>;
    selectedObject: EditorObject | null;
    isGroupedWithMask: boolean;
    maskObject: EditorObject | null;
    canGroup: boolean;
    canUngroup: boolean;
    onSelect: (id: string, node: Konva.Node, e?: Konva.KonvaEventObject<MouseEvent>) => void;
    onUpdate: (id: string, updates: Partial<EditorObject>) => void;
    onCellClick: (tableId: string, cellId: string, e?: Konva.KonvaEventObject<MouseEvent>) => void;
    onCellDblClick: (
        tableId: string,
        cellId: string,
        x: number,
        y: number,
        width: number,
        height: number,
        text: string
    ) => void;
    onGroup: (objectId: string, maskId: string) => void;
    onUngroup: (groupId: string) => void;
    stageWidth: number;
    stageHeight: number;
}

const ObjectsLayer = ({
    layerRef,
    objects,
    selectedObjectIds,
    selectedCellId,
    tool,
    transformerRef,
    selectedObject,
    isGroupedWithMask,
    maskObject,
    canGroup,
    canUngroup,
    onSelect,
    onUpdate,
    onCellClick,
    onCellDblClick,
    onGroup,
    onUngroup,
    stageWidth,
    stageHeight,
}: ObjectsLayerProps) => {
    return (
        <Layer ref={layerRef} listening={tool !== "pencil"}>
            {/* Render group objects first */}
            {objects
                .filter((obj) => obj.type === "group")
                .map((obj) => (
                    <ObjectRenderer
                        key={obj.id}
                        obj={obj}
                        isSelected={selectedObjectIds.includes(obj.id)}
                        transformerRef={transformerRef}
                        layerRef={layerRef}
                        onSelect={onSelect}
                        onUpdate={onUpdate}
                        draggable={tool === "select"}
                        onCellClick={onCellClick}
                        onCellDblClick={onCellDblClick}
                        selectedCellId={selectedCellId}
                        allObjects={objects}
                        stageWidth={stageWidth}
                        stageHeight={stageHeight}
                    />
                ))}
            {/* Render non-grouped objects */}
            {objects
                .filter((obj) => !obj.groupId && obj.type !== "group")
                .map((obj) => (
                    <ObjectRenderer
                        key={obj.id}
                        obj={obj}
                        isSelected={selectedObjectIds.includes(obj.id)}
                        transformerRef={transformerRef}
                        layerRef={layerRef}
                        onSelect={onSelect}
                        onUpdate={onUpdate}
                        draggable={tool === "select"}
                        onCellClick={onCellClick}
                        onCellDblClick={onCellDblClick}
                        selectedCellId={selectedCellId}
                        allObjects={objects}
                        stageWidth={stageWidth}
                        stageHeight={stageHeight}
                    />
                ))}
            {/* Render objects inside groups - they should not be interactive */}
            {objects
                .filter((obj) => obj.groupId && obj.type !== "group")
                .map((obj) => {
                    const groupObject = objects.find((o) => o.id === obj.groupId);
                    if (!groupObject) return null;

                    // Render with absolute position but wrapped in non-listening group
                    return (
                        <Group key={`group-member-${obj.id}`} listening={false}>
                            <ObjectRenderer
                                key={obj.id}
                                obj={obj}
                                isSelected={false}
                                transformerRef={transformerRef}
                                layerRef={layerRef}
                                onSelect={onSelect}
                                onUpdate={onUpdate}
                                draggable={false}
                                onCellClick={onCellClick}
                                onCellDblClick={onCellDblClick}
                                selectedCellId={selectedCellId}
                                allObjects={objects}
                                stageWidth={stageWidth}
                                stageHeight={stageHeight}
                            />
                        </Group>
                    );
                })}

            {/* Transformer and Group/Mask buttons must be inside the same Layer */}
            {selectedObject && (
                <>
                    <TransformerControls
                        transformerRef={transformerRef}
                        selectedObject={selectedObject}
                        isGroupedWithMask={isGroupedWithMask}
                    />
                    <GroupMaskButtons
                        selectedObject={selectedObject}
                        maskObject={maskObject}
                        canGroup={canGroup}
                        canUngroup={canUngroup}
                        onGroup={onGroup}
                        onUngroup={onUngroup}
                    />
                </>
            )}
        </Layer>
    );
};

// Memoized to prevent re-renders when EditorCanvas state that is unrelated to
// object rendering changes (e.g. activeGuideIds during drag). All function
// props are stabilised via useCallback in their respective hooks so this memo
// is effective — preventing the cascade: setActiveGuideIds → EditorCanvas
// re-render → ObjectsLayer re-render → every ObjectRenderer re-render →
// react-konva reconcile + batchDraw for every drag-move pixel.
export default memo(ObjectsLayer);

