import { useState, useCallback, useRef, useEffect } from 'react';
import { X, ZoomIn, ZoomOut } from 'lucide-react';
import { Button } from '@/shared/components/ui';

interface ImageCropModalProps {
  image: string;
  onComplete: (croppedImage: string) => void;
  onCancel: () => void;
  loading?: boolean;
}

interface CropData {
  x: number;
  y: number;
  scale: number;
}

export function ImageCropModal({
  image,
  onComplete,
  onCancel,
  loading = false
}: ImageCropModalProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const imageRef = useRef<HTMLImageElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);

  const [cropData, setCropData] = useState<CropData>({ x: 0, y: 0, scale: 0.5 });
  const [isDragging, setIsDragging] = useState(false);
  const [lastTouchDistance, setLastTouchDistance] = useState<number | null>(null);
  const [imageLoaded, setImageLoaded] = useState(false);
  const [dragStart, setDragStart] = useState({ x: 0, y: 0 });

  // Load and center image when component mounts
  useEffect(() => {
    const img = new Image();
    img.onload = () => {
      setImageLoaded(true);
      if (containerRef.current) {
        const containerRect = containerRef.current.getBoundingClientRect();
        const containerWidth = containerRect.width;
        const containerHeight = containerRect.height;

        const scaleToFit = Math.min(containerWidth / img.naturalWidth, containerHeight / img.naturalHeight);
        const initialScale = Math.max(0.3, scaleToFit);

        const cropCenterX = containerWidth / 2;
        const cropCenterY = containerHeight / 2;
        const scaledImageWidth = img.naturalWidth * initialScale;
        const scaledImageHeight = img.naturalHeight * initialScale;

        const centerX = cropCenterX - scaledImageWidth / 2;
        const centerY = cropCenterY - scaledImageHeight / 2;

        setCropData({ x: centerX, y: centerY, scale: initialScale });
      }
    };
    img.src = image;

    if (imageRef.current) {
      imageRef.current.src = image;
    }
  }, [image]);

  // Update canvas preview whenever crop data changes
  useEffect(() => {
    if (imageLoaded && imageRef.current) {
      updatePreview();
    }
  }, [cropData, imageLoaded]);

  const updatePreview = () => {
    const canvas = canvasRef.current;
    const img = imageRef.current;
    const container = containerRef.current;

    if (!canvas || !img || !container) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const size = 160;
    canvas.width = size;
    canvas.height = size;

    ctx.clearRect(0, 0, size, size);

    const containerRect = container.getBoundingClientRect();
    const containerWidth = containerRect.width;
    const containerHeight = containerRect.height;
    const cropRadius = 80;
    const cropCenterX = containerWidth / 2;
    const cropCenterY = containerHeight / 2;

    const imageCenterX = cropData.x + (img.naturalWidth * cropData.scale) / 2;
    const imageCenterY = cropData.y + (img.naturalHeight * cropData.scale) / 2;

    const offsetX = (cropCenterX - imageCenterX) / cropData.scale;
    const offsetY = (cropCenterY - imageCenterY) / cropData.scale;

    const sourceX = (img.naturalWidth / 2) + offsetX - (cropRadius / cropData.scale);
    const sourceY = (img.naturalHeight / 2) + offsetY - (cropRadius / cropData.scale);
    const sourceSize = (cropRadius * 2) / cropData.scale;

    ctx.save();
    ctx.beginPath();
    ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
    ctx.clip();

    ctx.drawImage(img, sourceX, sourceY, sourceSize, sourceSize, 0, 0, size, size);
    ctx.restore();

    ctx.strokeStyle = '#3b82f6';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.arc(size / 2, size / 2, size / 2 - 1, 0, Math.PI * 2);
    ctx.stroke();
  };

  const handleStart = useCallback((clientX: number, clientY: number) => {
    if (!containerRef.current) return;

    const containerRect = containerRef.current.getBoundingClientRect();
    const relativeX = clientX - containerRect.left;
    const relativeY = clientY - containerRect.top;

    setIsDragging(true);
    setDragStart({ x: relativeX - cropData.x, y: relativeY - cropData.y });
  }, [cropData.x, cropData.y]);

  const handleMove = useCallback((clientX: number, clientY: number) => {
    if (!isDragging || !containerRef.current) return;

    const containerRect = containerRef.current.getBoundingClientRect();
    const relativeX = clientX - containerRect.left;
    const relativeY = clientY - containerRect.top;

    setCropData(prev => ({
      ...prev,
      x: relativeX - dragStart.x,
      y: relativeY - dragStart.y
    }));
  }, [isDragging, dragStart]);

  const handleEnd = useCallback(() => {
    setIsDragging(false);
    setLastTouchDistance(null);
  }, []);

  const handleMouseDown = (e: React.MouseEvent) => handleStart(e.clientX, e.clientY);
  const handleMouseMove = (e: React.MouseEvent) => handleMove(e.clientX, e.clientY);
  const handleMouseUp = () => handleEnd();

  const getTouchDistance = (touch1: React.Touch, touch2: React.Touch) => {
    const dx = touch1.clientX - touch2.clientX;
    const dy = touch1.clientY - touch2.clientY;
    return Math.sqrt(dx * dx + dy * dy);
  };

  const handleTouchStart = (e: React.TouchEvent) => {
    if (e.touches.length === 1) {
      handleStart(e.touches[0].clientX, e.touches[0].clientY);
    } else if (e.touches.length === 2) {
      setLastTouchDistance(getTouchDistance(e.touches[0], e.touches[1]));
      setIsDragging(false);
    }
  };

  const handleTouchMove = (e: React.TouchEvent) => {
    if (e.touches.length === 1 && isDragging) {
      handleMove(e.touches[0].clientX, e.touches[0].clientY);
    } else if (e.touches.length === 2) {
      const distance = getTouchDistance(e.touches[0], e.touches[1]);
      if (lastTouchDistance) {
        const scale = Math.max(0.1, Math.min(3, cropData.scale * (distance / lastTouchDistance)));
        setCropData(prev => ({ ...prev, scale }));
      }
      setLastTouchDistance(distance);
    }
  };

  const handleZoomIn = () => setCropData(prev => ({ ...prev, scale: Math.min(3, prev.scale * 1.2) }));
  const handleZoomOut = () => setCropData(prev => ({ ...prev, scale: Math.max(0.1, prev.scale / 1.2) }));

  const handleCrop = () => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const img = imageRef.current;
    const container = containerRef.current;

    if (!ctx || !img || !container) return;

    const outputSize = 300;
    canvas.width = outputSize;
    canvas.height = outputSize;

    const containerRect = container.getBoundingClientRect();
    const containerWidth = containerRect.width;
    const containerHeight = containerRect.height;
    const cropRadius = 80;
    const cropCenterX = containerWidth / 2;
    const cropCenterY = containerHeight / 2;

    const imageCenterX = cropData.x + (img.naturalWidth * cropData.scale) / 2;
    const imageCenterY = cropData.y + (img.naturalHeight * cropData.scale) / 2;

    const offsetX = (cropCenterX - imageCenterX) / cropData.scale;
    const offsetY = (cropCenterY - imageCenterY) / cropData.scale;

    const sourceX = (img.naturalWidth / 2) + offsetX - (cropRadius / cropData.scale);
    const sourceY = (img.naturalHeight / 2) + offsetY - (cropRadius / cropData.scale);
    const sourceSize = (cropRadius * 2) / cropData.scale;

    ctx.save();
    ctx.beginPath();
    ctx.arc(outputSize / 2, outputSize / 2, outputSize / 2, 0, Math.PI * 2);
    ctx.clip();

    ctx.drawImage(img, sourceX, sourceY, sourceSize, sourceSize, 0, 0, outputSize, outputSize);
    ctx.restore();

    const croppedImage = canvas.toDataURL('image/jpeg', 0.9);
    onComplete(croppedImage);
  };

  return (
    <div className="fixed inset-0 z-[60] flex items-center justify-center p-4">
      <div className="absolute inset-0 bg-black/80" onClick={onCancel} />

      <div className="relative bg-bg-primary border border-border rounded-xl w-full max-w-sm shadow-xl">
        <div className="flex items-center justify-between p-4 border-b border-border">
          <h3 className="text-lg font-semibold text-text-primary">Bild zuschneiden</h3>
          <Button variant="ghost" size="icon" onClick={onCancel}>
            <X className="h-5 w-5" />
          </Button>
        </div>

        <div className="p-4 space-y-4">
          {/* Preview */}
          <div className="flex justify-center">
            <div className="text-center">
              <p className="text-xs text-text-secondary mb-2">Vorschau</p>
              <canvas
                ref={canvasRef}
                className="rounded-full border-2 border-primary-500"
                width={160}
                height={160}
              />
            </div>
          </div>

          {/* Touchpad area */}
          <div>
            <p className="text-xs text-text-secondary mb-2 text-center">
              Ziehen zum Bewegen, Pinch zum Zoomen
            </p>
            <div
              ref={containerRef}
              className="relative w-full h-32 rounded-lg overflow-hidden cursor-move select-none bg-bg-tertiary"
              style={{ touchAction: 'manipulation' }}
              onMouseDown={handleMouseDown}
              onMouseMove={handleMouseMove}
              onMouseUp={handleMouseUp}
              onMouseLeave={handleMouseUp}
              onTouchStart={handleTouchStart}
              onTouchMove={handleTouchMove}
              onTouchEnd={handleEnd}
            >
              {imageLoaded && (
                <img
                  ref={imageRef}
                  src={image}
                  alt="Crop"
                  className="absolute pointer-events-none opacity-0"
                  style={{
                    transform: `translate(${cropData.x}px, ${cropData.y}px) scale(${cropData.scale * 2})`,
                    transformOrigin: '0 0',
                  }}
                  draggable={false}
                />
              )}

              <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
                <div className="w-40 h-40 rounded-full border-2 border-dashed border-primary-500/50" />
              </div>
            </div>

            {/* Zoom controls */}
            <div className="flex justify-center items-center gap-3 mt-3">
              <Button variant="outline" size="icon" onClick={handleZoomOut} disabled={loading}>
                <ZoomOut className="h-4 w-4" />
              </Button>
              <span className="text-sm text-text-secondary w-12 text-center">
                {Math.round(cropData.scale * 100)}%
              </span>
              <Button variant="outline" size="icon" onClick={handleZoomIn} disabled={loading}>
                <ZoomIn className="h-4 w-4" />
              </Button>
            </div>
          </div>
        </div>

        <div className="flex gap-3 p-4 border-t border-border">
          <Button variant="outline" onClick={onCancel} disabled={loading} className="flex-1">
            Abbrechen
          </Button>
          <Button onClick={handleCrop} disabled={loading || !imageLoaded} className="flex-1">
            {loading ? 'Speichere...' : 'Übernehmen'}
          </Button>
        </div>
      </div>
    </div>
  );
}
