using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using RestaurantAPI.Models; public class GooglePlacesService { private readonly HttpClient _httpClient; private readonly string _apiKey; public GooglePlacesService(HttpClient httpClient, IConfiguration configuration) { _httpClient = httpClient; _apiKey = configuration["GooglePlaces:ApiKey"]; } public async Task> GetRestaurantsAsync( double latitude, double longitude, int radius = 5000, int? minPrice = null, int? maxPrice = null) { // Build the Nearby Search URL string url = $"https://maps.googleapis.com/maps/api/place/nearbysearch/json" + $"?location={latitude},{longitude}" + $"&radius={radius}" + $"&type=restaurant" + $"&key={_apiKey}"; // Append optional minPrice/maxPrice if (minPrice.HasValue) url += $"&minprice={minPrice.Value}"; if (maxPrice.HasValue) url += $"&maxprice={maxPrice.Value}"; // Call Google Places Nearby Search HttpResponseMessage response = await _httpClient.GetAsync(url); string json = await response.Content.ReadAsStringAsync(); Console.WriteLine("Google API Response: " + json); // Return empty list if the request failed if (!response.IsSuccessStatusCode) { Console.WriteLine("Error: " + response.StatusCode); return new List(); } // Deserialize the JSON into our GooglePlacesResponse model var data = JsonSerializer.Deserialize( json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true } ); var restaurants = new List(); if (data?.Results != null) { foreach (var place in data.Results) { // Skip places missing a name or location if (string.IsNullOrEmpty(place.Name) || place.Geometry?.Location == null) { Console.WriteLine($"Skipping a place due to missing name or location. Name: {place.Name}"); continue; } // Use Google's Place ID for unique identification string placeId = place.PlaceId ?? Guid.NewGuid().ToString(); // Extract the first photo reference if available string firstPhotoReference = place.Photos?.FirstOrDefault()?.PhotoReference; // Generate the Google Maps URL string googleMapsUrl = $"https://www.google.com/maps/place/?q=place_id:{placeId}"; // Create a Restaurant object with all necessary data restaurants.Add(new Restaurant { Id = placeId, PlaceId = placeId, Name = place.Name, Type = place.PriceLevel switch { 1 => "Fast Food", 2 => "Casual Dining", 3 => "Fine Dining", 4 => "Luxury Dining", _ => "Unknown" }, Latitude = place.Geometry.Location.Lat, Longitude = place.Geometry.Location.Lng, Rating = place.Rating, PriceLevel = place.PriceLevel, PhotoReference = firstPhotoReference, GoogleMapsUrl = googleMapsUrl }); } } return restaurants; } } // -------------------- Google Places Response Models -------------------- public class GooglePlacesResponse { [JsonPropertyName("results")] public List Results { get; set; } } public class GooglePlace { [JsonPropertyName("place_id")] public string PlaceId { get; set; } [JsonPropertyName("name")] public string Name { get; set; } public GoogleGeometry Geometry { get; set; } [JsonPropertyName("rating")] public double Rating { get; set; } [JsonPropertyName("price_level")] public int? PriceLevel { get; set; } [JsonPropertyName("photos")] public List Photos { get; set; } } public class GoogleGeometry { public GoogleLocation Location { get; set; } } public class GoogleLocation { [JsonPropertyName("lat")] public double Lat { get; set; } [JsonPropertyName("lng")] public double Lng { get; set; } } public class GooglePhoto { [JsonPropertyName("photo_reference")] public string PhotoReference { get; set; } }