#nullable enable
using Baya.Application.Models.Geography;
using Baya.Domain.Entities.Geography;

namespace Baya.Application.Contracts.Persistence;

/// <summary>
/// The province/city/district reference hierarchy: public active-only lookups for the cascading dropdowns
/// plus tracked getters/adds for the admin CRUD. Reads are projected + no-tracking; callers cache them.
/// </summary>
public interface IGeoRepository
{
    Task<IReadOnlyList<ProvinceDto>> ListActiveProvincesAsync(CancellationToken cancellationToken);

    /// <summary>Active cities under an active province, ordered — empty if the province is inactive/absent.</summary>
    Task<IReadOnlyList<CityDto>> ListActiveCitiesAsync(long provinceId, CancellationToken cancellationToken);

    /// <summary>Active districts under an active city, ordered — empty is valid (whole-city-only city).</summary>
    Task<IReadOnlyList<DistrictDto>> ListActiveDistrictsAsync(long cityId, CancellationToken cancellationToken);

    /// <summary>The full active province→city→district tree in one payload for the dropdown.</summary>
    Task<IReadOnlyList<ProvinceTreeDto>> GetActiveTreeAsync(CancellationToken cancellationToken);

    // Admin: tracked lookups (include inactive, exclude soft-deleted) for edit/toggle.
    Task<Province?> GetProvinceAsync(long id, CancellationToken cancellationToken);
    Task<City?> GetCityAsync(long id, CancellationToken cancellationToken);
    Task<District?> GetDistrictAsync(long id, CancellationToken cancellationToken);

    Task AddProvinceAsync(Province province, CancellationToken cancellationToken);
    Task AddCityAsync(City city, CancellationToken cancellationToken);
    Task AddDistrictAsync(District district, CancellationToken cancellationToken);

    Task<bool> ProvinceExistsAsync(long provinceId, CancellationToken cancellationToken);

    /// <summary>True when the city exists, is active, and its province is active.</summary>
    Task<bool> IsCityActiveAsync(long cityId, CancellationToken cancellationToken);

    /// <summary>True when the district exists, is active, belongs to <paramref name="cityId"/>, and that
    /// city (and its province) are active.</summary>
    Task<bool> IsDistrictInActiveCityAsync(long districtId, long cityId, CancellationToken cancellationToken);
}
