import React, { useState, useRef, useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import styles from './CropPhoto.module.css';

const CropPhoto: React.FC = () => {
  const location = useLocation();
  const navigate = useNavigate();
  const imageRef = useRef<HTMLImageElement>(null);
  const wrapperRef = useRef<HTMLDivElement>(null);
  const viewportRef = useRef<HTMLDivElement>(null);
  
  const [imageUrl, setImageUrl] = useState<string | null>(null);
  const [scale, setScale] = useState(1);
  const [minScale, setMinScale] = useState(1);
  const [position, setPosition] = useState({ x: 0, y: 0 });
  const [isDragging, setIsDragging] = useState(false);
  const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
  const [initialTouch, setInitialTouch] = useState<{ distance: number; scale: number } | null>(null);

  // Эффект для создания и очистки blob URL
  useEffect(() => {
    const file = (location.state as any)?.file;
    if (!file) {
      navigate('/');
      return;
    }

    // Создаем URL только если его еще нет
    if (!imageUrl) {
      const url = URL.createObjectURL(file);
      setImageUrl(url);
    }

    // Очищаем URL при размонтировании компонента
    return () => {
      if (imageUrl) {
        URL.revokeObjectURL(imageUrl);
        setImageUrl(null);
      }
    };
  }, [location.state, navigate, imageUrl]);

  // Отдельный эффект для обработки загруженного изображения
  useEffect(() => {
    if (!imageUrl || !viewportRef.current) return;

    const img = new Image();
    
    img.onload = () => {
      const viewport = viewportRef.current;
      if (!viewport) return;

      const frame = viewport.querySelector(`.${styles.frame}`);
      if (!frame) return;

      const viewportRect = viewport.getBoundingClientRect();
      const frameRect = frame.getBoundingClientRect();

      // Используем размеры рамки обрезки
      const frameWidth = frameRect.width;
      const frameHeight = frameRect.height;

      // Вычисляем масштаб, чтобы изображение полностью покрывало область обрезки
      const scaleX = frameWidth / img.naturalWidth;
      const scaleY = frameHeight / img.naturalHeight;
      const baseScale = Math.max(scaleX, scaleY);

      setMinScale(baseScale);
      setScale(baseScale);

      // Центрируем изображение относительно рамки
      const scaledWidth = img.naturalWidth * baseScale;
      const scaledHeight = img.naturalHeight * baseScale;

      // Учитываем отступы от рамки до viewport
      const frameLeft = frameRect.left - viewportRect.left;
      const frameTop = frameRect.top - viewportRect.top;

      setPosition({
        x: frameLeft + (frameWidth - scaledWidth) / 2,
        y: frameTop + (frameHeight - scaledHeight) / 2
      });
    };

    img.onerror = () => {
      // В случае ошибки загрузки изображения
      console.error('Ошибка загрузки изображения');
      navigate('/');
    };

    img.src = imageUrl;
  }, [imageUrl, navigate]);

  const handleStart = (e: React.MouseEvent | React.TouchEvent) => {
    if ('touches' in e) {
      if (e.touches.length === 2) {
        const distance = getDistance(e.touches);
        setInitialTouch({ distance, scale });
        setIsDragging(false);
      } else {
        const touch = e.touches[0];
        setIsDragging(true);
        setDragStart({ x: touch.clientX - position.x, y: touch.clientY - position.y });
      }
    } else {
      setIsDragging(true);
      setDragStart({ x: e.clientX - position.x, y: e.clientY - position.y });
    }
  };

  const handleMove = (e: React.MouseEvent | React.TouchEvent) => {
    if ('touches' in e) {
      if (e.touches.length === 2 && initialTouch) {
        // Масштабирование двумя пальцами
        const distance = getDistance(e.touches);
        const newScale = Math.min(
          Math.max(
            (initialTouch.scale * distance) / initialTouch.distance,
            minScale
          ),
          minScale * 3
        );
        handleScale(newScale);
      } else if (isDragging) {
        const touch = e.touches[0];
        handleDrag(touch.clientX, touch.clientY);
      }
    } else if (isDragging) {
      handleDrag(e.clientX, e.clientY);
    }
  };

  const handleEnd = () => {
    setIsDragging(false);
    setInitialTouch(null);
  };

  const getDistance = (touches: React.TouchList) => {
    const dx = touches[0].clientX - touches[1].clientX;
    const dy = touches[0].clientY - touches[1].clientY;
    return Math.sqrt(dx * dx + dy * dy);
  };

  const handleDrag = (clientX: number, clientY: number) => {
    if (!viewportRef.current || !imageRef.current) return;

    const viewport = viewportRef.current;
    const frame = viewport.querySelector(`.${styles.frame}`);
    if (!frame) return;

    const viewportRect = viewport.getBoundingClientRect();
    const frameRect = frame.getBoundingClientRect();

    // Получаем позицию рамки относительно viewport
    const frameLeft = frameRect.left - viewportRect.left;
    const frameTop = frameRect.top - viewportRect.top;

    // Вычисляем размеры масштабированного изображения
    const scaledWidth = imageRef.current.naturalWidth * scale;
    const scaledHeight = imageRef.current.naturalHeight * scale;

    // Вычисляем новую позицию
    const newX = clientX - dragStart.x;
    const newY = clientY - dragStart.y;

    // Ограничиваем перемещение
    const minX = frameLeft - (scaledWidth - frameRect.width);
    const maxX = frameLeft;
    const minY = frameTop - (scaledHeight - frameRect.height);
    const maxY = frameTop;

    setPosition({
      x: Math.max(minX, Math.min(maxX, newX)),
      y: Math.max(minY, Math.min(maxY, newY))
    });
  };

  const handleScale = (newScale: number) => {
    if (!viewportRef.current || !imageRef.current) return;

    const viewport = viewportRef.current;
    const frame = viewport.querySelector(`.${styles.frame}`);
    if (!frame) return;

    const viewportRect = viewport.getBoundingClientRect();
    const frameRect = frame.getBoundingClientRect();

    // Получаем позицию рамки относительно viewport
    const frameLeft = frameRect.left - viewportRect.left;
    const frameTop = frameRect.top - viewportRect.top;

    // Вычисляем центр рамки
    const frameCenterX = frameLeft + frameRect.width / 2;
    const frameCenterY = frameTop + frameRect.height / 2;

    // Вычисляем текущий центр изображения
    const currentCenterX = position.x + (imageRef.current.naturalWidth * scale) / 2;
    const currentCenterY = position.y + (imageRef.current.naturalHeight * scale) / 2;

    // Вычисляем смещение для сохранения центра
    const dx = (frameCenterX - currentCenterX) * (newScale / scale - 1);
    const dy = (frameCenterY - currentCenterY) * (newScale / scale - 1);

    // Вычисляем новые размеры изображения
    const newScaledWidth = imageRef.current.naturalWidth * newScale;
    const newScaledHeight = imageRef.current.naturalHeight * newScale;

    // Вычисляем новую позицию
    let newX = position.x + dx;
    let newY = position.y + dy;

    // Ограничиваем позицию
    const minX = frameLeft - (newScaledWidth - frameRect.width);
    const maxX = frameLeft;
    const minY = frameTop - (newScaledHeight - frameRect.height);
    const maxY = frameTop;

    setScale(newScale);
    setPosition({
      x: Math.max(minX, Math.min(maxX, newX)),
      y: Math.max(minY, Math.min(maxY, newY))
    });
  };

  const handleZoom = (e: React.ChangeEvent<HTMLInputElement>) => {
    handleScale(parseFloat(e.target.value));
  };

  const createPreview = () => {
    if (!imageRef.current || !viewportRef.current) return null;

    const canvas = document.createElement('canvas');
    canvas.width = 768;
    canvas.height = 768;
    const ctx = canvas.getContext('2d');
    if (!ctx) return null;

    const viewport = viewportRef.current;
    const frame = viewport.querySelector(`.${styles.frame}`);
    if (!frame) return null;

    const frameRect = frame.getBoundingClientRect();
    const image = imageRef.current;

    ctx.drawImage(
      image,
      -position.x / scale,
      -position.y / scale,
      frameRect.width / scale,
      frameRect.height / scale,
      0,
      0,
      768,
      768
    );

    return canvas.toDataURL('image/jpeg', 0.95);
  };

  const handleConfirm = () => {
    const previewUrl = createPreview();
    if (previewUrl) {
      // Передаем не только URL, но и base64 данные
      // Убираем префикс data:image/jpeg;base64, оставляем только данные
      const imageData = previewUrl.split(',')[1];
      
      // Сохраняем данные в localStorage для сохранения между сеансами навигации
      localStorage.setItem('stickerPreviewUrl', previewUrl);
      localStorage.setItem('stickerImageData', imageData);
      
      navigate('/', { 
        state: { 
          previewUrl,
          imageData
        } 
      });
    }
  };

  return (
    <div className={styles.container}>
      <div className={styles.header}>
        <button className={styles.backButton} onClick={() => navigate('/')}>
          ←
        </button>
        <h1 className={styles.title}>Обрезка фото</h1>
        <button className={styles.confirmButton} onClick={handleConfirm}>
          Готово
        </button>
      </div>

      <div className={styles.cropContainer}>
        <div className={styles.viewportContainer}>
          <div
            ref={viewportRef}
            className={styles.viewport}
            onTouchStart={handleStart}
            onTouchMove={handleMove}
            onTouchEnd={handleEnd}
            onTouchCancel={handleEnd}
            onMouseDown={handleStart}
            onMouseMove={handleMove}
            onMouseUp={handleEnd}
            onMouseLeave={handleEnd}
            onContextMenu={(e) => e.preventDefault()}
          >
          {imageUrl && (
            <div
              ref={wrapperRef}
              className={styles.imageWrapper}
            >
              <img
                ref={imageRef}
                src={imageUrl}
                alt="Crop"
                className={styles.image}
                draggable={false}
                style={{
                  transform: `matrix(${scale}, 0, 0, ${scale}, ${position.x}, ${position.y})`
                }}
              />
            </div>
          )}
            <div className={styles.frame} />
            <div className={styles.frameCross} />
          </div>
        </div>

        <div className={styles.controls}>
          <input
            type="range"
            min={minScale}
            max={minScale * 3}
            step="0.01"
            value={scale}
            onChange={handleZoom}
            className={styles.zoomSlider}
          />
          <div className={styles.hint}>
            Отрегулируйте масштаб и положение фото
          </div>
        </div>
      </div>
    </div>
  );
};

export default CropPhoto;
