import {
  IPalmistryFinger,
  IPalmistryLine,
  IPalmistryPoint,
} from "@/api/resources/Palmistry";
import "./scanned-photo.css";
import { useCallback, useEffect, useRef, useState } from "react";

type Props = {
  photo: string;
  small: boolean;
  displayLines: boolean;
  lines: Array<IPalmistryLine & { label?: string }>;
  fingers: IPalmistryFinger[];
  drawElementChangeDelay: number;
  startDelay: number;
  drawElements: Array<IPalmistryLine | IPalmistryFinger>;
  className?: string;
  isDecorationShown?: boolean;
  lineLabelsShown?: boolean;
  isShowLineScale?: boolean;
};

export default function StepScanPhoto(props: Props) {
  const { className: classNameProp = "", isDecorationShown = true } = props;
  const className = ["scanned-photo", classNameProp];
  const { lines, drawElementChangeDelay, fingers, drawElements, lineLabelsShown = false, isShowLineScale = false } = props;
  const imageRef = useRef<HTMLImageElement>(null);
  const linesRef = useRef<SVGPathElement[]>([]);
  const [isImageLoaded, setIsImageLoaded] = useState(false);
  const [imageWidth, setImageWidth] = useState(0);
  const [imageHeight, setImageHeight] = useState(0);
  const [textPositions, setTextPositions] = useState<Array<{ x: number, y: number }>>([]);

  if (props.small) {
    className.push("scanned-photo_small");
  }

  useEffect(() => {
    if (isImageLoaded && imageRef.current) {
      setImageWidth(imageRef.current.width || 0);
      setImageHeight(imageRef.current.height || 0);
    }
  }, [isImageLoaded]);

  useEffect(() => {
    if (!imageWidth || !imageHeight || !lines.length) return;

    const textWidth = 90;
    const textHeight = 17;
    const padding = 10;
    const newPositions: Array<{ x: number, y: number }> = [];

    lines.forEach((line, index) => {
      const points = line.points;
      const positions = [];

      for (let i = 0; i < points.length - 1; i++) {
        const x = (points[i].x + points[i + 1].x) / 2;
        const y = (points[i].y + points[i + 1].y) / 2;
        positions.push({ x, y });
      }

      positions.unshift({ x: points[0].x, y: points[0].y });
      positions.push({ x: points[points.length - 1].x, y: points[points.length - 1].y });

      let positionFound = false;
      for (const pos of positions) {
        let hasOverlap = false;

        for (const existingPos of newPositions) {
          if (
            pos.x * imageWidth + padding < existingPos.x + textWidth &&
            pos.x * imageWidth + padding + textWidth > existingPos.x &&
            pos.y * imageHeight - padding < existingPos.y + textHeight &&
            pos.y * imageHeight - padding + textHeight > existingPos.y
          ) {
            hasOverlap = true;
            break;
          }
        }

        if (!hasOverlap) {
          newPositions.push({
            x: pos.x * imageWidth + 10,
            y: pos.y * imageHeight - 5
          });
          positionFound = true;
          break;
        }
      }

      if (!positionFound) {
        newPositions.push({
          x: points[0].x * imageWidth + textWidth + padding * (index + 1),
          y: points[0].y * imageHeight - textHeight - padding * (index + 1)
        });
      }
    });

    setTextPositions(newPositions);
  }, [lines, imageWidth, imageHeight]);

  const getCoordinatesString = useCallback(
    (points: IPalmistryPoint[]) => {
      const coordinatesString = `M ${points[0]?.x * imageWidth} ${points[0]?.y * imageHeight
        }`;
      return points.reduce(
        (acc, point) =>
          `${acc} L ${point?.x * imageWidth} ${point?.y * imageHeight}`,
        coordinatesString
      );
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [lines, isImageLoaded, imageWidth, imageHeight]
  );

  const getLineLength = (line: SVGPathElement) => {
    return line?.getTotalLength();
  };

  return (
    <div
      className={className.join(" ")}
      style={{
        height: imageHeight ? `${imageHeight}px` : "auto",
      }}
    >
      <div className="scanned-photo__container">
        <div
          className={`scanned-photo__stick ${!isDecorationShown ? "scanned-photo__stick_hidden" : ""}`}
          style={{
            animationDelay: `${drawElementChangeDelay * drawElements?.length + 2500
              }ms`,
            maxWidth: `${imageWidth}px`,
          }}
        />

        <div className="scanned-photo__image-container">
          <img
            className="scanned-photo__image"
            alt="PalmIcon"
            src={props.photo}
            ref={imageRef}
            onLoad={() => setIsImageLoaded(true)}
          // width={imageWidth}
          // height={imageHeight}
          />
        </div>
        {!!imageHeight && !!imageWidth && (
          <svg
            viewBox={`0 0 ${imageWidth} ${imageHeight}`}
            className="scanned-photo__svg-objects"
          >
            {!!fingers.length &&
              fingers?.map((finger, index) => {
                return (
                  <svg
                    x={finger.point.x * imageWidth - 12}
                    y={finger.point.y * imageHeight - 12}
                    height="24px"
                    width="24px"
                    key={index}
                  >
                    <circle
                      cx="50%"
                      cy="50%"
                      r="11"
                      fill="white"
                      opacity="0.3"
                      className="scanned-photo__finger-point"
                      style={{
                        animationDelay: `${drawElementChangeDelay * (index + 1)
                          }ms`,
                      }}
                    />
                    <circle
                      cx="50%"
                      cy="50%"
                      r="5"
                      fill="#066FDE"
                      stroke="white"
                      strokeWidth="0.3"
                      className="scanned-photo__finger-point"
                      style={{
                        animationDelay: `${drawElementChangeDelay * (index + 1)
                          }ms`,
                      }}
                    />
                  </svg>
                );
              })}

            {props.displayLines && (
              <>
                {lines.map((line, index) => (
                  <g key={`line-${index}`}>
                    <g>
                      <path
                        className={`scanned-photo__line scanned-photo__line_${line?.name}`}
                        d={getCoordinatesString(line?.points)}
                        ref={(el) =>
                          (linesRef.current[index] = el as SVGPathElement)
                        }
                        style={{
                          strokeDasharray:
                            getLineLength(linesRef.current[index]) || 500,
                          strokeDashoffset:
                            getLineLength(linesRef.current[index]) || 500,
                          animationDelay: `${drawElementChangeDelay * (index + 1)
                            }ms`,
                        }}
                      />
                    </g>

                  </g>
                ))}
                {isShowLineScale && lines.map((line, index) => (
                  <g key={`line-scale-${index}`}>
                    {line.name === "life" && <g>
                      {(() => {
                        // Вычисляем общую длину линии
                        let totalLength = 0;
                        const segmentLengths = [];

                        for (let i = 0; i < line.points.length - 1; i++) {
                          const dx = line.points[i + 1].x - line.points[i].x;
                          const dy = line.points[i + 1].y - line.points[i].y;
                          const segmentLength = Math.sqrt(dx * dx + dy * dy);
                          totalLength += segmentLength;
                          segmentLengths.push(segmentLength);
                        }

                        // Вычисляем расстояние между черточками
                        // Для 8 черточек нужно 7 интервалов, плюс два интервала от краев
                        const intervalCount = 10; // 7 интервалов между черточками + 2 интервала от краев

                        // Создаем 8 равномерно распределенных точек вдоль линии
                        const result = [];

                        // Сначала собираем все точки для анализа
                        const scalePoints = [];
                        for (let i = 0; i < 8; i++) {
                          // Вычисляем позицию вдоль линии (от 0 до 1)
                          // Первая черточка на расстоянии intervalLength от начала
                          // Последняя черточка на расстоянии intervalLength от конца
                          const position = (i + 1) / (intervalCount - 1);
                          const targetLength = position * totalLength;

                          // Находим сегмент, в котором находится точка
                          let currentLength = 0;
                          let segmentIndex = 0;

                          for (let j = 0; j < segmentLengths.length; j++) {
                            if (currentLength + segmentLengths[j] >= targetLength) {
                              segmentIndex = j;
                              break;
                            }
                            currentLength += segmentLengths[j];
                          }

                          // Вычисляем точное положение внутри сегмента
                          const segmentPosition = (targetLength - currentLength) / segmentLengths[segmentIndex];

                          // Интерполируем координаты точки
                          const x = line.points[segmentIndex].x +
                            (line.points[segmentIndex + 1].x - line.points[segmentIndex].x) * segmentPosition;
                          const y = line.points[segmentIndex].y +
                            (line.points[segmentIndex + 1].y - line.points[segmentIndex].y) * segmentPosition;

                          // Вычисляем вектор направления линии для перпендикуляра
                          const dx = line.points[segmentIndex + 1].x - line.points[segmentIndex].x;
                          const dy = line.points[segmentIndex + 1].y - line.points[segmentIndex].y;

                          // Нормализуем вектор и поворачиваем на 90 градусов для перпендикуляра
                          const length = Math.sqrt(dx * dx + dy * dy);
                          const perpX = -dy / length * 0.015;
                          const perpY = dx / length * 0.015;

                          // Вычисляем угол поворота для текста (в градусах)
                          const angle = Math.atan2(perpY, perpX) * 180 / Math.PI;

                          // Определяем, нужно ли перевернуть текст
                          // Если угол больше 90 или меньше -90 градусов, текст будет перевернут
                          // В этом случае добавляем 180 градусов к углу поворота
                          const textAngle = (angle > 90 || angle < -90) ? angle + 180 : angle;

                          // Виртуально размещаем текст с обеих сторон и проверяем пересечения
                          const leftTextX = x * imageWidth + perpX * imageWidth * 2.5;
                          const leftTextY = y * imageHeight + perpY * imageHeight * 2.5;
                          const rightTextX = x * imageWidth - perpX * imageWidth * 2.5;
                          const rightTextY = y * imageHeight - perpY * imageHeight * 2.5;

                          // Создаем виртуальный прямоугольник для текста (примерные размеры)
                          const textWidth = 30; // Примерная ширина текста
                          const textHeight = 15; // Примерная высота текста

                          // Создаем точки для проверки пересечений (углы и центр прямоугольника)
                          const leftTextPoints = [
                            { x: leftTextX - textWidth / 2, y: leftTextY - textHeight / 2 },
                            { x: leftTextX + textWidth / 2, y: leftTextY - textHeight / 2 },
                            { x: leftTextX + textWidth / 2, y: leftTextY + textHeight / 2 },
                            { x: leftTextX - textWidth / 2, y: leftTextY + textHeight / 2 },
                            { x: leftTextX, y: leftTextY }
                          ];

                          const rightTextPoints = [
                            { x: rightTextX - textWidth / 2, y: rightTextY - textHeight / 2 },
                            { x: rightTextX + textWidth / 2, y: rightTextY - textHeight / 2 },
                            { x: rightTextX + textWidth / 2, y: rightTextY + textHeight / 2 },
                            { x: rightTextX - textWidth / 2, y: rightTextY + textHeight / 2 },
                            { x: rightTextX, y: rightTextY }
                          ];

                          // Подсчитываем количество пересечений с каждой стороны
                          let leftIntersections = 0;
                          let rightIntersections = 0;

                          // Проверяем пересечения с другими линиями
                          for (const otherLine of lines) {
                            if (otherLine === line) continue;

                            for (let j = 0; j < otherLine.points.length - 1; j++) {
                              const p1 = otherLine.points[j];
                              const p2 = otherLine.points[j + 1];

                              // Проверяем пересечение с каждой точкой текста слева
                              for (const point of leftTextPoints) {
                                const distance = pointToLineDistance(
                                  point.x / imageWidth, point.y / imageHeight,
                                  p1.x, p1.y,
                                  p2.x, p2.y
                                );

                                if (distance < 0.01) { // Порог расстояния
                                  leftIntersections++;
                                }
                              }

                              // Проверяем пересечение с каждой точкой текста справа
                              for (const point of rightTextPoints) {
                                const distance = pointToLineDistance(
                                  point.x / imageWidth, point.y / imageHeight,
                                  p1.x, p1.y,
                                  p2.x, p2.y
                                );

                                if (distance < 0.01) { // Порог расстояния
                                  rightIntersections++;
                                }
                              }
                            }
                          }

                          // Сохраняем все данные для точки
                          scalePoints.push({
                            x, y, perpX, perpY, textAngle, leftIntersections, rightIntersections
                          });
                        }

                        // Определяем общую сторону для всех чисел
                        let totalLeftIntersections = 0;
                        let totalRightIntersections = 0;

                        for (const point of scalePoints) {
                          totalLeftIntersections += point.leftIntersections;
                          totalRightIntersections += point.rightIntersections;
                        }

                        // Определяем, с какой стороны меньше пересечений в целом
                        const isLeftSideBetter = totalLeftIntersections <= totalRightIntersections;

                        // Определяем множитель для стороны текста (1 или -1)
                        const sideMultiplier = isLeftSideBetter ? 1 : -1;

                        // Теперь отрисовываем все точки с выбранной стороной
                        for (let i = 0; i < scalePoints.length; i++) {
                          const point = scalePoints[i];

                          // Строим перпендикулярную линию
                          result.push(
                            <g key={`line-scale-${i}`}>
                              <path
                                className={`scanned-photo__line-scale scanned-photo__line_${line?.name}`}
                                style={{
                                  animationDelay: `${drawElementChangeDelay * (index + 1) + 1500 + i * 100}ms`,
                                }}
                                d={`M ${point.x * imageWidth - point.perpX * imageWidth} ${point.y * imageHeight - point.perpY * imageHeight} L ${point.x * imageWidth + point.perpX * imageWidth} ${point.y * imageHeight + point.perpY * imageHeight}`}
                              />
                              <text
                                x={point.x * imageWidth + point.perpX * imageWidth * 2.5 * sideMultiplier}
                                y={point.y * imageHeight + point.perpY * imageHeight * 2.5 * sideMultiplier}
                                className={`scanned-photo__line-scale-text scanned-photo__line_${line?.name}`}
                                transform={`rotate(${point.textAngle}, ${point.x * imageWidth + point.perpX * imageWidth * 2.5 * sideMultiplier}, ${point.y * imageHeight + point.perpY * imageHeight * 2.5 * sideMultiplier})`}
                                textAnchor="middle"
                                dominantBaseline="middle"
                                fontSize="10"
                                fill="#066FDE"
                                style={{
                                  animationDelay: `${drawElementChangeDelay * (index + 1) + 1500 + i * 100}ms`,
                                }}
                              >
                                {(i + 1) * 10}
                              </text>
                            </g>
                          );
                        }

                        // Функция для вычисления расстояния от точки до линии
                        function pointToLineDistance(px: number, py: number, x1: number, y1: number, x2: number, y2: number): number {
                          const A = px - x1;
                          const B = py - y1;
                          const C = x2 - x1;
                          const D = y2 - y1;

                          const dot = A * C + B * D;
                          const lenSq = C * C + D * D;
                          let param = -1;

                          if (lenSq !== 0) {
                            param = dot / lenSq;
                          }

                          let xx, yy;

                          if (param < 0) {
                            xx = x1;
                            yy = y1;
                          } else if (param > 1) {
                            xx = x2;
                            yy = y2;
                          } else {
                            xx = x1 + param * C;
                            yy = y1 + param * D;
                          }

                          const dx = px - xx;
                          const dy = py - yy;

                          return Math.sqrt(dx * dx + dy * dy);
                        }

                        return result;
                      })()}
                    </g>}
                  </g>
                ))}
                {lineLabelsShown && lines.map((line, index) => (
                  <g key={`line-label-${index}`}>
                    <text
                      x={textPositions[index]?.x || 0}
                      y={textPositions[index]?.y || 0}
                      fill="#066FDE"
                      className={`scanned-photo__line-text scanned-photo__line-text_${line?.name}`}
                      style={{
                        animationDelay: `${drawElementChangeDelay * (index + 1) + 300}ms`,
                      }}
                    >
                      {line.label || line.name}
                    </text>
                  </g>
                ))}
              </>
            )}
          </svg>
        )}
      </div>
      <div
        className={`scanned-photo__decoration ${!isDecorationShown ? "scanned-photo__decoration_hidden" : ""}`}
        style={{
          animationDelay: `${drawElementChangeDelay * drawElements?.length}ms`,
        }}
      >
        <div
          className="scanned-photo__decoration__corners"
          style={{
            animationDelay: `${drawElementChangeDelay * drawElements?.length + 1500
              }ms`,
          }}
        >
          <div className="scanned-photo__decoration__light-blue-circle" />

          <svg
            version="1.1"
            id="L3"
            xmlns="http://www.w3.org/2000/svg"
            x="0px"
            y="0px"
            viewBox="0 0 220 220"
            enableBackground="new 0 0 0 0"
            className="scanned-photo__decoration_svg"
          >
            <circle
              fill="none"
              stroke="#EFF2FD"
              strokeWidth="2"
              cx="110"
              cy="110"
              r="105"
            />
            <circle
              fill="#066fde"
              stroke="none"
              strokeWidth="3"
              cx="110"
              cy="215"
              r="4"
            >
              <animateTransform
                attributeName="transform"
                dur={`${drawElementChangeDelay * drawElements?.length + 3000
                  }ms`}
                type="rotate"
                from="0 110 110"
                to="360 110 110"
                repeatCount="indefinite"
              ></animateTransform>
            </circle>
          </svg>
        </div>
      </div>
    </div>
  );
}
