import { useEffect, useState } from "react";
import { Platform, StyleSheet } from "react-native";
import MapView, { Marker, PROVIDER_DEFAULT } from "react-native-maps";
import MapViewDirections from "react-native-maps-directions";

import { icons } from "@/constants";
import { useFetch } from "@/lib/fetch";
import {
  calculateDriverTimes,
  calculateRegion,
  generateMarkersFromData,
} from "@/lib/map";
import { useDriverStore, useLocationStore, useServiceStore } from "@/store";
import type { Driver, MarkerData } from "@/types/type";

// react-native-maps sizes itself from a real style object, so give it explicit
// dimensions rather than relying on percentage classNames resolving to 0.
const styles = StyleSheet.create({
  map: { ...StyleSheet.absoluteFillObject, borderRadius: 16 },
});

// "mutedStandard" is an Apple Maps type. Android's MapManager looks the value
// up in a fixed table and unboxes the result into an int, so an unrecognised
// name is a null Integer -> NullPointerException, and the map never draws.
const MAP_TYPE = Platform.OS === "ios" ? "mutedStandard" : "standard";

// showsPointsOfInterest is iOS-only; on Android the same muting is done with a
// style array, so both platforms get the same clean base map.
const MUTED_POI_STYLE = [
  {
    featureType: "poi",
    elementType: "labels",
    stylers: [{ visibility: "off" }],
  },
  {
    featureType: "transit",
    elementType: "labels.icon",
    stylers: [{ visibility: "off" }],
  },
];

export const Map = () => {
  const {
    userLatitude,
    userLongitude,
    destinationLatitude,
    destinationLongitude,
  } = useLocationStore();
  const { service } = useServiceStore();
  const { selectedDriver, setDrivers } = useDriverStore();

  // Online drivers of the selected service near the rider. Falls back to a
  // Beirut center when the rider's position isn't resolved yet so the map
  // still populates instead of sitting empty.
  const lat = userLatitude ?? 33.8938;
  const lng = userLongitude ?? 35.5018;
  const { data: drivers, error } = useFetch<Driver[]>(
    `/(api)/driver/nearby?service=${service}&lat=${lat}&lng=${lng}`,
  );

  const [markers, setMarkers] = useState<MarkerData[]>([]);

  const region = calculateRegion({
    userLatitude,
    userLongitude,
    destinationLatitude,
    destinationLongitude,
  });

  useEffect(() => {
    if (Array.isArray(drivers)) {
      if (!userLatitude || !userLongitude) return;

      const newMarkers = generateMarkersFromData({
        data: drivers,
        userLatitude,
        userLongitude,
      });

      setMarkers(newMarkers);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [drivers, userLatitude, userLongitude]);

  useEffect(() => {
    if (markers.length > 0 && destinationLatitude && destinationLongitude) {
      calculateDriverTimes({
        markers,
        userLatitude,
        userLongitude,
        destinationLatitude,
        destinationLongitude,
        service,
      }).then((driversWithTimes) => {
        setDrivers((driversWithTimes as MarkerData[]) ?? []);
      });
    }
  }, [
    markers,
    destinationLatitude,
    destinationLongitude,
    userLatitude,
    userLongitude,
    setDrivers,
    service,
  ]);

  // The map itself never waits on the driver list or the location fix: drivers
  // are an overlay, and calculateRegion falls back to Beirut without coords.
  // Previously either one failing replaced the whole map with a spinner or an
  // error line, which read as "the map didn't load".
  if (error) console.log("[MAP_DRIVERS]: ", error);

  return (
    <MapView
      provider={PROVIDER_DEFAULT}
      style={styles.map}
      tintColor="black"
      mapType={MAP_TYPE}
      customMapStyle={MUTED_POI_STYLE}
      showsPointsOfInterest={false}
      initialRegion={region}
      showsUserLocation
      userInterfaceStyle="light"
    >
      {markers.map((marker) => (
        <Marker
          key={marker.id}
          coordinate={{
            latitude: marker.latitude,
            longitude: marker.longitude,
          }}
          title={marker.title}
          image={
            selectedDriver === marker.id ? icons.selectedMarker : icons.marker
          }
        />
      ))}

      {userLatitude &&
        userLongitude &&
        destinationLatitude &&
        destinationLongitude && (
          <>
            <Marker
              key="destination"
              coordinate={{
                latitude: destinationLatitude,
                longitude: destinationLongitude,
              }}
              title="Destination"
              image={icons.pin}
            />

            <MapViewDirections
              origin={{
                latitude: userLatitude,
                longitude: userLongitude,
              }}
              destination={{
                latitude: destinationLatitude,
                longitude: destinationLongitude,
              }}
              apikey={process.env.EXPO_PUBLIC_GOOGLE_API_KEY!}
              strokeColor="#0286FF"
              strokeWidth={3}
            />
          </>
        )}
    </MapView>
  );
};
