import { eventQueries } from "@/entities/event";
import type { Event } from "@/entities/event";
import type { EventPlace } from "@/entities/place";
import { isEventPast } from "@/features/events-list";
import { EbaliMap, useMapState } from "@/features/map";
import { useQuery } from "@tanstack/react-query";
import { useMap } from "@vis.gl/react-google-maps";
import { useEffect, useMemo, useRef } from "react";
import { useSearchParams } from "react-router";

interface PlaceWithEvents extends EventPlace {
  events: Omit<Event, "place">[];
}

export const HomeMap: React.FC = () => {
  const map = useMap();
  const [searchParams] = useSearchParams();
  const hasInitialized = useRef(false);

  const { data: events } = useQuery(eventQueries.list());
  const { selectEventPlace, setEventLayer } = useMapState();

  const approvedEvents = useMemo(
    () =>
      (events ?? ([] as Event[])).filter(
        (event) => event.status === "approved" && !isEventPast(event),
      ),
    [events],
  );

  const placesWithEvents = useMemo(
    () =>
      approvedEvents.reduce<Record<number, PlaceWithEvents>>((acc, event) => {
        const { place } = event;
        const placeId = place.id;
        const { place: _, ...eventWithoutPlace } = event;

        if (!acc[placeId]) {
          acc[placeId] = {
            ...place,
            events: [],
          };
        }

        acc[placeId].events.push(eventWithoutPlace as Omit<Event, "place">);
        return acc;
      }, {}),
    [approvedEvents],
  );

  useEffect(() => {
    setEventLayer(placesWithEvents, approvedEvents);
  }, [approvedEvents, placesWithEvents, setEventLayer]);

  useEffect(() => {
    if (!map || hasInitialized.current) {
      return;
    }

    const places = Object.values(placesWithEvents);
    if (places.length === 0) {
      return;
    }

    const lat = searchParams.get("lat");
    const lng = searchParams.get("lng");

    if (
      lat &&
      lng &&
      !Number.isNaN(Number(lat)) &&
      !Number.isNaN(Number(lng))
    ) {
      map.panTo({ lat: Number(lat), lng: Number(lng) });
      map.setZoom(16);
      const foundPlace = places.find((place) => {
        const coords = place.geometry.coordinates[0];
        return coords?.lat === +lat && coords?.lng === +lng;
      });
      if (foundPlace) {
        selectEventPlace(foundPlace.id);
      }
    }
    hasInitialized.current = true;
  }, [map, placesWithEvents, searchParams, selectEventPlace]);

  return (
    <EbaliMap
      className="h-full relative"
      requireTwoFingerScroll={false}
      layersOpacity={0.4}
    />
  );
};

Graph