"use client";

import { useEffect, useRef, useState, useCallback, useMemo } from "react";
import dynamic from "next/dynamic";
import { useTranslations, useLocale } from "next-intl";
import { useHeatmapData, type HeatmapPoint } from "@/hooks/use-heatmap-data";
import { useCountryData, type LabelData } from "./use-country-data";
import { GlobeControls } from "./globe-controls";

function GlobeLoading() {
  const t = useTranslations("globe");
  return (
    <div className="flex h-full items-center justify-center">
      <div className="flex flex-col items-center gap-3">
        <div className="h-8 w-8 animate-spin rounded-full border-2 border-[var(--accent-cyan)] border-t-transparent" />
        <span className="font-mono text-xs text-[var(--text-muted)]">{t("loading")}</span>
      </div>
    </div>
  );
}

const Globe = dynamic(() => import("react-globe.gl"), {
  ssr: false,
  loading: () => <GlobeLoading />,
});

interface ArcData {
  startLat: number;
  startLng: number;
  endLat: number;
  endLng: number;
  color: string;
}

export function GlobeView() {
  const t = useTranslations("globe");
  const tPopup = useTranslations("clawPopup");
  const locale = useLocale();
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const globeRef = useRef<any>(undefined);
  const containerRef = useRef<HTMLDivElement>(null);
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
  const [hoveredPoint, setHoveredPoint] = useState<HeatmapPoint | null>(null);
  const [selectedPoint, setSelectedPoint] = useState<HeatmapPoint | null>(null);
  const { points } = useHeatmapData(30000);
  const { countries, labels } = useCountryData(locale);

  // Generate arcs only between online points
  const arcs = useMemo((): ArcData[] => {
    const onlinePoints = points.filter((p) => p.onlineCount > 0);
    if (onlinePoints.length < 2) return [];
    const result: ArcData[] = [];
    const maxArcs = Math.min(onlinePoints.length - 1, 8);
    for (let i = 0; i < maxArcs; i++) {
      const from = onlinePoints[i];
      const to = onlinePoints[(i + 1) % onlinePoints.length];
      result.push({
        startLat: from.lat,
        startLng: from.lng,
        endLat: to.lat,
        endLng: to.lng,
        color: "rgba(0, 240, 255, 0.4)",
      });
    }
    return result;
  }, [points]);

  useEffect(() => {
    const updateDimensions = () => {
      if (containerRef.current) {
        setDimensions({
          width: containerRef.current.clientWidth,
          height: containerRef.current.clientHeight,
        });
      }
    };

    updateDimensions();
    const observer = new ResizeObserver(updateDimensions);
    if (containerRef.current) observer.observe(containerRef.current);
    return () => observer.disconnect();
  }, []);

  useEffect(() => {
    if (globeRef.current) {
      globeRef.current.pointOfView({ lat: 20, lng: 100, altitude: 2.5 });
    }
  }, [dimensions]);

  const handleResetView = useCallback(() => {
    if (globeRef.current) {
      globeRef.current.pointOfView({ lat: 20, lng: 100, altitude: 2.5 });
    }
  }, []);

  const handleZoomIn = useCallback(() => {
    if (globeRef.current) {
      globeRef.current.pointOfView({ lat: 20, lng: 100, altitude: 1.5 });
    }
  }, []);

  const handleZoomOut = useCallback(() => {
    if (globeRef.current) {
      globeRef.current.pointOfView({ lat: 20, lng: 100, altitude: 3.5 });
    }
  }, []);

  return (
    <div ref={containerRef} className="relative h-full w-full overflow-hidden rounded-xl border border-white/5">
      {dimensions.width > 0 && (
        <Globe
          ref={globeRef}
          width={dimensions.width}
          height={dimensions.height}
          backgroundColor="rgba(0,0,0,0)"
          globeImageUrl="//unpkg.com/three-globe/example/img/earth-dark.jpg"
          atmosphereColor="#00f0ff"
          atmosphereAltitude={0.15}
          // Country polygons
          polygonsData={countries}
          polygonCapColor={() => "rgba(26, 31, 46, 0.6)"}
          polygonSideColor={() => "rgba(0, 240, 255, 0.05)"}
          polygonStrokeColor={() => "rgba(0, 240, 255, 0.15)"}
          polygonAltitude={0.005}
          // Country name labels (use HTML elements for CJK support)
          labelsData={labels}
          labelLat={(d: object) => (d as LabelData).lat}
          labelLng={(d: object) => (d as LabelData).lng}
          labelAltitude={0.01}
          labelSize={1.5}
          labelDotRadius={0}
          labelText={(d: object) => (d as LabelData).name}
          labelColor={() => "rgba(0, 240, 255, 0.5)"}
          labelResolution={2}
          // Graticules
          showGraticules={true}
          // Points with claw icons (using htmlElements for custom icons)
          htmlElementsData={points}
          htmlLat={(d: object) => (d as HeatmapPoint).lat}
          htmlLng={(d: object) => (d as HeatmapPoint).lng}
          htmlAltitude={(d: object) => {
            const p = d as HeatmapPoint;
            const base = Math.min(p.weight * 0.02, 0.15);
            return p.onlineCount > 0 ? base : base * 0.5;
          }}
          htmlElement={(d: object) => {
            const p = d as HeatmapPoint;
            const el = document.createElement("div");
            const size = p.onlineCount > 0 ? Math.max(p.weight * 0.8, 16) : Math.max(p.weight * 0.5, 12);
            el.style.width = `${size}px`;
            el.style.height = `${size}px`;
            el.style.backgroundImage = "url(/claw-icon.svg)";
            el.style.backgroundSize = "contain";
            el.style.backgroundRepeat = "no-repeat";
            el.style.backgroundPosition = "center";
            el.style.opacity = p.onlineCount > 0 ? "1" : "0.4";
            el.style.filter = p.onlineCount > 0 ? "drop-shadow(0 0 4px rgba(0, 240, 255, 0.6))" : "none";
            el.style.cursor = "pointer";
            el.style.transition = "transform 0.2s ease";
            el.dataset.pointId = `${p.city}-${p.country}`;

            // Add click handler directly to the element
            el.addEventListener("click", () => {
              setSelectedPoint(p);
            });
            el.addEventListener("mouseenter", () => {
              setHoveredPoint(p);
            });
            el.addEventListener("mouseleave", () => {
              setHoveredPoint(null);
            });

            return el;
          }}
          // Arcs
          arcsData={arcs}
          arcStartLat={(d: object) => (d as ArcData).startLat}
          arcStartLng={(d: object) => (d as ArcData).startLng}
          arcEndLat={(d: object) => (d as ArcData).endLat}
          arcEndLng={(d: object) => (d as ArcData).endLng}
          arcColor={(d: object) => (d as ArcData).color}
          arcDashLength={0.5}
          arcDashGap={0.2}
          arcDashAnimateTime={2000}
          arcStroke={0.3}
          // Auto-rotate
          animateIn={true}
          enablePointerInteraction={true}
        />
      )}

      {/* Hover Tooltip */}
      {hoveredPoint && !selectedPoint && (
        <div className="pointer-events-none absolute left-1/2 top-4 z-20 -translate-x-1/2">
          <div className="rounded-xl border border-white/10 bg-[var(--bg-card)]/95 p-3 shadow-xl backdrop-blur-sm">
            <div className="flex items-center gap-2">
              <span className="text-lg">🦞</span>
              <div>
                <p className="font-mono text-sm font-medium text-[var(--accent-cyan)]">
                  {hoveredPoint.city}
                </p>
                <p className="text-xs text-[var(--text-muted)]">{hoveredPoint.country}</p>
              </div>
            </div>
            <p className="mt-1 text-xs text-[var(--text-secondary)]">
              {t("totalClaws", { total: hoveredPoint.clawCount, online: hoveredPoint.onlineCount })}
            </p>
          </div>
        </div>
      )}

      {/* Click Popup */}
      {selectedPoint && (
        <div className="absolute bottom-4 left-4 z-20 w-72">
          <div className="rounded-xl border border-[var(--accent-cyan)]/20 bg-[var(--bg-card)]/95 p-4 shadow-xl backdrop-blur-sm">
            <div className="flex items-center justify-between">
              <div>
                <p className="font-mono text-sm font-medium text-[var(--accent-cyan)]">
                  {selectedPoint.city}
                </p>
                <p className="text-xs text-[var(--text-muted)]">{selectedPoint.country}</p>
              </div>
              <button
                onClick={() => setSelectedPoint(null)}
                className="text-xs text-[var(--text-muted)] hover:text-[var(--text-primary)]"
              >
                ✕
              </button>
            </div>
            <div className="mt-2 flex gap-2">
              <span className="rounded-full bg-[var(--accent-cyan)]/10 px-2 py-0.5 text-xs text-[var(--accent-cyan)]">
                {tPopup("total", { count: selectedPoint.clawCount })}
              </span>
              <span className="rounded-full bg-green-500/10 px-2 py-0.5 text-xs text-green-400">
                {tPopup("online", { count: selectedPoint.onlineCount })}
              </span>
            </div>
            {selectedPoint.claws.length > 0 && (
              <div className="mt-3 max-h-40 space-y-1.5 overflow-y-auto">
                {selectedPoint.claws.map((claw) => (
                  <div key={claw.id} className="flex items-center gap-2">
                    <span
                      className={`h-1.5 w-1.5 rounded-full ${
                        claw.isOnline ? "bg-green-400" : "bg-gray-500"
                      }`}
                    />
                    <span className="truncate font-mono text-xs text-[var(--text-secondary)]">
                      {claw.name}
                    </span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      )}

      <GlobeControls
        onResetView={handleResetView}
        onZoomIn={handleZoomIn}
        onZoomOut={handleZoomOut}
      />
    </div>
  );
}
