using skydiveLogs_api.Domain;
using skydiveLogs_api.DomainBusiness.Interfaces;
using System.Collections.Generic;
using System.Linq;

namespace skydiveLogs_api.DomainBusiness
{
    public class StatsService : IStatsService
    {
        #region Public Constructors

        public StatsService(IJumpService jumpService,
                            IStatsByAircraftService statsByAircraftService,
                            IStatsByDzService statsByDzService,
                            IStatsByGearService statsByGearService,
                            IStatsByJumpTypeService statsByJumpTypeService,
                            IStatsByYearByJumpTypeService statsByYearByJumpTypeService,
                            IStatsByYearService statsByYearService,
                            IStatsForLastMonthByDzService statsForLastMonthByDzService,
                            IStatsForLastMonthByJumpTypeService statsForLastMonthByJumpTypeService,
                            IStatsForLastYearByDzService statsForLastYearByDzService,
                            IStatsForLastYearByJumpTypeService statsForLastYearByJumpTypeService)
        {
            _jumpService = jumpService;
            _statsByAircraftService = statsByAircraftService;
            _statsByDzService = statsByDzService;
            _statsByGearService = statsByGearService;
            _statsByJumpTypeService = statsByJumpTypeService;
            _statsByYearByJumpTypeService = statsByYearByJumpTypeService;
            _statsByYearService = statsByYearService;
            _statsForLastMonthByDzService = statsForLastMonthByDzService;
            _statsForLastMonthByJumpTypeService = statsForLastMonthByJumpTypeService;
            _statsForLastYearByDzService = statsForLastYearByDzService;
            _statsForLastYearByJumpTypeService = statsForLastYearByJumpTypeService;
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Retrieves a simple summary of all statistics.
        /// </summary>
        /// <returns>A SimpleSummary entity containing the simple summary statistics.</returns>
        public SimpleSummary GetSimpleSummary()
        {
            var allJumps = _jumpService.GetAllJumps();
            var results = new SimpleSummary();

            if (allJumps.Any())
            {
                var lastJump = allJumps.OrderByDescending(j => j.JumpDate).First();

                results = new SimpleSummary
                {
                    LastJump = lastJump,
                    TotalJumps = allJumps.Count(),
                    TotalCutaways = allJumps.Where(j => j.WithCutaway).Count()
                };
            }

            return results;
        }

        /// <summary>
        /// Resets all statistics.
        /// </summary>
        public void Reset()
        {
            _statsByAircraftService.Reset();
            _statsByDzService.Reset();
            _statsByGearService.Reset();
            _statsByJumpTypeService.Reset();
            _statsByYearByJumpTypeService.Reset();
            _statsByYearService.Reset();
            _statsForLastMonthByDzService.Reset();
            _statsForLastMonthByJumpTypeService.Reset();
            _statsForLastYearByDzService.Reset();
            _statsForLastYearByJumpTypeService.Reset();
        }

        /// <summary>
        /// Retrieves statistics grouped by aircraft.
        /// </summary>
        /// <returns>A collection of Statistic entities containing aircraft statistics.</returns>
        public IEnumerable<Statistic> GetStatsByAircraft()
        {
            var tmp = _statsByAircraftService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.Aircraft,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics grouped by drop zone.
        /// </summary>
        /// <returns>A collection of Statistic entities containing drop zone statistics.</returns>
        public IEnumerable<Statistic> GetStatsByDz()
        {
            var tmp = _statsByDzService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.DropZone,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics grouped by gear.
        /// </summary>
        /// <returns>A collection of Statistic entities containing gear statistics.</returns>
        public IEnumerable<Statistic> GetStatsByGear()
        {
            var tmp = _statsByGearService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.Gear,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics grouped by jump type.
        /// </summary>
        /// <returns>A collection of Statistic entities containing jump type statistics.</returns>
        public IEnumerable<Statistic> GetStatsByJumpType()
        {
            var tmp = _statsByJumpTypeService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.JumpType,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics grouped by year.
        /// </summary>
        /// <returns>A collection of Statistic entities containing year statistics.</returns>
        public IEnumerable<Statistic> GetStatsByYear()
        {
            var tmp = _statsByYearService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.Year,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics for the last month grouped by drop zone.
        /// </summary>
        /// <returns>A collection of Statistic entities containing last month drop zone statistics.</returns>
        public IEnumerable<Statistic> GetStatsForLastMonthByDz()
        {
            var tmp = _statsForLastMonthByDzService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.DropZone,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics for the last month grouped by jump type.
        /// </summary>
        /// <returns>A collection of Statistic entities containing last month jump type statistics.</returns>
        public IEnumerable<Statistic> GetStatsForLastMonthByJumpType()
        {
            var tmp = _statsForLastMonthByJumpTypeService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.JumpType,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics for the last year grouped by drop zone.
        /// </summary>
        /// <returns>A collection of Statistic entities containing last year drop zone statistics.</returns>
        public IEnumerable<Statistic> GetStatsForLastYearByDz()
        {
            var tmp = _statsForLastYearByDzService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.DropZone,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics for the last year grouped by jump type.
        /// </summary>
        /// <returns>A collection of Statistic entities containing last year jump type statistics.</returns>
        public IEnumerable<Statistic> GetStatsForLastYearByJumpType()
        {
            var tmp = _statsForLastYearByJumpTypeService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.JumpType,
                Nb = a.Nb
            })];
        }

        /// <summary>
        /// Retrieves statistics by year grouped with jump type.
        /// </summary>
        /// <returns>A collection of Statistic entities containing yearly jump type statistics.</returns>
        public IEnumerable<Statistic> GetStatsByYearByJumpType()
        {
            var tmp = _statsByYearByJumpTypeService.GetStats();
            return [.. tmp.Select(a => new Statistic
            {
                Label = a.Year,
                Label2 = a.JumpType,
                Nb = a.Nb
            })];
        }

        #endregion Public Methods

        #region Private Fields

        private readonly IJumpService _jumpService;
        private readonly IStatsByAircraftService _statsByAircraftService;
        private readonly IStatsByDzService _statsByDzService;
        private readonly IStatsByGearService _statsByGearService;
        private readonly IStatsByJumpTypeService _statsByJumpTypeService;
        private readonly IStatsByYearByJumpTypeService _statsByYearByJumpTypeService;
        private readonly IStatsByYearService _statsByYearService;
        private readonly IStatsForLastMonthByDzService _statsForLastMonthByDzService;
        private readonly IStatsForLastMonthByJumpTypeService _statsForLastMonthByJumpTypeService;
        private readonly IStatsForLastYearByDzService _statsForLastYearByDzService;
        private readonly IStatsForLastYearByJumpTypeService _statsForLastYearByJumpTypeService;

        #endregion Private Fields
    }
}
