import { useEffect, useState } from "react";
import { useTransform } from "./TransformContext";
import { SightData } from "./types";
import { Assets, FederatedMouseEvent, Texture } from "pixi.js";

import { SIGHT_SIZE, UP_SCALE } from "./Constants";
import { coordinatesToLocal, localToCoordinates } from "./utils";
import { useMapData } from "./MapDataContext";

interface SightProps {
  sight: SightData;
  id: number;
}

export const Sight = ({ sight, id }: Readonly<SightProps>) => {
  const { rotation, scale } = useTransform();
  const { setSightCoordinates, setSelectedSight } = useMapData();

  const [position, setPosition] = useState(
    coordinatesToLocal(sight.latitude, sight.longitude)
  );
  const [isDragging, setIsDragging] = useState(false);
  const [isPointerDown, setIsPointerDown] = useState(false);
  const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });
  const [startMousePosition, setStartMousePosition] = useState({ x: 0, y: 0 });

  const handlePointerDown = (e: FederatedMouseEvent) => {
    setIsPointerDown(true);
    setIsDragging(false);
    setStartPosition({
      x: position.x,
      y: position.y,
    });
    setStartMousePosition({
      x: e.globalX,
      y: e.globalY,
    });

    e.stopPropagation();
  };
  const handlePointerMove = (e: FederatedMouseEvent) => {
    if (!isPointerDown) return;

    if (!isDragging) {
      const dx = e.globalX - startMousePosition.x;
      const dy = e.globalY - startMousePosition.y;
      if (Math.abs(dx) > 2 || Math.abs(dy) > 2) {
        setIsDragging(true);
      } else {
        return;
      }
    }

    const dx = (e.globalX - startMousePosition.x) / scale / UP_SCALE;
    const dy = (e.globalY - startMousePosition.y) / scale / UP_SCALE;
    const cos = Math.cos(rotation);
    const sin = Math.sin(rotation);
    const newPosition = {
      x: startPosition.x + dx * cos + dy * sin,
      y: startPosition.y - dx * sin + dy * cos,
    };
    setPosition(newPosition);
    const coordinates = localToCoordinates(newPosition.x, newPosition.y);
    setSightCoordinates(sight.id, coordinates.latitude, coordinates.longitude);
    e.stopPropagation();
  };

  const handlePointerUp = (e: FederatedMouseEvent) => {
    setIsPointerDown(false);

    // Если не было перетаскивания, то это клик
    if (!isDragging) {
      setSelectedSight(sight);
    }

    setIsDragging(false);
    e.stopPropagation();
  };

  const [texture, setTexture] = useState(Texture.EMPTY);
  useEffect(() => {
    Assets.load("/sight_icon.svg").then(setTexture);
  }, []);

  useEffect(() => {}, [id, sight.latitude, sight.longitude]);

  if (!sight) {
    console.error("sight is null");
    return null;
  }

  // Компенсируем масштаб, но при зуме текст немного увеличивается
  const clampedScale = Math.min(Math.max(scale, 1), 3);
  const textScaleFactor = 1 + (clampedScale - 1) * 0.4;
  const compensatedSize = SIGHT_SIZE / scale;
  const compensatedFontSize = (24 / scale) * textScaleFactor;

  return (
    <pixiContainer
      rotation={-rotation}
      eventMode="static"
      interactive
      onPointerDown={handlePointerDown}
      onGlobalPointerMove={handlePointerMove}
      onPointerUp={handlePointerUp}
      onPointerUpOutside={handlePointerUp}
      x={position.x * UP_SCALE - SIGHT_SIZE / 2}
      y={position.y * UP_SCALE - SIGHT_SIZE / 2}
    >
      <pixiSprite
        texture={texture}
        width={compensatedSize}
        height={compensatedSize}
      />
      <pixiGraphics
        draw={(g) => {
          g.clear();
          g.circle(0, 0, 20 / scale);
          g.fill({ color: "#000" });
        }}
        x={compensatedSize}
        y={0}
      />
      <pixiText
        text={`${id + 1}`}
        x={compensatedSize + 1 / scale}
        y={0}
        anchor={0.5}
        style={{
          fontSize: compensatedFontSize,
          fontWeight: "bold",
          fill: "#ffffff",
        }}
      />
    </pixiContainer>
  );
};
