import { useState } from "react";
import { GripHorizontal, ChevronUp, Eye, EyeOff } from "lucide-react";
import L from "leaflet";
import { useAtom } from "jotai";
import { isOpenMapsetDialogAtom, selectedMapsetAtom } from "../../../../state/mapset-dialog";
import { useQuery } from "@tanstack/react-query";
import { ActiveLayer, removeLayerAtom, toggleLayerAtom, setLayerOpacityAtom } from "../../../../state/active-layers";
import { mapAtom } from "../../../../state/map";
import mapsetApi from "@/shared/services/mapset";
import { LegendDisplay } from "./legend-display";
import { OpacityControl } from "./opacity-control";
import { LayerActions } from "./layer-actions";
import dynamic from "next/dynamic";

const ChoroplethControl = dynamic(() => import("./choropleth-control"), {
  ssr: false,
  loading: () => <div className="w-full aspect-square bg-gray-200 animate-pulse" />,
});

interface LayerControlItemProps {
  layer: ActiveLayer;
  layerInstance?: L.Layer;
  onZoom: (bounds?: L.LatLngBoundsExpression | null) => void;
}

export const LayerControlItem = ({ layer, layerInstance, onZoom }: LayerControlItemProps) => {
  const [isExpanded, setIsExpanded] = useState(false);
  // Drive slider from global state so newly created instances pick it up
  const opacity = layer.settings.opacity;
  const [, setIsOpenDialog] = useAtom(isOpenMapsetDialogAtom);
  const [, setSelectedMapset] = useAtom(selectedMapsetAtom);
  const [, removeLayer] = useAtom(removeLayerAtom);
  const [, toggleLayer] = useAtom(toggleLayerAtom);
  const [, setLayerOpacity] = useAtom(setLayerOpacityAtom);
  const { data: mapset } = useQuery({
    queryKey: ["mapset", layer.source.id],
    queryFn: () =>
      mapsetApi.getMapsetById(layer.source.id.toString(), { skipAuth: true }).then((res) => {
        return res;
      }),
  });
  const [map] = useAtom(mapAtom);

  const handleOpacityChange = (value: number[]) => {
    const next = value[0];

    // Update the Leaflet instance immediately for responsiveness
    if (layerInstance && layerInstance instanceof L.TileLayer.WMS) {
      layerInstance.setOpacity(next);
    }
    if (layerInstance && layerInstance instanceof L.GeoJSON) {
      layerInstance.setStyle({
        fillOpacity: next,
        opacity: next,
      });
    }

    // Persist in global state so new/reattached instances get correct opacity
    setLayerOpacity({ layerId: layer.id, opacity: next });
  };

  const handleInfo = () => {
    if (!mapset) return;

    setSelectedMapset(mapset);
    setIsOpenDialog(true);
  };

  const handleToggleVisibility = () => {
    if (!map) return;

    toggleLayer(layer.id);
    if (layerInstance) {
      if (layer.settings.visible) {
        layerInstance.remove();
      } else {
        layerInstance.addTo(map);
      }
    }
  };

  function toLatLngBounds(bounds: L.LatLngBoundsExpression): L.LatLngBounds {
    if ("getSouthWest" in bounds && "getNorthEast" in bounds) {
      return bounds as L.LatLngBounds;
    }
    return L.latLngBounds(bounds as L.LatLngExpression[]);
  }

  const handleDownloadImage = () => {
    if (!layer.layer.url || !layer.layer.layers) return;

    const rawBounds = layer.layer.bounds ?? map?.getBounds() ?? null;
    if (!rawBounds) return;

    const bounds = toLatLngBounds(rawBounds);
    const southWest = bounds.getSouthWest();
    const northEast = bounds.getNorthEast();

    const bbox = [southWest.lng, southWest.lat, northEast.lng, northEast.lat].join(",");

    const width = 1024;
    const height = 768;

    const downloadUrl = `${layer.layer.url}?service=WMS&version=1.1.1&request=GetMap&layers=${layer.layer.layers}&styles=&bbox=${bbox}&width=${width}&height=${height}&srs=EPSG:4326&format=image/png&transparent=true`;

    window.open(downloadUrl, "_blank");
  };

  return (
    <div className="bg-muted rounded-lg border border-primary p-3">
      <div className="cursor-pointer w-full flex items-center justify-between text-sm">
        <div className="flex flex-1 items-center gap-2">
          <button className="cursor-pointer self-start mt-0.5">
            <GripHorizontal className="w-4 h-4 text-zinc-950"></GripHorizontal>
          </button>
          <button onClick={() => setIsExpanded((prev) => !prev)} className={`text-left text-zinc-700 text-sm cursor-pointer ${!isExpanded && "line-clamp-1"}`}>
            {layer.name}
          </button>
        </div>

        {!isExpanded && (
          <button onClick={handleToggleVisibility} className="cursor-pointer flex items-center justify-center" title={layer.settings.visible ? "Hide layer" : "Show layer"}>
            {layer.settings.visible ? <Eye className="h-4 w-4 text-zinc-950" /> : <EyeOff className="h-4 w-4 text-zinc-950" />}
          </button>
        )}

        {!isExpanded && <div className="border-l border-gray-300 h-4 mx-2"></div>}

        <button onClick={() => setIsExpanded((prev) => !prev)} className="flex items-center justify-center shrink-0 self-start mt-0.5">
          {isExpanded ? <ChevronUp size={12} className="h-4 w-4 rotate-0 shrink-0 text-zinc-950" /> : <ChevronUp size={12} className="rotate-180 h-4 w-4 text-zinc-950" />}
        </button>
      </div>

      {isExpanded && (
        <div className="space-y-3 mt-3">
          <LegendDisplay layer={layer} />
          <LayerActions layer={layer} onZoom={onZoom} onInfo={handleInfo} onRemove={() => removeLayer(layer.id)} onDownload={handleDownloadImage} />
          <OpacityControl opacity={opacity} onOpacityChange={handleOpacityChange} />

          {mapset?.layer_type === "point" && <ChoroplethControl layer={layer} />}
        </div>
      )}
    </div>
  );
};
