using Baya.Application.Contracts.Persistence;
using Baya.Application.Models.Common;
using Baya.Application.Models.Geography;
using Baya.Domain.Entities.Geography;
using Baya.Infrastructure.Persistence.Repositories.Common;
using Microsoft.EntityFrameworkCore;

namespace Baya.Infrastructure.Persistence.Repositories;

internal sealed class NurseServiceAreaRepository : BaseAsyncRepository<NurseServiceArea>, INurseServiceAreaRepository
{
    public NurseServiceAreaRepository(ApplicationDbContext dbContext) : base(dbContext)
    {
    }

    public Task AddAsync(NurseServiceArea area, CancellationToken cancellationToken)
        => base.AddAsync(area);

    public Task<NurseServiceArea> GetOwnedAsync(long id, long nurseId, CancellationToken cancellationToken)
        => Table.FirstOrDefaultAsync(a => a.Id == id && a.NurseId == nurseId, cancellationToken);

    public Task<bool> DuplicateExistsAsync(long nurseId, long cityId, long? districtId, CancellationToken cancellationToken)
        => TableNoTracking.AnyAsync(
            a => a.NurseId == nurseId && a.CityId == cityId && a.DistrictId == districtId,
            cancellationToken);

    public async Task<PagedResult<NurseServiceAreaDto>> ListAsync(long nurseId, int page, int pageSize, CancellationToken cancellationToken)
    {
        var query = TableNoTracking.Where(a => a.NurseId == nurseId);

        var total = await query.CountAsync(cancellationToken);
        var items = await query
            // Whole-city rows (district_id NULL) first, then by id.
            .OrderByDescending(a => a.DistrictId == null)
            .ThenBy(a => a.Id)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .Select(a => new NurseServiceAreaDto(
                a.Id,
                a.CityId,
                a.City.NameFa,
                a.City.NameEn,
                a.DistrictId,
                a.DistrictId == null ? null : a.District.NameFa,
                a.DistrictId == null ? null : a.District.NameEn,
                a.DistrictId == null,
                a.IsActive))
            .ToListAsync(cancellationToken);

        return new PagedResult<NurseServiceAreaDto>(items, total, page, pageSize);
    }
}
