using Mango.Nop.Core.Repositories;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Events;
using Nop.Data;
using Nop.Plugin.Misc.AuctionPlugin.Domains.Entities;
using Nop.Services.Logging;

namespace Nop.Plugin.Misc.AuctionPlugin.Domains.DataLayer;

public class AuctionBidDbTable : MgDbTableBase<AuctionBid>
{
    public AuctionBidDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings, ILogger logger)
        : base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings, logger)
    {
    }

    public IOrderedQueryable<AuctionBid> GetAllLastBidByAuctionId(int auctionId)
    {
        return GetAllByAuctionId(auctionId)
            .OrderByDescending(x => x.Id)
            .GroupBy(x => x.AuctionId, (_, bids) => bids.FirstOrDefault())
            .OrderByDescending(percentGroup => percentGroup.Id);
    }

    public IOrderedQueryable<AuctionBid> GetLastAuctionBidByProductToAuctionId(int productToAuctionId)
        => GetAllByProductToAuctionId(productToAuctionId).OrderByDescending(x => x.Id);

    public Task<int> GetBidsCountByProductToAuctionIdAsync(int productToAuctionId)
	    => Table.CountAsync(x => x.ProductAuctionMappingId == productToAuctionId);

    public IQueryable<AuctionBid> GetAllByAuctionId(int auctionId)
        => Table.Where(x => x.AuctionId == auctionId);

    public IQueryable<AuctionBid> GetAllByProductToAuctionId(int productToAuctionId)
        => Table.Where(x => x.ProductAuctionMappingId == productToAuctionId);

    public Task<bool> HasBidByProductToAuctionIdAsync(int productToAuctionId)
    {
        return Table.AnyAsync(x => x.ProductAuctionMappingId == productToAuctionId);
    }

    public async Task<AuctionBid> RevertByProductToAuctionIdAsync(int productToAuctionId)
    {
        var lastBid = await GetLastAuctionBidByProductToAuctionId(productToAuctionId).FirstOrDefaultAsync();
        if (lastBid == null)
        {
            await Logger.InformationAsync($"AuctionBidDbTable.RevertByProductToAuctionIdAsync(); (lastBid == null); productToAuction.Id: {productToAuctionId}");
            return null;
        }

        await DeleteAsync(lastBid);
        return await GetLastAuctionBidByProductToAuctionId(productToAuctionId).FirstOrDefaultAsync();
    }

    public async Task<int> DeleteAllByProductToAuctionIdAsync(int productToAuctionId)
    {
        var deletedBids = await DeleteAsync(x => x.ProductAuctionMappingId == productToAuctionId);
        await Logger.InformationAsync($"AuctionBidDbTable.DeleteAllByProductToAuctionIdAsync(); productToAuction.Id: {productToAuctionId}; deletedBids: {deletedBids}");

        return deletedBids;
    }
}