import React, { useEffect, useRef, useState } from "react";
import { CameraStateListener, GameRenderer } from "@/shared/render";
import { useGameAPI } from "@/shared/api";
import { useThrottledCallback } from "@/shared/hooks";

interface GameCanvasProps {
  className?: string;
  initialState?: any | null;
  onRendererReady?: (renderer: GameRenderer | null) => void;
  onNationHover?: (nationId: number | null) => void;
}

export const GameCanvas: React.FC<GameCanvasProps> = ({ className, initialState, onRendererReady, onNationHover }) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const rendererRef = useRef<GameRenderer | null>(null);
  const [isInitialized, setIsInitialized] = useState(false);
  const lastHoveredNationRef = useRef<number | null>(null);
  const lastHoveredTileRef = useRef<number | null>(null);
  const api = useGameAPI();

  // Apply initial state when provided (for reload recovery)
  useEffect(() => {
    if (!initialState || !rendererRef.current || !isInitialized) return;

    console.log("Applying initial game state to renderer:", initialState);
    const renderer = rendererRef.current;

    try {
      // Apply RenderInit data: terrain palette, terrain, player palette, territories
      renderer.setTerrainPalette(initialState.terrain_palette);
      renderer.initTerrain(initialState.terrain);
      renderer.initPalette(initialState.palette);
      renderer.applyTerritorySnapshot(initialState.initial_territories.turn, initialState.initial_territories.territories);
      console.log("Initial state applied successfully");
    } catch (err) {
      console.error("Failed to apply initial state:", err);
    }
  }, [initialState, isInitialized]);

  // Initialize renderer once on mount
  useEffect(() => {
    if (!canvasRef.current || rendererRef.current) return;

    let cancelled = false;
    const renderer = new GameRenderer();
    rendererRef.current = renderer;

    // Initialize renderer
    renderer
      .init(canvasRef.current)
      .then(async () => {
        if (cancelled) {
          renderer.destroy();
          return;
        }

        setIsInitialized(true);

        // Set up camera listener
        const cameraListener: CameraStateListener = {
          onCameraUpdate: (x, y, zoom) => {
            if (api && typeof api.sendCameraUpdate === "function") {
              api.sendCameraUpdate({ x, y, zoom });
            }
          },
        };
        renderer.setCameraListener(cameraListener);

        // Register renderer with API for receiving updates
        if (api && typeof api.setRenderer === "function") {
          await api.setRenderer(renderer);
        }

        // Notify parent that renderer is ready
        onRendererReady?.(renderer);
      })
      .catch((err: unknown) => {
        if (!cancelled) {
          console.error("Failed to initialize GameRenderer:", err);
        }
      });

    // Cleanup
    return () => {
      cancelled = true;
      if (rendererRef.current) {
        // Unregister renderer from API before destroying
        if (api && typeof api.setRenderer === "function") {
          api.setRenderer(null);
        }
        rendererRef.current.destroy();
        rendererRef.current = null;
        onRendererReady?.(null);
      }
      setIsInitialized(false);
    };
  }, [api, onRendererReady]);

  // Handle canvas clicks using native event listener (after renderer initialization)
  // React onClick doesn't work reliably when native listeners are attached to canvas
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || !rendererRef.current || !api) return;

    const handleCanvasClick = (e: MouseEvent) => {
      if (!rendererRef.current || !api) return;

      // Ignore clicks that were camera drags
      if (rendererRef.current.hadCameraInteraction()) {
        return;
      }

      const rect = canvas.getBoundingClientRect();
      const screenX = e.clientX - rect.left;
      const screenY = e.clientY - rect.top;

      const tileIndex = rendererRef.current.screenToTile(screenX, screenY);

      if (typeof api.sendMapClick === "function") {
        const worldPos = rendererRef.current.tileToWorld(tileIndex || 0);
        api.sendMapClick({
          tile_index: tileIndex,
          world_x: worldPos.x,
          world_y: worldPos.y,
          button: e.button,
        });
      }
    };

    canvas.addEventListener("click", handleCanvasClick);
    return () => canvas.removeEventListener("click", handleCanvasClick);
  }, [api, isInitialized]);

  // Handle mouse move (for hover) - throttled to reduce IPC overhead
  const handleMouseMove = useThrottledCallback((e: React.MouseEvent<HTMLCanvasElement>) => {
    if (!rendererRef.current) return;

    const rect = canvasRef.current!.getBoundingClientRect();
    const screenX = e.clientX - rect.left;
    const screenY = e.clientY - rect.top;

    const tileIndex = rendererRef.current.screenToTile(screenX, screenY);
    if (tileIndex === null) return;

    // Handle nation hover detection
    if (onNationHover) {
      const nationId = rendererRef.current.getNationAtTile(tileIndex);
      if (nationId !== lastHoveredNationRef.current) {
        lastHoveredNationRef.current = nationId;
        onNationHover(nationId);
      }
    }

    // Only send map hover if tile changed
    if (tileIndex !== lastHoveredTileRef.current) {
      lastHoveredTileRef.current = tileIndex;

      if (api && typeof api.sendMapHover === "function") {
        const worldPos = rendererRef.current.tileToWorld(tileIndex);
        // Only send if we have valid coordinates
        if (isFinite(worldPos.x) && isFinite(worldPos.y)) {
          api.sendMapHover({
            tile_index: tileIndex,
            world_x: worldPos.x,
            world_y: worldPos.y,
          });
        }
      }
    }
  }, 10);

  // Handle keyboard input
  useEffect(() => {
    if (!api) return;

    const handleKeyDown = (e: KeyboardEvent) => {
      if (typeof api.sendKeyPress === "function") {
        api.sendKeyPress({
          key: e.code,
          pressed: true,
        });
      }
    };

    const handleKeyUp = (e: KeyboardEvent) => {
      if (typeof api.sendKeyPress === "function") {
        api.sendKeyPress({
          key: e.code,
          pressed: false,
        });
      }
    };

    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);

    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("keyup", handleKeyUp);
    };
  }, [api]);

  return (
    <div className={className} style={{ position: "relative", width: "100%", height: "100%" }}>
      <canvas
        ref={canvasRef}
        onMouseMove={handleMouseMove}
        onContextMenu={(e) => e.preventDefault()}
        style={{
          display: "block",
          width: "100%",
          height: "100%",
          cursor: isInitialized ? undefined : "wait",
        }}
      />
      {!isInitialized && (
        <div
          style={{
            position: "absolute",
            top: "50%",
            left: "50%",
            transform: "translate(-50%, -50%)",
            color: "white",
            fontSize: "18px",
            fontFamily: "Inter, sans-serif",
          }}
        >
          Initializing renderer...
        </div>
      )}
    </div>
  );
};
