interface Coordinates {
  lat: number;
  lon: number;
}

interface DistanceResult {
  distance: number;
  duration: number;
}

export class DistanceCalculator {
  private static readonly OSRM_API = 'https://router.project-osrm.org/route/v1/driving';

  static async geocodeAddress(address: string): Promise<Coordinates | null> {
    try {
      const nominatimUrl = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(address)}&limit=1`;
      
      const response = await fetch(nominatimUrl, {
        headers: {
          'User-Agent': 'SaveTheMoment-Atlas/1.0',
        },
      });

      if (!response.ok) {
        throw new Error(`Geocoding failed: ${response.statusText}`);
      }

      const data = await response.json();

      if (!data || data.length === 0) {
        console.warn(`No results found for address: ${address}`);
        return null;
      }

      return {
        lat: parseFloat(data[0].lat),
        lon: parseFloat(data[0].lon),
      };
    } catch (error) {
      console.error('Geocoding error:', error);
      return null;
    }
  }

  static async calculateDistance(
    fromAddress: string,
    toAddress: string
  ): Promise<DistanceResult | null> {
    try {
      const fromCoords = await this.geocodeAddress(fromAddress);
      const toCoords = await this.geocodeAddress(toAddress);

      if (!fromCoords || !toCoords) {
        console.error('Failed to geocode one or both addresses');
        return null;
      }

      const url = `${this.OSRM_API}/${fromCoords.lon},${fromCoords.lat};${toCoords.lon},${toCoords.lat}?overview=false`;

      const response = await fetch(url);

      if (!response.ok) {
        throw new Error(`OSRM API failed: ${response.statusText}`);
      }

      const data = await response.json();

      if (!data.routes || data.routes.length === 0) {
        console.error('No route found');
        return null;
      }

      const route = data.routes[0];
      
      return {
        distance: Math.round(route.distance / 1000 * 100) / 100,
        duration: Math.round(route.duration / 60),
      };
    } catch (error) {
      console.error('Distance calculation error:', error);
      return null;
    }
  }

  static formatAddress(address: string, zip: string, city: string): string {
    return `${address}, ${zip} ${city}`.trim();
  }
}
