/**
 * @ai-summary Hook to enrich Google Maps search results with community station data
 */

import { useMemo } from 'react';
import { Station } from '../types/stations.types';
import { CommunityStation } from '../types/community-stations.types';
import { useApprovedNearbyStations } from './useCommunityStations';
import { calculateDistance } from '../utils/distance';

/**
 * Community-verified data for a station
 */
export interface CommunityStationData {
  /** Whether the station has 93 octane fuel */
  has93Octane: boolean;
  /** Whether the 93 octane is ethanol free */
  has93OctaneEthanolFree: boolean;
  /** Whether this data comes from approved community submissions */
  isVerified: boolean;
  /** When this community data was last verified */
  verifiedAt?: string;
  /** The community station ID for reference */
  communityStationId?: string;
}

/**
 * Station enriched with community verification data
 */
export interface EnrichedStation extends Station {
  /** Community verification data if available */
  communityData?: CommunityStationData;
}

/**
 * Normalize an address for comparison
 * Removes extra whitespace and converts to lowercase
 */
function normalizeAddress(address: string): string {
  return address
    .toLowerCase()
    .trim()
    .replace(/\s+/g, ' ')
    .replace(/[,]/g, '');
}

/**
 * Check if a search result matches a community station
 * Uses multiple strategies: address matching and distance threshold
 */
function matchesStation(
  searchResult: Station,
  communityStation: CommunityStation,
  matchDistanceThresholdMeters: number = 50
): boolean {
  // Strategy 1: Compare normalized addresses
  const normalizedSearchAddress = normalizeAddress(searchResult.address);
  const normalizedCommunityAddress = normalizeAddress(communityStation.address);

  if (normalizedSearchAddress === normalizedCommunityAddress) {
    return true;
  }

  // Strategy 2: Check if addresses contain common elements
  const searchParts = normalizedSearchAddress.split(' ');
  const communityParts = normalizedCommunityAddress.split(' ');

  // If both have street numbers and they don't match, not the same station
  const searchStreetNum = searchParts[0];
  const communityStreetNum = communityParts[0];
  if (
    searchStreetNum &&
    communityStreetNum &&
    /^\d+$/.test(searchStreetNum) &&
    /^\d+$/.test(communityStreetNum)
  ) {
    if (searchStreetNum !== communityStreetNum) {
      return false;
    }
  }

  // Strategy 3: Use distance threshold as a final check
  const distance = calculateDistance(
    searchResult.latitude,
    searchResult.longitude,
    communityStation.latitude,
    communityStation.longitude
  );

  return distance <= matchDistanceThresholdMeters;
}

/**
 * Enrich search results with community station verification data
 *
 * @param searchResults - Gas stations from Google Maps search
 * @param latitude - User's current latitude (or null if unavailable)
 * @param longitude - User's current longitude (or null if unavailable)
 * @param radiusMeters - Search radius for community stations (default: 5000m)
 * @returns Object containing enriched stations, loading state, and community data map
 */
export function useEnrichedStations(
  searchResults: Station[],
  latitude: number | null,
  longitude: number | null,
  radiusMeters: number = 5000
): {
  enrichedStations: EnrichedStation[];
  isLoading: boolean;
  communityStationsMap: Map<string, CommunityStationData>;
} {
  // Fetch approved nearby community stations
  const { data: communityStations = [], isLoading } = useApprovedNearbyStations(
    latitude,
    longitude,
    radiusMeters
  );

  // Enrich search results with community data
  const result = useMemo(() => {
    // If we don't have coordinates or no search results, return unchanged
    if (latitude === null || longitude === null || searchResults.length === 0) {
      return {
        enrichedStations: searchResults,
        communityStationsMap: new Map(),
      };
    }

    // Create a map of community data indexed by placeId and address
    const communityStationsMap = new Map<string, CommunityStationData>();

    communityStations.forEach((communityStation: CommunityStation) => {
      const data: CommunityStationData = {
        has93Octane: communityStation.has93Octane,
        has93OctaneEthanolFree: communityStation.has93OctaneEthanolFree,
        isVerified: communityStation.status === 'approved',
        verifiedAt: communityStation.reviewedAt,
        communityStationId: communityStation.id,
      };

      // Store by normalized address as primary key
      const normalizedAddress = normalizeAddress(communityStation.address);
      communityStationsMap.set(normalizedAddress, data);
    });

    // Enrich each search result
    const enrichedStations: EnrichedStation[] = searchResults.map(
      (station: Station) => {
        // Try to find a matching community station
        const matchingCommunity = communityStations.find((community) =>
          matchesStation(station, community)
        );

        if (matchingCommunity) {
          return {
            ...station,
            communityData: {
              has93Octane: matchingCommunity.has93Octane,
              has93OctaneEthanolFree: matchingCommunity.has93OctaneEthanolFree,
              isVerified: matchingCommunity.status === 'approved',
              verifiedAt: matchingCommunity.reviewedAt,
              communityStationId: matchingCommunity.id,
            },
          };
        }

        return station;
      }
    );

    return {
      enrichedStations,
      communityStationsMap,
    };
  }, [searchResults, communityStations, latitude, longitude]);

  return {
    enrichedStations: result.enrichedStations,
    isLoading,
    communityStationsMap: result.communityStationsMap,
  };
}
