#nullable enable
namespace Baya.Application.Contracts.Common;

/// <summary>
/// Seam for turning a typed postal address into geographic coordinates. The mock derives a deterministic
/// point around the city centroid with no network call; the real implementation swaps to a Neshan/Google
/// geocoding client behind the same contract. Coordinates are <see cref="decimal"/> (never float) so the
/// EVV distance check (b9) that later consumes them is exact.
/// </summary>
public interface IGeocoder
{
    /// <summary>
    /// Resolves the free-text <paramref name="addressText"/> (within the named <paramref name="cityName"/>
    /// and optional <paramref name="districtName"/>) to coordinates. A low-confidence / unresolvable
    /// address yields a result with <see cref="GeocodeResult.Latitude"/>/<see cref="GeocodeResult.Longitude"/>
    /// left <c>null</c> — the address is still saved, just without a map pin.
    /// </summary>
    ValueTask<GeocodeResult> GeocodeAsync(
        string addressText,
        string cityName,
        string? districtName,
        CancellationToken cancellationToken = default);
}

/// <summary>
/// The outcome of a geocoding attempt. <see cref="Latitude"/>/<see cref="Longitude"/> are <c>null</c> when
/// the provider could not resolve the address with enough confidence.
/// </summary>
public sealed record GeocodeResult(
    decimal? Latitude,
    decimal? Longitude,
    string FormattedAddress,
    double Confidence)
{
    public bool HasCoordinates => Latitude is not null && Longitude is not null;
}
