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

const EMPTY_CROP = { left: 0, right: 0, top: 0, bottom: 0 };

export const RefImageNode = ({ image }: { image: RefImage }) => {
  const { setImages, zoom, selectedNodeIds, setSelectedNodeIds, globalDesaturate, setContextMenu, isClickThrough, isAnnotationMode, focusedImageId, valueMirrorIds } = useAppStore();
  const isSelected = selectedNodeIds.includes(image.id);
  const isFocusDimmed = focusedImageId !== null && focusedImageId !== image.id;
  const isValueMirror = valueMirrorIds.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 [valueMirrorSplit, setValueMirrorSplit] = useState(0.5);
  const [isDraggingSplit, setIsDraggingSplit] = useState(false);
  const [faviconFailed, setFaviconFailed] = useState(false);

  const crop = image.crop || EMPTY_CROP;
  const cropL = crop.left || 0, cropR = crop.right || 0, cropT = crop.top || 0, cropB = crop.bottom || 0;
  const fullW = image.width / Math.max(0.01, 1 - cropL - cropR);
  const fullH = image.height / Math.max(0.01, 1 - cropT - cropB);
  const innerLeft = -cropL * fullW;
  const innerTop = -cropT * fullH;

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

  const handlePointerDown = (e: React.PointerEvent) => {
    if (isClickThrough || isAnnotationMode) return;
    if (e.button === 2) { e.stopPropagation(); return; }
    e.stopPropagation();
    if (!isSelected) {
      setImages(prev => {
        let ids = [image.id];
        if (image.groupId) ids = prev.filter(i => i.groupId === image.groupId).map(i => i.id);
        if (e.shiftKey) setSelectedNodeIds(s => Array.from(new Set([...s, ...ids])));
        else setSelectedNodeIds(ids);
        return prev;
      });
    }
    setIsDragging(true);
    e.currentTarget.setPointerCapture(e.pointerId);
  };

  const handlePointerMove = (e: React.PointerEvent) => {
    if (isDraggingSplit) {
      e.stopPropagation();
      const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
      setValueMirrorSplit(Math.max(0.05, Math.min(0.95, (e.clientX - rect.left) / rect.width)));
      return;
    }
    if (isDragging && !activeCropEdge && !activeResizeCorner) {
      e.stopPropagation();
      setImages(prev => {
        const targetIds = new Set([...selectedNodeIds, image.id]);
        const groupIds = new Set<string>();
        prev.forEach(i => { if (targetIds.has(i.id) && i.groupId) groupIds.add(i.groupId); });
        return prev.map(i => (targetIds.has(i.id) || (i.groupId && groupIds.has(i.groupId))) ? { ...i, x: i.x + e.movementX / zoom, y: i.y + e.movementY / zoom } : i);
      });
    }
    if (activeResizeCorner) {
      e.stopPropagation();
      setImages(prev => prev.map(img => {
        if (img.id !== image.id) return img;
        const ratio = img.width / img.height;
        const dx = e.movementX / zoom;
        let nw = img.width, nh = img.height, nx = img.x, ny = img.y;
        if (activeResizeCorner === 'br') { nw = Math.max(20, img.width + dx); nh = nw / ratio; }
        else if (activeResizeCorner === 'bl') { nw = Math.max(20, img.width - dx); nh = nw / ratio; nx = img.x + (img.width - nw); }
        else if (activeResizeCorner === 'tr') { nw = Math.max(20, img.width + dx); nh = nw / ratio; ny = img.y + (img.height - nh); }
        else if (activeResizeCorner === 'tl') { nw = Math.max(20, img.width - dx); nh = nw / ratio; nx = img.x + (img.width - nw); ny = img.y + (img.height - nh); }
        return { ...img, width: nw, height: nh, x: nx, y: ny };
      }));
    }
    if (activeCropEdge) {
      e.stopPropagation();
      setImages(prev => prev.map(img => {
        if (img.id !== image.id) return img;
        const c = img.crop || EMPTY_CROP;
        const l = c.left || 0, r = c.right || 0, t = c.top || 0, b = c.bottom || 0;
        const originalW = img.width / Math.max(0.01, 1 - l - r);
        const originalH = img.height / Math.max(0.01, 1 - t - b);
        const dx = e.movementX / zoom;
        const dy = e.movementY / zoom;
        const next = { left: l, right: r, top: t, bottom: b };
        let nx = img.x, ny = img.y;
        if (activeCropEdge === 'left') next.left = 1 - next.right - Math.max(20, img.width - dx) / originalW;
        else if (activeCropEdge === 'right') next.right = 1 - next.left - Math.max(20, img.width + dx) / originalW;
        else if (activeCropEdge === 'top') next.top = 1 - next.bottom - Math.max(20, img.height - dy) / originalH;
        else if (activeCropEdge === 'bottom') next.bottom = 1 - next.top - Math.max(20, img.height + dy) / originalH;
        next.left = Math.max(0, Math.min(next.left, 0.95 - next.right));
        next.right = Math.max(0, Math.min(next.right, 0.95 - next.left));
        next.top = Math.max(0, Math.min(next.top, 0.95 - next.bottom));
        next.bottom = Math.max(0, Math.min(next.bottom, 0.95 - next.top));
        const finalW = originalW * (1 - next.left - next.right);
        const finalH = originalH * (1 - next.top - next.bottom);
        if (activeCropEdge === 'left') nx = img.x + (img.width - finalW);
        if (activeCropEdge === 'top') ny = img.y + (img.height - finalH);
        return { ...img, x: nx, y: ny, width: finalW, height: finalH, crop: next };
      }));
    }
  };

  const handlePointerUp = (e: React.PointerEvent) => {
    setIsDragging(false); setActiveResizeCorner(null); setActiveCropEdge(null); setIsDraggingSplit(false);
    try { e.currentTarget.releasePointerCapture(e.pointerId); } catch {}
  };
  const handleResizeStart = (e: React.PointerEvent, corner: 'tl'|'tr'|'bl'|'br') => { e.stopPropagation(); setIsDragging(false); setActiveResizeCorner(corner); (e.target as HTMLElement).setPointerCapture(e.pointerId); };
  const handleCropStart = (e: React.PointerEvent, edge: 'left'|'right'|'top'|'bottom') => { e.stopPropagation(); setIsDragging(false); setActiveCropEdge(edge); (e.target as HTMLElement).setPointerCapture(e.pointerId); };

  const flipTransform = `scaleX(${image.isFlippedH ? -1 : 1}) scaleY(${image.isFlippedV ? -1 : 1})`;
  let filter = '';
  if (globalDesaturate || image.isDesaturated) filter = 'grayscale(100%)';
  if (isFocusDimmed) filter += ' opacity(0.15)';

  const sourceDomain = image.sourceUrl ? (() => { try { return new URL(image.sourceUrl).hostname.replace('www.', ''); } catch { return null; } })() : null;
  const mediaStyle: React.CSSProperties = { left: innerLeft, top: innerTop, width: fullW, height: fullH, maxWidth: 'none', maxHeight: 'none', minWidth: 'unset', minHeight: 'unset', transform: flipTransform, transformOrigin: 'center center', objectFit: 'fill' };

  return (
    <div className={`absolute touch-none group ${isSelected ? 'ring-[1.5px] ring-[#0A84FF] shadow-2xl' : 'shadow-lg'} ${!isFocusDimmed ? 'hover:ring-[1px] hover:ring-white/20' : ''}`} style={{ transform: `translate(${image.x}px, ${image.y}px)`, width: image.width, height: image.height, filter, zIndex: isSelected || focusedImageId === image.id ? 10 : 1, pointerEvents: (isClickThrough || isAnnotationMode || isFocusDimmed) ? 'none' : 'auto', transition: isFocusDimmed ? 'filter 0.2s ease' : undefined, overflow: 'visible' }} 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]); }}>
      <div className="absolute inset-0 overflow-hidden">
        {isVideo ? <video src={image.url} autoPlay loop muted playsInline controls className="absolute block pointer-events-none" style={mediaStyle} draggable={false} /> : <img src={image.url} alt="Ref" className="absolute pointer-events-none block" draggable={false} style={{ ...mediaStyle, imageRendering: zoom > 2 ? 'pixelated' : 'auto' }} />}
        {isValueMirror && !isVideo && <>
          <div className="absolute inset-0 pointer-events-none overflow-hidden" style={{ clipPath: `inset(0 0 0 ${valueMirrorSplit * 100}%)` }}><img src={image.url} className="absolute block" draggable={false} style={{ ...mediaStyle, filter: 'grayscale(100%)' }} /></div>
          <div className="absolute top-0 bottom-0 w-[3px] bg-white/70 cursor-col-resize z-20 hover:bg-white" style={{ left: `${valueMirrorSplit * 100}%`, transform: 'translateX(-50%)' }} onPointerDown={(e) => { e.stopPropagation(); setIsDraggingSplit(true); (e.target as HTMLElement).setPointerCapture(e.pointerId); }} onPointerUp={handlePointerUp} />
          <div className="absolute top-1 left-1 text-[9px] text-white/60 bg-black/40 px-1 rounded pointer-events-none">COLOR</div><div className="absolute top-1 right-1 text-[9px] text-white/60 bg-black/40 px-1 rounded pointer-events-none">VALUE</div>
        </>}
      </div>
      {(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 pointer-events-none">{isVideo ? 'VIDEO' : 'GIF'}</div>}
      {sourceDomain && <div className="absolute bottom-1.5 right-1.5 opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none flex items-center gap-1 bg-black/60 backdrop-blur rounded px-1.5 py-0.5">
        {!faviconFailed ? <img src={`https://www.google.com/s2/favicons?domain=${sourceDomain}&sz=16`} onError={() => setFaviconFailed(true)} className="w-3 h-3 rounded-sm bg-white/10" alt="" /> : <span className="w-3 h-3 rounded-sm bg-[#0A84FF] text-white text-[8px] leading-3 text-center font-bold">{sourceDomain[0]?.toUpperCase()}</span>}
        <span className="text-[9px] text-white/80 font-medium">{sourceDomain}</span>
      </div>}
      {isSelected && !isFocusDimmed && <>
        <div className="absolute -top-1.5 -left-1.5 w-3 h-3 bg-[#0A84FF] border-[1.5px] border-white rounded-full cursor-nw-resize hover:scale-125 transition-transform z-30 shadow-md" onPointerDown={e => handleResizeStart(e, 'tl')} onPointerUp={handlePointerUp} />
        <div className="absolute -top-1.5 -right-1.5 w-3 h-3 bg-[#0A84FF] border-[1.5px] border-white rounded-full cursor-ne-resize hover:scale-125 transition-transform z-30 shadow-md" onPointerDown={e => handleResizeStart(e, 'tr')} onPointerUp={handlePointerUp} />
        <div className="absolute -bottom-1.5 -left-1.5 w-3 h-3 bg-[#0A84FF] border-[1.5px] border-white rounded-full cursor-sw-resize hover:scale-125 transition-transform z-30 shadow-md" onPointerDown={e => handleResizeStart(e, 'bl')} onPointerUp={handlePointerUp} />
        <div className="absolute -bottom-1.5 -right-1.5 w-3 h-3 bg-[#0A84FF] border-[1.5px] border-white rounded-full cursor-se-resize hover:scale-125 transition-transform z-30 shadow-md" onPointerDown={e => handleResizeStart(e, 'br')} onPointerUp={handlePointerUp} />
        <div className="absolute top-1/2 -translate-y-1/2 -left-1.5 w-3 h-8 cursor-col-resize z-20" 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-8 cursor-col-resize z-20" 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-8 cursor-row-resize z-20" 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-8 cursor-row-resize z-20" 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>
  );
};
