using Managing.Application.Abstractions.Repositories;
using Managing.Domain.Statistics;
using Managing.Infrastructure.Databases.MongoDb;
using Managing.Infrastructure.Databases.MongoDb.Abstractions;
using Managing.Infrastructure.Databases.MongoDb.Collections;

namespace Managing.Infrastructure.Databases;

public class StatisticRepository : IStatisticRepository
{
    private readonly IMongoRepository<BestTraderDto> _bestTrader;
    private readonly IMongoRepository<BadTraderDto> _badTrader;
    private readonly IMongoRepository<TopVolumeTickerDto> _topRepository;
    private readonly IMongoRepository<SpotlighOverviewDto> _spotlightRepository;
    private readonly IMongoRepository<FundingRateDto> _fundingRateRepository;

    public StatisticRepository(
        IMongoRepository<TopVolumeTickerDto> topRepository,
        IMongoRepository<SpotlighOverviewDto> spotlightRepository,
        IMongoRepository<BestTraderDto> bestTrader,
        IMongoRepository<BadTraderDto> badTrader,
        IMongoRepository<FundingRateDto> fundingRateRepository)
    {
        _topRepository = topRepository;
        _spotlightRepository = spotlightRepository;
        _bestTrader = bestTrader;
        _badTrader = badTrader;
        _fundingRateRepository = fundingRateRepository;
    }

    public async Task InsertTopVolumeTicker(TopVolumeTicker topVolumeTicker)
    {
        await _topRepository.InsertOneAsync(MongoMappers.Map(topVolumeTicker));
    }

    public IList<TopVolumeTicker> GetTopVolumeTickers(DateTime date)
    {
        var top = _topRepository.FilterBy(t => date < t.Date);
        return MongoMappers.Map(top);
    }

    public async Task SaveSpotligthtOverview(SpotlightOverview overview)
    {
        await _spotlightRepository.InsertOneAsync(MongoMappers.Map(overview));
    }

    public IList<SpotlightOverview> GetSpotlightOverviews(DateTime date)
    {
        var overviews = _spotlightRepository.FilterBy(t => date < t.DateTime);
        return MongoMappers.Map(overviews);
    }

    public void UpdateSpotlightOverview(SpotlightOverview overview)
    {
        var s = _spotlightRepository.FindOne(o => o.Identifier == overview.Identifier);
        var dto = MongoMappers.Map(overview);
        dto.Id = s.Id;
        _spotlightRepository.Update(dto);
    }

    public List<Trader> GetBestTraders()
    {
        return MongoMappers.Map(_bestTrader.FindAll());
    }

    public void UpdateBestTrader(Trader trader)
    {
        var t = _bestTrader.FindOne(t => t.Address == trader.Address);
        var dto = MongoMappers.Map(trader);
        dto.Id = t.Id;
        _bestTrader.Update(dto);
    }

    public async Task InsertBestTrader(Trader trader)
    {
        await _bestTrader.InsertOneAsync(MongoMappers.Map(trader));
    }

    public async Task RemoveBestTrader(Trader trader)
    {
        await _bestTrader.DeleteOneAsync(t => t.Address == trader.Address);
    }

    public List<Trader> GetBadTraders()
    {
        return MongoMappers.Map(_badTrader.FindAll());
    }

    public void UpdateBadTrader(Trader trader)
    {
        var t = _badTrader.FindOne(t => t.Address == trader.Address);
        var dto = MongoMappers.BadTraderMap(trader);
        dto.Id = t.Id;
        _badTrader.Update(dto);
    }

    public async Task InsertBadTrader(Trader trader)
    {
        await _badTrader.InsertOneAsync(MongoMappers.BadTraderMap(trader));
    }

    public async Task RemoveBadTrader(Trader trader)
    {
        await _badTrader.DeleteOneAsync(t => t.Address == trader.Address);
    }

    public List<FundingRate> GetFundingRates()
    {
        return _fundingRateRepository.FindAll().Select(MongoMappers.Map).ToList();
    }

    public async Task RemoveFundingRate(FundingRate oldRate)
    {
        var rate = _fundingRateRepository.FindOne(r => r.Ticker == oldRate.Ticker && r.Exchange == oldRate.Exchange);
        await _fundingRateRepository.DeleteOneAsync(r => r.Id == rate.Id);
    }

    public async Task InsertFundingRate(FundingRate newRate)
    {
        await _fundingRateRepository.InsertOneAsync(MongoMappers.Map(newRate));
    }

    public void UpdateFundingRate(FundingRate oldRate, FundingRate newRate)
    {
        var f = _fundingRateRepository.FindOne(t => t.Ticker == oldRate.Ticker && t.Exchange == oldRate.Exchange);
        var dto = MongoMappers.Map(newRate);
        dto.Id = f.Id;
        _fundingRateRepository.Update(dto);
    }
}