#nullable enable
using Baya.Application.Contracts.Persistence;
using Baya.Application.Models.Booking;
using Baya.Domain.Entities.Booking;
using Baya.Infrastructure.Persistence.Repositories.Common;
using Microsoft.EntityFrameworkCore;

namespace Baya.Infrastructure.Persistence.Repositories;

internal sealed class CancellationPolicyRepository : BaseAsyncRepository<CancellationPolicy>, ICancellationPolicyRepository
{
    public CancellationPolicyRepository(ApplicationDbContext dbContext) : base(dbContext)
    {
    }

    public async Task<IReadOnlyList<CancellationPolicy>> GetActiveForActorAsync(string appliesTo, CancellationToken cancellationToken)
        => await TableNoTracking
            .Where(p => p.AppliesTo == appliesTo && p.IsActive)
            // Tighter (bounded) buckets first so the resolver prefers the most specific covering tier.
            .OrderBy(p => p.HoursBeforeStartMin ?? int.MinValue)
            .ToListAsync(cancellationToken);

    public async Task<IReadOnlyList<CancellationPolicyDto>> ListAsync(CancellationToken cancellationToken)
        => await TableNoTracking
            .OrderBy(p => p.AppliesTo).ThenBy(p => p.Code)
            .Select(p => new CancellationPolicyDto(
                p.Id, p.Code, p.AppliesTo, p.HoursBeforeStartMin, p.HoursBeforeStartMax,
                p.RefundPercentage, p.FeeAmountIrr.ToString(), p.FeeRate, p.IsActive))
            .ToListAsync(cancellationToken);

    public Task<CancellationPolicy?> GetTrackedByCodeAsync(string code, CancellationToken cancellationToken)
        => Table.FirstOrDefaultAsync(p => p.Code == code, cancellationToken);

    public Task AddAsync(CancellationPolicy policy, CancellationToken cancellationToken)
        => base.AddAsync(policy);
}
