"use client";

import { Map } from "@/components/map";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useSettings } from "@/hook/use-settings";
import { useQueryParams } from "@/hook/use-query-params";
import { Location } from "@/types/global";
import { useDebounce } from "@/hook/use-debounce";
import type { Map as MapLibreMap } from "maplibre-gl";
import { MarkerCluster } from "./marker-cluster";

interface LocationWithDistance extends Location {
  distance: string;
}

const DEFAULT_CENTER = { lat: 35.6892, lng: 51.389 };

const toFiniteNumber = (value: unknown, fallback: number) => {
  const num = typeof value === "number" ? value : parseFloat(String(value ?? ""));
  return Number.isFinite(num) ? num : fallback;
};

export const ShopsInMap = () => {
  const [map, setMap] = useState<MapLibreMap>();
  const [center, setCenter] = useState<LocationWithDistance | null>(null);
  const debouncedCenter = useDebounce(center);
  const { setQueryParams, urlSearchParams } = useQueryParams({ scroll: false });
  const { settings } = useSettings();

  const mapCenter = useMemo(() => {
    const latParam = urlSearchParams.get("latitude");
    const lngParam = urlSearchParams.get("longitude");
    if (latParam && lngParam) {
      return {
        lat: toFiniteNumber(latParam, DEFAULT_CENTER.lat),
        lng: toFiniteNumber(lngParam, DEFAULT_CENTER.lng),
      };
    }
    return {
      lat: toFiniteNumber(settings?.latitude, DEFAULT_CENTER.lat),
      lng: toFiniteNumber(settings?.longitude, DEFAULT_CENTER.lng),
    };
  }, [urlSearchParams, settings?.latitude, settings?.longitude]);

  const handleChangeMapCenter = useCallback(() => {
    if (map) {
      const c = map.getCenter();
      setCenter({
        latitude: c.lat.toString(),
        longitude: c.lng.toString(),
        distance: map.getZoom()?.toString() || "",
      });
    }
  }, [map]);

  useEffect(() => {
    if (debouncedCenter?.longitude && debouncedCenter?.latitude) {
      setQueryParams(debouncedCenter, false);
    }
  }, [debouncedCenter?.longitude, debouncedCenter?.latitude]);

  useEffect(() => {
    if (!map) return;
    const lat = toFiniteNumber(urlSearchParams.get("latitude"), NaN);
    const lng = toFiniteNumber(urlSearchParams.get("longitude"), NaN);
    if (Number.isFinite(lat) && Number.isFinite(lng)) {
      map.panTo([lng, lat]);
    }
  }, [map, urlSearchParams.get("latitude"), urlSearchParams.get("longitude")]);

  return (
    <Map
      containerStyles={{ width: "100%", height: "100%" }}
      center={mapCenter}
      zoom={urlSearchParams?.has("distance") ? Number(urlSearchParams.get("distance")) : undefined}
      onLoad={(newMap) => setMap(newMap)}
      onCenterChange={handleChangeMapCenter}
    >
      <MarkerCluster
        centerLatitude={debouncedCenter?.latitude}
        centerLongitude={debouncedCenter?.longitude}
      />
    </Map>
  );
};
