import { useEffect, useRef } from "react";
import { Stage, Layer, Transformer, Rect } from "react-konva";
import Konva from "konva";
import { useEditorStore } from "../store/editorStore";
import { useDrawingHandlers } from "./canvas/useDrawingHandlers";
import { useStageSize } from "./canvas/useStageSize";
import { useKeyboardMovement } from "./canvas/useKeyboardMovement";
import ObjectRenderer from "./canvas/ObjectRenderer";
import { getMaskForObject } from "./canvas/maskUtils";
import CellEditor from "@/components/CellEditor";
import ZoomControls from "./ZoomControls";

const EditorCanvas = () => {
  const stageRef = useRef<Konva.Stage>(null);
  const layerRef = useRef<Konva.Layer>(null);

  const {
    tool,
    objects,
    updateObject,
    selectedObjectId,
    setSelectedObjectId,
    setSelectedTableId,
    selectedCellId,
    setSelectedCellId,
    editingCell,
    setEditingCell,
    updateCellValue,
    applyTableResize,
    setStageRef,
    setLayerRef,
    zoom,
  } = useEditorStore();

  const { transformerRef, handleStageMouseDown, handleStageMouseMove, handleStageMouseUp } = useDrawingHandlers();
  const stageSize = useStageSize();
  useKeyboardMovement();

  useEffect(() => {
    if (stageRef.current) {
      setStageRef(stageRef);
    }
    if (layerRef.current) {
      setLayerRef(layerRef);
    }
  }, [setStageRef, setLayerRef]);

  const handleSelect = (id: string, node: Konva.Node) => {
    const obj = objects.find((o) => o.id === id);
    setSelectedObjectId(id);
    if (obj?.type === "grid") {
      setSelectedTableId(id);
    } else {
      setSelectedTableId(null);
    }
    setSelectedCellId(null);
    if (transformerRef.current) {
      transformerRef.current.nodes([node]);
      transformerRef.current.getLayer()?.batchDraw();
    }
  };

  const handleCellClick = (tableId: string, cellId: string) => {
    setSelectedTableId(tableId);
    setSelectedObjectId(tableId);
    setSelectedCellId(cellId);
    const obj = objects.find((o) => o.id === tableId);
    if (obj && transformerRef.current && layerRef.current) {
      const tableNode = layerRef.current.findOne(`#${tableId}`);
      if (tableNode) {
        transformerRef.current.nodes([tableNode]);
        transformerRef.current.getLayer()?.batchDraw();
      }
    }
  };

  const handleCellDblClick = (tableId: string, cellId: string, x: number, y: number, width: number, height: number, text: string) => {
    setEditingCell({ tableId, cellId, x, y, width, height, value: text });
  };

  const handleCellEditorSave = (text: string) => {
    if (editingCell) {
      updateCellValue(editingCell.tableId, editingCell.cellId, text);
      setEditingCell(null);
    }
  };

  const handleCellEditorCancel = () => {
    setEditingCell(null);
  };

  // Attach transformer to selected object when it changes
  useEffect(() => {
    if (!transformerRef.current || !selectedObjectId || !layerRef.current) return;

    const selectedObject = objects.find((obj) => obj.id === selectedObjectId);
    if (!selectedObject) return;

    // For grid objects, handle separately
    if (selectedObject.type === "grid") {
      const tableNode = layerRef.current.findOne(`#${selectedObjectId}`);
      if (tableNode && transformerRef.current) {
        transformerRef.current.nodes([tableNode]);
        transformerRef.current.getLayer()?.batchDraw();
      }
      return;
    }

    // For other objects (like images), find the node by id and attach transformer
    // Use a small delay to ensure the node is mounted (especially for images that need to load)
    const timeoutId = setTimeout(() => {
      if (!layerRef.current || !transformerRef.current) return;

      // Check if object is masked - if so, find parent Group
      const maskShape = getMaskForObject(selectedObject, objects);
      let node: Konva.Node | undefined;
      
      if (maskShape) {
        node = layerRef.current.findOne(`.masked-group-${selectedObjectId}`);
      } else {
        node = layerRef.current.findOne(`#${selectedObjectId}`);
      }
      
      if (node && transformerRef.current) {
        transformerRef.current.nodes([node]);
        transformerRef.current.getLayer()?.batchDraw();
      }
    }, 100);

    return () => clearTimeout(timeoutId);
  }, [selectedObjectId, objects, transformerRef, layerRef]);

  useEffect(() => {
    if (!transformerRef.current || !selectedObjectId) return;

    const selectedObject = objects.find((obj) => obj.id === selectedObjectId);
    if (selectedObject?.type !== "grid") return;

    const transformer = transformerRef.current;
    const handleTransformEnd = () => {
      const node = transformer.nodes()[0];
      if (!node || !selectedObject) return;

      const scaleX = node.scaleX();
      const scaleY = node.scaleY();

      node.scaleX(1);
      node.scaleY(1);

      const newWidth = (selectedObject.width || 300) * scaleX;
      const newHeight = (selectedObject.height || 200) * scaleY;

      applyTableResize(selectedObject.id, newWidth, newHeight);
      updateObject(selectedObject.id, {
        x: node.x(),
        y: node.y(),
      });
    };

    transformer.on("transformend", handleTransformEnd);

    return () => {
      transformer.off("transformend", handleTransformEnd);
    };
  }, [selectedObjectId, objects, transformerRef, applyTableResize, updateObject]);

  const finalScale = stageSize.scale * zoom;

  return (
    <div className="flex-1 flex items-center justify-center pb-8 overflow-auto relative">
      <div className="shadow-lg mt-8">
        <Stage
          ref={stageRef}
          width={stageSize.width * finalScale}
          height={stageSize.height * finalScale}
          scaleX={finalScale}
          scaleY={finalScale}
          onMouseDown={handleStageMouseDown}
          onMouseMove={handleStageMouseMove}
          onMouseUp={handleStageMouseUp}
        >
          <Layer listening={false}>
            <Rect
              x={0}
              y={0}
              width={stageSize.width}
              height={stageSize.height}
              fill="#ffffff"
              listening={false}
            />
          </Layer>

          <Layer ref={layerRef}>
            {objects.map((obj) => {
              const maskShape = getMaskForObject(obj, objects);
              
              return (
                <ObjectRenderer
                  key={obj.id}
                  obj={obj}
                  isSelected={selectedObjectId === obj.id}
                  transformerRef={transformerRef}
                  layerRef={layerRef}
                  onSelect={handleSelect}
                  onUpdate={updateObject}
                  draggable={tool === "select"}
                  onCellClick={handleCellClick}
                  onCellDblClick={handleCellDblClick}
                  selectedCellId={selectedCellId}
                  maskShape={maskShape}
                />
              );
            })}
            
            {selectedObjectId && (() => {
              const selectedObject = objects.find(obj => obj.id === selectedObjectId);
              const isText = selectedObject?.type === "text";

              return (
                <Transformer
                  ref={transformerRef}
                  boundBoxFunc={(oldBox, newBox) => {
                    if (Math.abs(newBox.width) < 5 || Math.abs(newBox.height) < 5) {
                      return oldBox;
                    }
                    return newBox;
                  }}
                  ignoreStroke={isText}
                  perfectDrawEnabled={false}
                  anchorFill="#3b82f6"
                  anchorStroke="#ffffff"
                  borderStroke="#3b82f6"
                  borderStrokeWidth={2}
                  anchorSize={8}
                  rotateEnabled={true}
                  enabledAnchors={[
                    "top-left",
                    "top-right",
                    "bottom-left",
                    "bottom-right",
                    "top-center",
                    "bottom-center",
                    "middle-left",
                    "middle-right",
                  ]}
                />
              );
            })()}
          </Layer>
        </Stage>
      </div>
      {editingCell && (
        <CellEditor
          x={editingCell.x}
          y={editingCell.y}
          width={editingCell.width}
          height={editingCell.height}
          value={editingCell.value}
          onSave={handleCellEditorSave}
          onCancel={handleCellEditorCancel}
        />
      )}
      <ZoomControls />
    </div>
  );
};

export default EditorCanvas;
