using System.Text.Json; namespace Backend.ServiceHander { public sealed class WeatherService { private static readonly HttpClient Http = new() { DefaultRequestHeaders = { { "User-Agent", "SoftTrader/1.0" } } }; public async Task<(string City, double Latitude, double Longitude)?> GeocodeAsync( string city, CancellationToken cancellationToken = default) { string encoded = Uri.EscapeDataString(city.Trim()); string url = $"https://geocoding-api.open-meteo.com/v1/search?name={encoded}&count=1&language=en"; string json = await Http.GetStringAsync(url, cancellationToken); using var doc = JsonDocument.Parse(json); if (!doc.RootElement.TryGetProperty("results", out var results) || results.GetArrayLength() == 0) return null; var first = results[0]; string name = first.GetProperty("name").GetString() ?? city; double lat = first.GetProperty("latitude").GetDouble(); double lng = first.GetProperty("longitude").GetDouble(); return (name, lat, lng); } public async Task GetCurrentWeatherAsync( double latitude, double longitude, CancellationToken cancellationToken = default) { string url = $"https://api.open-meteo.com/v1/forecast" + $"?latitude={latitude}&longitude={longitude}" + $"¤t=temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m" + $"&temperature_unit=fahrenheit" + $"&wind_speed_unit=mph"; string json = await Http.GetStringAsync(url, cancellationToken); using var doc = JsonDocument.Parse(json); if (!doc.RootElement.TryGetProperty("current", out var current)) return null; return new WeatherResult { TemperatureF = current.GetProperty("temperature_2m").GetDouble(), HumidityPercent = current.GetProperty("relative_humidity_2m").GetDouble(), WeatherCode = current.GetProperty("weather_code").GetInt32(), WindSpeedMph = current.GetProperty("wind_speed_10m").GetDouble() }; } } public sealed class WeatherResult { public double TemperatureF { get; init; } public double HumidityPercent { get; init; } public int WeatherCode { get; init; } public double WindSpeedMph { get; init; } public string Description => WeatherCode switch { 0 => "Clear sky", 1 => "Mainly clear", 2 => "Partly cloudy", 3 => "Overcast", 45 or 48 => "Foggy", 51 or 53 or 55 => "Drizzle", 61 or 63 or 65 => "Rain", 66 or 67 => "Freezing rain", 71 or 73 or 75 => "Snowfall", 77 => "Snow grains", 80 or 81 or 82 => "Rain showers", 85 or 86 => "Snow showers", 95 => "Thunderstorm", 96 or 99 => "Thunderstorm with hail", _ => "Unknown" }; } }