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;
};

export default function StepScanPhoto(props: Props) {
  const { className: classNameProp = "", isDecorationShown = true } = props;
  const className = ["scanned-photo", classNameProp];
  const { lines, drawElementChangeDelay, fingers, drawElements, lineLabelsShown = 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}`}>
                    <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>
                ))}
                {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"
          >
            <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>
  );
}
