import React, { useState } from 'react';
import { useAppStore } from '../store';
import { RefImage } from '../types';

export const RefImageNode = ({ image }: { image: RefImage }) => {
  const { setImages, zoom, selectedNodeIds, setSelectedNodeIds, globalDesaturate, setContextMenu, isClickThrough, isAnnotationMode } = useAppStore();
  const isSelected = selectedNodeIds.includes(image.id);
  const [isDragging, setIsDragging] = useState(false);
  const [activeResizeCorner, setActiveResizeCorner] = useState<'tl' | 'tr' | 'bl' | 'br' | null>(null);
  const [activeCropEdge, setActiveCropEdge] = useState<'left' | 'right' | 'top' | 'bottom' | null>(null);

  const handlePointerDown = (e: React.PointerEvent) => {
    if (isClickThrough || isAnnotationMode) return; // Allow event to bubble to canvas for drawing
    
    if (e.button === 2) {
      e.stopPropagation();
      return;
    }
    
    e.stopPropagation();
    if (!isSelected) {
        setImages(prevImages => {
            let idsToSelect = [image.id];
            if (image.groupId) {
                idsToSelect = prevImages.filter(img => img.groupId === image.groupId).map(img => img.id);
            }
            if (e.shiftKey) {
                setSelectedNodeIds(prev => Array.from(new Set([...prev, ...idsToSelect])));
            } else {
                setSelectedNodeIds(idsToSelect);
            }
            return prevImages;
        });
    }
    setIsDragging(true);
    e.currentTarget.setPointerCapture(e.pointerId);
  };

  const handlePointerMove = (e: React.PointerEvent) => {
    if (isDragging && !activeCropEdge) {
      e.stopPropagation();
      setImages(prev => {
        // Collect all explicit targets
        const explicitTargetIds = new Set([...selectedNodeIds, image.id]);
        
        // Find any group IDs associated with the targets
        const affectedGroupIds = new Set<string>();
        prev.forEach(img => {
            if (explicitTargetIds.has(img.id) && img.groupId) {
                affectedGroupIds.add(img.groupId);
            }
        });

        return prev.map(img => {
          if (explicitTargetIds.has(img.id) || (img.groupId && affectedGroupIds.has(img.groupId))) {
            return { ...img, x: img.x + e.movementX / zoom, y: img.y + e.movementY / zoom };
          }
          return img;
        });
      });
    }
    if (activeResizeCorner) {
       e.stopPropagation();
       setImages(prev => prev.map(img => {
           if (img.id === image.id) {
               const currentRatio = img.width / img.height;
               let dx = e.movementX / zoom;
               
               let newWidth = img.width;
               let newHeight = img.height;
               let newX = img.x;
               let newY = img.y;

               if (activeResizeCorner === 'br') {
                   newWidth = Math.max(20, img.width + dx);
                   newHeight = newWidth / currentRatio;
               } else if (activeResizeCorner === 'bl') {
                   newWidth = Math.max(20, img.width - dx);
                   newHeight = newWidth / currentRatio;
                   newX = img.x + (img.width - newWidth);
               } else if (activeResizeCorner === 'tr') {
                   newWidth = Math.max(20, img.width + dx);
                   newHeight = newWidth / currentRatio;
                   newY = img.y + (img.height - newHeight);
               } else if (activeResizeCorner === 'tl') {
                   newWidth = Math.max(20, img.width - dx);
                   newHeight = newWidth / currentRatio;
                   newX = img.x + (img.width - newWidth);
                   newY = img.y + (img.height - newHeight);
               }

               return { ...img, width: newWidth, height: newHeight, x: newX, y: newY };
           }
           return img;
       }));
    }
    if (activeCropEdge) {
       e.stopPropagation();
       setImages(prev => prev.map(img => {
           if (img.id === image.id) {
               const crop = img.crop || { left: 0, right: 0, top: 0, bottom: 0 };
               const fullW = img.width / (1 - crop.left - crop.right);
               const fullH = img.height / (1 - crop.top - crop.bottom);
               
               let newX = img.x;
               let newY = img.y;
               let newCrop = { ...crop };

               const dx = e.movementX / zoom;
               const dy = e.movementY / zoom;

               if (activeCropEdge === 'right') {
                   const newWidth = Math.max(10, img.width + dx);
                   newCrop.right = 1 - newCrop.left - (newWidth / fullW);
               } else if (activeCropEdge === 'left') {
                   const newWidth = Math.max(10, img.width - dx);
                   const appliedDx = img.width - newWidth;
                   newX = img.x + appliedDx;
                   newCrop.left = 1 - newCrop.right - (newWidth / fullW);
               } else if (activeCropEdge === 'bottom') {
                   const newHeight = Math.max(10, img.height + dy);
                   newCrop.bottom = 1 - newCrop.top - (newHeight / fullH);
               } else if (activeCropEdge === 'top') {
                   const newHeight = Math.max(10, img.height - dy);
                   const appliedDy = img.height - newHeight;
                   newY = img.y + appliedDy;
                   newCrop.top = 1 - newCrop.bottom - (newHeight / fullH);
               }
               
               // constrain bounds
               newCrop.left = Math.max(0, Math.min(newCrop.left, 1 - newCrop.right - 0.01));
               newCrop.right = Math.max(0, Math.min(newCrop.right, 1 - newCrop.left - 0.01));
               newCrop.top = Math.max(0, Math.min(newCrop.top, 1 - newCrop.bottom - 0.01));
               newCrop.bottom = Math.max(0, Math.min(newCrop.bottom, 1 - newCrop.top - 0.01));

               // recalculate width/height based on constrained crop
               const finalWidth = fullW * (1 - newCrop.left - newCrop.right);
               const finalHeight = fullH * (1 - newCrop.top - newCrop.bottom);

               // recalculate x, y for constrained top/left
               if (activeCropEdge === 'left') {
                   const actualDx = img.width - finalWidth;
                   newX = img.x + actualDx;
               } else if (activeCropEdge === 'top') {
                   const actualDy = img.height - finalHeight;
                   newY = img.y + actualDy;
               }

               return { ...img, width: finalWidth, height: finalHeight, x: newX, y: newY, crop: newCrop };
           }
           return img;
       }));
    }
  };

  const handlePointerUp = (e: React.PointerEvent) => {
    setIsDragging(false);
    setActiveResizeCorner(null);
    setActiveCropEdge(null);
    e.currentTarget.releasePointerCapture(e.pointerId);
  };

  const handleResizeStart = (e: React.PointerEvent, corner: 'tl' | 'tr' | 'bl' | 'br') => {
      e.stopPropagation();
      setActiveResizeCorner(corner);
      (e.target as HTMLElement).setPointerCapture(e.pointerId);
  };

  const handleCropStart = (e: React.PointerEvent, edge: 'left' | 'right' | 'top' | 'bottom') => {
      e.stopPropagation();
      setActiveCropEdge(edge);
      (e.target as HTMLElement).setPointerCapture(e.pointerId);
  };

  const isGif = image.url.toLowerCase().includes('.gif') || image.url.startsWith('data:image/gif');
  const isVideo = image.url.toLowerCase().match(/\.(mp4|webm|mov)$/) || image.url.startsWith('data:video/');

  return (
    <div
      className={`absolute ${isSelected ? 'ring-[1.5px] ring-accent-blue shadow-2xl' : 'shadow-lg'} touch-none group hover:ring-[1px] hover:ring-white/20`}
      style={{
        transform: `translate(${image.x}px, ${image.y}px)`,
        width: image.width,
        height: image.height,
        filter: globalDesaturate || image.isDesaturated ? 'grayscale(100%)' : 'none',
        zIndex: isSelected ? 10 : 1,
        pointerEvents: isClickThrough || isAnnotationMode ? 'none' : 'auto'
      }}
      onPointerDown={handlePointerDown}
      onPointerMove={handlePointerMove}
      onPointerUp={handlePointerUp}
      onContextMenu={e => {
        e.preventDefault();
        e.stopPropagation();
        setContextMenu({ x: e.clientX, y: e.clientY, imageId: image.id });
        if (!isSelected) setSelectedNodeIds([image.id]);
      }}
    >
      {isVideo ? (
         <video
            src={image.url}
            autoPlay
            loop
            muted
            playsInline
            controls
            className={`w-full h-full block ${isGif || isVideo ? 'opacity-100 object-fill' : 'opacity-0 object-contain'}`}
            style={{
                transform: `scaleX(${image.isFlippedH ? -1 : 1}) scaleY(${image.isFlippedV ? -1 : 1})`,
                clipPath: isVideo && image.crop ? `inset(${image.crop.top * 100}% ${image.crop.right * 100}% ${image.crop.bottom * 100}% ${image.crop.left * 100}%)` : 'none'
            }}
         />
      ) : (
         <img 
            src={image.url} 
            alt="Ref" 
            className={`w-full h-full pointer-events-none block ${isGif || isVideo ? 'opacity-100 object-fill' : 'opacity-0 object-contain'}`}
            draggable={false} 
            style={{
                transform: `scaleX(${image.isFlippedH ? -1 : 1}) scaleY(${image.isFlippedV ? -1 : 1})`,
                imageRendering: zoom > 2 ? 'pixelated' : 'auto',
                clipPath: isGif && image.crop ? `inset(${image.crop.top * 100}% ${image.crop.right * 100}% ${image.crop.bottom * 100}% ${image.crop.left * 100}%)` : 'none'
            }}
         />
      )}
      {(isGif || isVideo) && (
          <div className="absolute top-2 right-2 bg-black/60 backdrop-blur rounded px-1.5 py-0.5 text-[10px] text-white font-medium opacity-0 group-hover:opacity-100 transition-opacity">
              {isVideo ? 'VIDEO' : 'GIF'}
          </div>
      )}
      {isSelected && (
        <>
            {/* Resize corners */}
            <div 
               className="absolute -top-1.5 -left-1.5 w-3 h-3 bg-accent-blue border-[1.5px] border-white rounded-full cursor-nw-resize hover:scale-125 transition-transform z-20 shadow-md" 
               onPointerDown={(e) => handleResizeStart(e, 'tl')} onPointerUp={handlePointerUp} 
            />
            <div 
               className="absolute -top-1.5 -right-1.5 w-3 h-3 bg-accent-blue border-[1.5px] border-white rounded-full cursor-ne-resize hover:scale-125 transition-transform z-20 shadow-md" 
               onPointerDown={(e) => handleResizeStart(e, 'tr')} onPointerUp={handlePointerUp} 
            />
            <div 
               className="absolute -bottom-1.5 -left-1.5 w-3 h-3 bg-accent-blue border-[1.5px] border-white rounded-full cursor-sw-resize hover:scale-125 transition-transform z-20 shadow-md" 
               onPointerDown={(e) => handleResizeStart(e, 'bl')} onPointerUp={handlePointerUp} 
            />
            <div 
               className="absolute -bottom-1.5 -right-1.5 w-3 h-3 bg-accent-blue border-[1.5px] border-white rounded-full cursor-se-resize hover:scale-125 transition-transform z-20 shadow-md" 
               onPointerDown={(e) => handleResizeStart(e, 'br')} onPointerUp={handlePointerUp} 
            />
            {/* Crop edges */}
            <div className="absolute top-1/2 -translate-y-1/2 -left-1.5 w-3 h-6 cursor-col-resize z-10" onPointerDown={(e) => handleCropStart(e, 'left')} onPointerUp={handlePointerUp}>
                <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-1 h-6 bg-white border border-black/20 rounded-full opacity-0 group-hover:opacity-100 transition-opacity" />
            </div>
            <div className="absolute top-1/2 -translate-y-1/2 -right-1.5 w-3 h-6 cursor-col-resize z-10" onPointerDown={(e) => handleCropStart(e, 'right')} onPointerUp={handlePointerUp}>
                <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-1 h-6 bg-white border border-black/20 rounded-full opacity-0 group-hover:opacity-100 transition-opacity" />
            </div>
            <div className="absolute left-1/2 -translate-x-1/2 -top-1.5 h-3 w-6 cursor-row-resize z-10" onPointerDown={(e) => handleCropStart(e, 'top')} onPointerUp={handlePointerUp}>
                <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-6 h-1 bg-white border border-black/20 rounded-full opacity-0 group-hover:opacity-100 transition-opacity" />
            </div>
            <div className="absolute left-1/2 -translate-x-1/2 -bottom-1.5 h-3 w-6 cursor-row-resize z-10" onPointerDown={(e) => handleCropStart(e, 'bottom')} onPointerUp={handlePointerUp}>
                <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-6 h-1 bg-white border border-black/20 rounded-full opacity-0 group-hover:opacity-100 transition-opacity" />
            </div>
        </>
      )}
    </div>
  );
};
