import React, { useState, useEffect, useRef } from 'react';
import { Handle, Position, useUpdateNodeInternals, useReactFlow } from '@xyflow/react';
import { Image as ImageIcon, Loader2 } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import axios from 'axios';

const ImageNode = ({ id, data, selected, width, height }) => {
  const { t } = useTranslation();
  const updateNodeInternals = useUpdateNodeInternals();
  const { getZoom, getNode, setNodes } = useReactFlow();
  const [imageUrl, setImageUrl] = useState(data.url || '');
  const [loading, setLoading] = useState(false);
  const [isShiftPressed, setIsShiftPressed] = useState(false);
  const [isResizing, setIsResizing] = useState(false);
  const imageRatioRef = useRef(1);

  // Load large data from backend on mount if not loaded
  useEffect(() => {
    if (!imageUrl && data.hasLargeData) {
      setLoading(true);
      const API_URL = import.meta.env.VITE_API_URL;
      axios.get(`${API_URL}/TaskNodes/${id}/data`)
        .then(res => {
          if (res.data && res.data.data) {
            setImageUrl(res.data.data);
            if (data.updateNodeData) {
              data.updateNodeData(id, { url: res.data.data, isLoadedFromBackend: true });
            }
          }
        })
        .catch(err => console.error('[ImageNode] Error loading large data:', err))
        .finally(() => setLoading(false));
    }
  }, [id, imageUrl, data.hasLargeData]);

  // Sync if data changes from remote
  useEffect(() => {
    if (data.url && data.url !== imageUrl) {
      setImageUrl(data.url);
    }
  }, [data.url]);

  // Re-calculate handles when data dimensions update
  useEffect(() => {
    updateNodeInternals(id);
  }, [id, data.width, data.height, updateNodeInternals]);

  // Sync aspect ratio ref if size is changed
  useEffect(() => {
    if (data.width && data.height && data.height !== 'auto') {
      imageRatioRef.current = data.width / data.height;
    }
  }, [data.width, data.height]);

  // Listen to Shift key events globally to toggle aspect ratio constraint
  useEffect(() => {
    const handleKeyDown = (e) => {
      if (e.key === 'Shift') {
        setIsShiftPressed(true);
      }
    };
    const handleKeyUp = (e) => {
      if (e.key === 'Shift') {
        setIsShiftPressed(false);
      }
    };
    const handleBlur = () => {
      setIsShiftPressed(false);
    };

    window.addEventListener('keydown', handleKeyDown);
    window.addEventListener('keyup', handleKeyUp);
    window.addEventListener('blur', handleBlur);
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
      window.removeEventListener('keyup', handleKeyUp);
      window.removeEventListener('blur', handleBlur);
    };
  }, []);

  const handleImageLoad = (e) => {
    const { naturalWidth, naturalHeight } = e.target;
    if (naturalWidth && naturalHeight) {
      const ratio = naturalWidth / naturalHeight;
      imageRatioRef.current = ratio;
      // Only set initial size if data.height is 'auto' or not set in pixels
      if (!data.height || data.height === 'auto') {
        const initialWidth = data.width || 300;
        const calculatedHeight = Math.round(initialWidth / ratio);
        
        if (data.updateNodeData) {
          data.updateNodeData(id, { width: initialWidth, height: calculatedHeight });
        }
      }
    }
  };

  const handleResizeStart = (e, direction) => {
    e.stopPropagation();
    e.preventDefault();

    const node = getNode(id);
    if (!node) return;

    setIsResizing(true);

    const startX = e.clientX;
    const startY = e.clientY;
    const startPos = { ...node.position };
    const startSize = {
      width: node.width || node.style?.width || data.width || 300,
      height: node.height || node.style?.height || data.height || 200
    };

    const ratio = imageRatioRef.current || (startSize.width / startSize.height) || 1;
    const zoom = getZoom();

    let finalWidth = startSize.width;
    let finalHeight = startSize.height;
    let finalX = startPos.x;
    let finalY = startPos.y;

    const nodeElement = document.querySelector(`.react-flow__node[data-id="${id}"]`);

    const handlePointerMove = (moveEvent) => {
      const dx = (moveEvent.clientX - startX) / zoom;
      const dy = (moveEvent.clientY - startY) / zoom;

      const shiftPressed = moveEvent.shiftKey || isShiftPressed;
      const isCorner = ['top-left', 'top-right', 'bottom-left', 'bottom-right'].includes(direction);
      const shouldLockRatio = isCorner || shiftPressed;

      if (shouldLockRatio) {
        // --- PROPORTIONAL RESIZING ---
        if (direction === 'right') {
          finalWidth = Math.max(50, startSize.width + dx);
          finalHeight = Math.round(finalWidth / ratio);
          finalY = startPos.y;
        } else if (direction === 'left') {
          finalWidth = Math.max(50, startSize.width - dx);
          finalHeight = Math.round(finalWidth / ratio);
          finalX = startPos.x + (startSize.width - finalWidth);
          finalY = startPos.y;
        } else if (direction === 'bottom') {
          finalHeight = Math.max(50, startSize.height + dy);
          finalWidth = Math.round(finalHeight * ratio);
          finalX = startPos.x;
        } else if (direction === 'top') {
          finalHeight = Math.max(50, startSize.height - dy);
          finalWidth = Math.round(finalHeight * ratio);
          finalY = startPos.y + (startSize.height - finalHeight);
          finalX = startPos.x;
        } else if (direction === 'bottom-right') {
          if (Math.abs(dx) > Math.abs(dy)) {
            finalWidth = Math.max(50, startSize.width + dx);
            finalHeight = Math.round(finalWidth / ratio);
          } else {
            finalHeight = Math.max(50, startSize.height + dy);
            finalWidth = Math.round(finalHeight * ratio);
          }
          finalX = startPos.x;
          finalY = startPos.y;
        } else if (direction === 'bottom-left') {
          if (Math.abs(dx) > Math.abs(dy)) {
            finalWidth = Math.max(50, startSize.width - dx);
            finalHeight = Math.round(finalWidth / ratio);
          } else {
            finalHeight = Math.max(50, startSize.height + dy);
            finalWidth = Math.round(finalHeight * ratio);
          }
          finalX = startPos.x + (startSize.width - finalWidth);
          finalY = startPos.y;
        } else if (direction === 'top-right') {
          if (Math.abs(dx) > Math.abs(dy)) {
            finalWidth = Math.max(50, startSize.width + dx);
            finalHeight = Math.round(finalWidth / ratio);
          } else {
            finalHeight = Math.max(50, startSize.height - dy);
            finalWidth = Math.round(finalHeight * ratio);
          }
          finalX = startPos.x;
          finalY = startPos.y + (startSize.height - finalHeight);
        } else if (direction === 'top-left') {
          if (Math.abs(dx) > Math.abs(dy)) {
            finalWidth = Math.max(50, startSize.width - dx);
            finalHeight = Math.round(finalWidth / ratio);
          } else {
            finalHeight = Math.max(50, startSize.height - dy);
            finalWidth = Math.round(finalHeight * ratio);
          }
          finalX = startPos.x + (startSize.width - finalWidth);
          finalY = startPos.y + (startSize.height - finalHeight);
        }
      } else {
        // --- DISTORTION RESIZING ---
        if (direction === 'right') {
          finalWidth = Math.max(50, startSize.width + dx);
        } else if (direction === 'left') {
          finalWidth = Math.max(50, startSize.width - dx);
          finalX = startPos.x + (startSize.width - finalWidth);
        } else if (direction === 'bottom') {
          finalHeight = Math.max(50, startSize.height + dy);
        } else if (direction === 'top') {
          finalHeight = Math.max(50, startSize.height - dy);
          finalY = startPos.y + (startSize.height - finalHeight);
        } else if (direction === 'bottom-right') {
          finalWidth = Math.max(50, startSize.width + dx);
          finalHeight = Math.max(50, startSize.height + dy);
        } else if (direction === 'bottom-left') {
          finalWidth = Math.max(50, startSize.width - dx);
          finalHeight = Math.max(50, startSize.height + dy);
          finalX = startPos.x + (startSize.width - finalWidth);
        } else if (direction === 'top-right') {
          finalWidth = Math.max(50, startSize.width + dx);
          finalHeight = Math.max(50, startSize.height - dy);
          finalY = startPos.y + (startSize.height - finalHeight);
        } else if (direction === 'top-left') {
          finalWidth = Math.max(50, startSize.width - dx);
          finalHeight = Math.max(50, startSize.height - dy);
          finalX = startPos.x + (startSize.width - finalWidth);
          finalY = startPos.y + (startSize.height - finalHeight);
        }
      }

      // Direct DOM update for 60fps buttery smooth dragging
      if (nodeElement) {
        nodeElement.style.width = `${finalWidth}px`;
        nodeElement.style.height = `${finalHeight}px`;
        nodeElement.style.transform = `translate(${finalX}px, ${finalY}px)`;
      }
    };

    const handlePointerUp = () => {
      window.removeEventListener('pointermove', handlePointerMove);
      window.removeEventListener('pointerup', handlePointerUp);

      // React state update on drop to sync react-flow store
      setNodes((nds) =>
        nds.map((n) => {
          if (n.id === id) {
            return {
              ...n,
              position: { x: finalX, y: finalY },
              width: finalWidth,
              height: finalHeight,
              style: { ...n.style, width: finalWidth, height: finalHeight }
            };
          }
          return n;
        })
      );

      // Save new dimensions and position to database, history and broadcast
      if (data.updateNodeData) {
        data.updateNodeData(id, { 
          width: finalWidth, 
          height: finalHeight,
          x: finalX,
          y: finalY
        });
      }

      setIsResizing(false);
    };

    window.addEventListener('pointermove', handlePointerMove);
    window.addEventListener('pointerup', handlePointerUp);
  };

  const isCustomSized = width !== undefined || isResizing;
  const styleWidth = isCustomSized ? '100%' : (data.width || 300);
  const styleHeight = isCustomSized ? '100%' : (data.height || 'auto');

  // Common handle style & class (Removed transition-all to prevent lag on resize animation)
  const handleClass = "absolute w-3.5 h-3.5 bg-surface-container-lowest border-2 border-primary rounded-md shadow-[2px_2px_0px_0px_var(--color-primary)] z-50 hover:scale-110 active:scale-95 transition-transform select-none";

  return (
    <div 
      className={`relative group ${
        selected ? 'ring-2 ring-primary/40 shadow-xl' : ''
      }`}
      style={{
        width: styleWidth,
        height: styleHeight,
        minWidth: 50,
        minHeight: 50,
      }}
    >
      {selected && (
        <>
          {/* Custom Dashed Outline */}
          <div className="absolute inset-0 border-2 border-dashed border-primary opacity-60 rounded-lg pointer-events-none z-10" />
          
          {/* Corners (Always Proportional) */}
          <div 
            style={{ top: '-7px', left: '-7px' }}
            className={`${handleClass} cursor-nwse-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'top-left')}
          />
          <div 
            style={{ top: '-7px', right: '-7px' }}
            className={`${handleClass} cursor-nesw-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'top-right')}
          />
          <div 
            style={{ bottom: '-7px', left: '-7px' }}
            className={`${handleClass} cursor-nesw-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'bottom-left')}
          />
          <div 
            style={{ bottom: '-7px', right: '-7px' }}
            className={`${handleClass} cursor-nwse-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'bottom-right')}
          />

          {/* Sides (Proportional only if Shift is held) */}
          <div 
            style={{ top: '-7px', left: '50%', marginLeft: '-7px' }}
            className={`${handleClass} cursor-ns-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'top')}
          />
          <div 
            style={{ bottom: '-7px', left: '50%', marginLeft: '-7px' }}
            className={`${handleClass} cursor-ns-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'bottom')}
          />
          <div 
            style={{ left: '-7px', top: '50%', marginTop: '-7px' }}
            className={`${handleClass} cursor-ew-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'left')}
          />
          <div 
            style={{ right: '-7px', top: '50%', marginTop: '-7px' }}
            className={`${handleClass} cursor-ew-resize`}
            onPointerDown={(e) => handleResizeStart(e, 'right')}
          />
        </>
      )}

      {loading ? (
        <div className="w-full h-full min-h-[100px] bg-secondary/5 flex flex-col items-center justify-center gap-2 p-4 text-center border-2 border-dashed border-primary/10">
          <Loader2 size={24} className="text-primary animate-spin" />
          <p className="text-[10px] font-bold text-primary/40 uppercase tracking-widest">
            {t('canvas.image_loading', 'Завантаження...')}
          </p>
        </div>
      ) : imageUrl ? (
        <img 
          src={imageUrl} 
          alt="Canvas Asset" 
          onLoad={handleImageLoad}
          className="w-full h-full object-fill pointer-events-none select-none rounded-lg"
        />
      ) : (
        <div className="w-full h-full min-h-[100px] bg-secondary/5 flex flex-col items-center justify-center gap-2 p-4 text-center border-2 border-dashed border-primary/10">
          <ImageIcon size={24} className="text-primary/20" />
          <p className="text-[10px] font-bold text-primary/40 uppercase tracking-widest">
            {t('canvas.image_drop_hint', 'Drop image here')}
          </p>
        </div>
      )}

      {/* Connection points - barely visible */}
      <Handle type="target" position={Position.Top} className="!opacity-0 group-hover:!opacity-30" />
      <Handle type="source" position={Position.Bottom} className="!opacity-0 group-hover:!opacity-30" />
    </div>
  );
};

export default ImageNode;
