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

namespace skydiveLogs_api.DomainBusiness
{
    public class TunnelFlightService : ITunnelFlightService
    {
        #region Public Constructors

        public TunnelFlightService(IJumpTypeService jumpTypeService,
                                   ITunnelFlightRepository tunnelFlightRepository,
                                   IDropZoneService dropZoneService,
                                   IIdentityService identityService)
        {
            _dropZoneService = dropZoneService;
            _jumpTypeService = jumpTypeService;
            _identityService = identityService;
            _tunnelFlightRepository = tunnelFlightRepository;
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Retrieves all tunnel flights.
        /// </summary>
        /// <returns>A collection of TunnelFlight entities containing all tunnel flights.</returns>
        public IEnumerable<TunnelFlight> GetAllTunnelFlights()
        {
            return _tunnelFlightRepository.GetAll(_identityService.ConnectedUser);
        }

        /// <summary>
        /// Retrieves a tunnel flight by its ID.
        /// </summary>
        /// <param name="id">The tunnel flight ID to retrieve.</param>
        /// <returns>A TunnelFlight entity containing the tunnel flight details.</returns>
        public TunnelFlight GetTunnelFlightById(int id)
        {
            return _tunnelFlightRepository.GetById(id);
        }

        /// <summary>
        /// Retrieves the total count of tunnel flights.
        /// </summary>
        /// <returns>The total number of tunnel flights.</returns>
        public int GetTunnelFlightCount()
        {
            return _tunnelFlightRepository.GetCount(_identityService.ConnectedUser);
        }

        /// <summary>
        /// Retrieves a range of tunnel flights with pagination.
        /// </summary>
        /// <param name="beginIndex">The starting index for pagination.</param>
        /// <param name="endIndex">The ending index for pagination.</param>
        /// <returns>A collection of TunnelFlight entities containing the requested range.</returns>
        public IEnumerable<TunnelFlight> GetTunnelFlightsByIndexes(int beginIndex, int endIndex)
        {
            return _tunnelFlightRepository.GetBetweenIndex(_identityService.ConnectedUser, beginIndex, endIndex);
        }

        /// <summary>
        /// Retrieves tunnel flights grouped by month within a date range.
        /// </summary>
        /// <param name="beginDate">The start date for grouping.</param>
        /// <param name="endDate">The end date for grouping.</param>
        /// <returns>A collection of Statistic entities grouped by month.</returns>
        public IEnumerable<Statistic> GetTunnelFlightGroupByMonth(string beginDate, string endDate)
        {
            var convertedBeginDate = Convert.ToDateTime(beginDate);
            var convertedEndDate = Convert.ToDateTime(endDate);

            var allTunnelFlights = _tunnelFlightRepository.GetBetweenDate(_identityService.ConnectedUser, convertedBeginDate, convertedEndDate);
            var results = Enumerable.Empty<Statistic>();

            if (allTunnelFlights.Any())
            {
                results = allTunnelFlights.GroupBy(j => new { FlightDate = j.FlightDate.ToString("yy-MM"), j.JumpType },
                                                   j => j,
                                                   (groupby, tunnelFlights) => new Statistic
                                                   {
                                                       Label = groupby.FlightDate,
                                                       Label2 = groupby.JumpType.Name,
                                                       Nb = tunnelFlights.Sum(t => t.NbMinutes)
                                                   })
                                           .ToList();
            }

            return results;
        }
        /// <summary>
        /// Retrieves tunnel flights filtered by date range.
        /// </summary>
        /// <param name="beginDate">The start date for filtering.</param>
        /// <param name="endDate">The end date for filtering.</param>
        /// <returns>A collection of TunnelFlight entities filtered by the specified date range.</returns>
        public IEnumerable<TunnelFlight> GetTunnelFlightByDates(string beginDate, string endDate)
        {
            var convertedBeginDate = Convert.ToDateTime(beginDate);
            var convertedEndDate = Convert.ToDateTime(endDate);

            return _tunnelFlightRepository.GetBetweenDate(_identityService.ConnectedUser, convertedBeginDate, convertedEndDate);
        }

        /// <summary>
        /// Adds a new tunnel flight to the system.
        /// </summary>
        /// <param name="tunnelId">The tunnel ID to add the flight to.</param>
        /// <param name="jumpTypeId">The jump type ID for the flight.</param>
        /// <param name="newFlight">TunnelFlight entity containing the new flight data.</param>
        public void AddNewFlight(int tunnelId, int jumpTypeId, TunnelFlight newFlight)
        {
            var tmp = _dropZoneService.GetDzById(tunnelId);
            var selectedTunnel = new Tunnel
            {
                Id = tmp.Id,
                Name = tmp.Name,
                Website = tmp.Website,
                Address = tmp.Address,
                Email = tmp.Email,
                Latitude = tmp.Latitude,
                Longitude = tmp.Longitude
            };

            var selectedJumpType = _jumpTypeService.GetJumpTypeById(jumpTypeId);

            newFlight.Tunnel = selectedTunnel;
            newFlight.JumpType = selectedJumpType;
            _tunnelFlightRepository.Add(newFlight);
        }

        /// <summary>
        /// Deletes a tunnel flight by its ID.
        /// </summary>
        /// <param name="id">The tunnel flight ID to delete.</param>
        public void DeleteTunnelFlightById(int id)
        {
            _tunnelFlightRepository.DeleteById(id);
        }

        /// <summary>
        /// Updates an existing tunnel flight.
        /// </summary>
        /// <param name="id">The tunnel flight ID to update.</param>
        /// <param name="updatedTunnelFlight">TunnelFlight entity containing the updated tunnel flight data.</param>
        public void UpdateTunnelFlight(int id, TunnelFlight updatedTunnelFlight)
        {
            var myTunnelFlight = GetTunnelFlightById(id);
            myTunnelFlight.FlightDate = updatedTunnelFlight.FlightDate;
            myTunnelFlight.NbMinutes = updatedTunnelFlight.NbMinutes;
            myTunnelFlight.Notes = updatedTunnelFlight.Notes;

            _tunnelFlightRepository.Update(myTunnelFlight);
        }

        #endregion Public Methods

        #region Private Fields

        private readonly IDropZoneService _dropZoneService;
        private readonly IJumpTypeService _jumpTypeService;
        private readonly ITunnelFlightRepository _tunnelFlightRepository;
        private readonly IIdentityService _identityService;

        #endregion Private Fields
    }
}
