import { useState, useRef, useEffect, useCallback } from "react";
import { PositionAnimator } from "../utils/animationUtils";

interface AnimatedPositionState {
  x: number;
  y: number;
  isAnimating: boolean;
}

/**
 * Хук для управления анимированной позицией элемента
 * Основано на логике анимации трамвая
 */
export const useAnimatedPosition = (
  initialX: number = 0,
  initialY: number = 0,
  animationDuration: number = 1000
) => {
  const [position, setPosition] = useState<AnimatedPositionState>({
    x: initialX,
    y: initialY,
    isAnimating: false,
  });

  const animatorRef = useRef<PositionAnimator | null>(null);

  // Создаем аниматор при первом рендере
  useEffect(() => {
    if (!animatorRef.current) {
      animatorRef.current = new PositionAnimator(
        (newPosition) => {
          setPosition((prev) => ({
            ...prev,
            x: newPosition.x,
            y: newPosition.y,
          }));
        },
        () => {
          setPosition((prev) => ({
            ...prev,
            isAnimating: false,
          }));
        },
        animationDuration
      );
    }

    return () => {
      if (animatorRef.current) {
        animatorRef.current.stop();
      }
    };
  }, [animationDuration]);

  // Функция для анимации к новой позиции
  const animateTo = useCallback(
    (targetX: number, targetY: number, duration?: number) => {
      if (animatorRef.current) {
        setPosition((prev) => ({ ...prev, isAnimating: true }));
        animatorRef.current.animateTo(targetX, targetY, duration);
      }
    },
    []
  );

  // Функция для мгновенной установки позиции
  const setPositionImmediate = useCallback((x: number, y: number) => {
    if (animatorRef.current) {
      animatorRef.current.stop();
      animatorRef.current.setPosition(x, y);
      setPosition({
        x,
        y,
        isAnimating: false,
      });
    }
  }, []);

  // Функция для остановки анимации
  const stopAnimation = useCallback(() => {
    if (animatorRef.current) {
      animatorRef.current.stop();
      setPosition((prev) => ({ ...prev, isAnimating: false }));
    }
  }, []);

  return {
    position: { x: position.x, y: position.y },
    isAnimating: position.isAnimating,
    animateTo,
    setPositionImmediate,
    stopAnimation,
  };
};

/**
 * Хук для управления анимированной позицией с поддержкой полярных координат
 */
export const useAnimatedPolarPosition = (
  centerX: number = 0,
  centerY: number = 0,
  initialAngle: number = 0,
  initialDistance: number = 0,
  animationDuration: number = 1000
) => {
  const [position, setPosition] = useState<AnimatedPositionState>({
    x: centerX + initialDistance * Math.cos(initialAngle),
    y: centerY - initialDistance * Math.sin(initialAngle),
    isAnimating: false,
  });

  const [polarPosition, setPolarPosition] = useState({
    angle: initialAngle,
    distance: initialDistance,
  });

  const animatorRef = useRef<PositionAnimator | null>(null);

  useEffect(() => {
    if (!animatorRef.current) {
      animatorRef.current = new PositionAnimator(
        (newPosition) => {
          setPosition((prev) => ({
            ...prev,
            x: newPosition.x,
            y: newPosition.y,
          }));
        },
        () => {
          setPosition((prev) => ({
            ...prev,
            isAnimating: false,
          }));
        },
        animationDuration
      );
    }

    return () => {
      if (animatorRef.current) {
        animatorRef.current.stop();
      }
    };
  }, [animationDuration]);

  // Функция для анимации к новой позиции по полярным координатам
  const animateToPolar = useCallback(
    (targetAngle: number, targetDistance: number, duration?: number) => {
      if (animatorRef.current) {
        const targetX = centerX + targetDistance * Math.cos(targetAngle);
        const targetY = centerY - targetDistance * Math.sin(targetAngle);

        setPosition((prev) => ({ ...prev, isAnimating: true }));
        setPolarPosition({ angle: targetAngle, distance: targetDistance });
        animatorRef.current.animateTo(targetX, targetY, duration);
      }
    },
    [centerX, centerY]
  );

  // Функция для анимации к новой позиции по декартовым координатам
  const animateTo = useCallback(
    (targetX: number, targetY: number, duration?: number) => {
      if (animatorRef.current) {
        const dx = targetX - centerX;
        const dy = centerY - targetY;
        const targetDistance = Math.sqrt(dx * dx + dy * dy);
        const targetAngle = Math.atan2(dy, dx);

        setPosition((prev) => ({ ...prev, isAnimating: true }));
        setPolarPosition({ angle: targetAngle, distance: targetDistance });
        animatorRef.current.animateTo(targetX, targetY, duration);
      }
    },
    [centerX, centerY]
  );

  // Функция для мгновенной установки позиции
  const setPositionImmediate = useCallback(
    (x: number, y: number) => {
      if (animatorRef.current) {
        animatorRef.current.stop();
        animatorRef.current.setPosition(x, y);

        const dx = x - centerX;
        const dy = centerY - y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        const angle = Math.atan2(dy, dx);

        setPosition({
          x,
          y,
          isAnimating: false,
        });
        setPolarPosition({ angle, distance });
      }
    },
    [centerX, centerY]
  );

  // Функция для остановки анимации
  const stopAnimation = useCallback(() => {
    if (animatorRef.current) {
      animatorRef.current.stop();
      setPosition((prev) => ({ ...prev, isAnimating: false }));
    }
  }, []);

  return {
    position: { x: position.x, y: position.y },
    polarPosition: {
      angle: polarPosition.angle,
      distance: polarPosition.distance,
    },
    isAnimating: position.isAnimating,
    animateTo,
    animateToPolar,
    setPositionImmediate,
    stopAnimation,
  };
};
