using SoftwareInstallationBusinessLogic.OfficePackage.HelperModels;
using SoftwareInstallationBusinessLogic.OfficePackage;
using SoftwareInstallationContracts.BindingModels;
using SoftwareInstallationContracts.BusinessLogicsContracts;
using SoftwareInstallationContracts.SearchModels;
using SoftwareInstallationContracts.StoragesContracts;
using SoftwareInstallationContracts.ViewModels;

namespace SoftwareInstallationBusinessLogic
{
    public class ReportLogic : IReportLogic
    {
        private readonly IPackageStorage _packageStorage;

        private readonly IOrderStorage _orderStorage;

        private readonly IShopStorage _shopStorage;
        private readonly IComponentStorage _componentStorage;

        private readonly AbstractSaveToExcel _saveToExcel;

        private readonly AbstractSaveToWord _saveToWord;

        private readonly AbstractSaveToPdf _saveToPdf;

        public ReportLogic(IPackageStorage PackageStorage, IOrderStorage orderStorage, IShopStorage shopStorage, IComponentStorage componentStorage,
            AbstractSaveToExcel saveToExcel, AbstractSaveToWord saveToWord, AbstractSaveToPdf saveToPdf)
        {
            _componentStorage = componentStorage;
            _packageStorage = PackageStorage;
            _orderStorage = orderStorage;
            _shopStorage = shopStorage;

            _saveToExcel = saveToExcel;
            _saveToWord = saveToWord;
            _saveToPdf = saveToPdf;
        }

        /// <summary>
        /// Получение списка магазинов с изделиями
        /// </summary>
        /// <returns></returns>
        public List<ReportShopPackagetViewModel> GetShopPackages()
        {
            var shops = _shopStorage.GetFullList();

            var packages = _packageStorage.GetFullList();

            var list = new List<ReportShopPackagetViewModel>();

            foreach (var shop in shops)
            {
                var record = new ReportShopPackagetViewModel
                {
                    ShopName = shop.Name,
                    Packages = new List<Tuple<string, int>>(),
                    TotalCount = 0
                };
                foreach (var package in packages)
                {
                    if (shop.Packages.ContainsKey(package.Id))
                    {
                        record.Packages.Add(new(package.PackageName, shop.Packages[package.Id].Item2));
                        record.TotalCount += shop.Packages[package.Id].Item2;
                    }
                }
                record.Workload = record.TotalCount / (double)shop.MaxCountPackages;
                list.Add(record);
            }

            return list;
        }

        /// <summary>
        /// Получение списка компонент с указанием, в каких изделиях используются
        /// </summary>
        /// <returns></returns>
        public List<ReportPackageComponentViewModel> GetPackageComponent()
        {
            var components = _componentStorage.GetFullList();

            var packages = _packageStorage.GetFullList();

            var list = new List<ReportPackageComponentViewModel>();

            foreach (var package in packages)
            {
                var record = new ReportPackageComponentViewModel
                {
                    PackageName = package.PackageName,
                    Components = new List<Tuple<string, int>>(),
                    TotalCount = 0
                };
                foreach (var component in components)
                {
                    if (package.PackageComponents.ContainsKey(component.Id))
                    {
                        record.Components.Add(new(component.ComponentName, package.PackageComponents[component.Id].Item2));
                        record.TotalCount += package.PackageComponents[component.Id].Item2;
                    }
                }

                list.Add(record);
            }

            return list;
        }

        /// <summary>
        /// Получение списка заказов за определенный период
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public List<ReportOrdersViewModel> GetOrders(ReportBindingModel model)
        {
            return _orderStorage.GetFilteredList(new OrderSearchModel { DateFrom = model.DateFrom, DateTo = model.DateTo })
                    .Select(x => new ReportOrdersViewModel
                    {
                        Id = x.Id,
                        DateCreate = x.DateCreate,
                        PackageName = x.PackageName,
                        OrderStatus = Convert.ToString(x.Status) ?? string.Empty,
                        Sum = x.Sum
                    })
                    .ToList();
        }

        /// <summary>
        /// Получение списка заказов за определенный период
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public List<ReportGroupOrdersViewModel> GetGroupOrders(ReportBindingModel model)
        {
            return _orderStorage.GetFullList()
                .GroupBy(x => x.DateCreate.Date)
                .Select(x => new ReportGroupOrdersViewModel 
                { 
                    Date = x.Key,
                    Count = x.Count(),
                    Sum = x.Sum(y => y.Sum)
                }).ToList();

        }

        /// <summary>
        /// Сохранение магазинов в файл-Word
        /// </summary>
        /// <param name="model"></param>
        public void SaveShopsTableToWordFile(ReportBindingModel model)
        {
            _saveToWord.CreateDocTable(new WordInfoTable
            {
                FileName = model.FileName,
                Title = "Список магазинов",
                Shops = _shopStorage.GetFullList()
            });
        }

        public void SavePackagesToWordFile(ReportBindingModel model)
        {
            _saveToWord.CreateDoc(new WordInfo
            {
                FileName = model.FileName,
                Title = "Список изделий",
                Packages = _packageStorage.GetFullList()
            });
        }



        /// <summary>
        /// Сохранение магазинов с указаеним продуктов в файл-Excel
        /// </summary>
        /// <param name="model"></param>
        public void SaveShopPackageToExcelFile(ReportBindingModel model)
        {
            _saveToExcel.CreateReportShop(new ExcelInfo
            {
                FileName = model.FileName,
                Title = "Список магазинов",
                ShopPackages = GetShopPackages()
            });
        }

        public void SavePackageComponentToExcelFile(ReportBindingModel model)
        {
            _saveToExcel.CreateReportPackage(new ExcelInfoPackage
            {
                FileName = model.FileName,
                Title = "Список изделий по компонентам",
                PackageComponents = GetPackageComponent(),
            });
        }

        /// <summary>
        /// Сохранение заказов в файл-Pdf
        /// </summary>
        /// <param name="model"></param>
        public void SaveGroupOrdersToPdfFile(ReportBindingModel model)
        {
            _saveToPdf.CreateDoc(new PdfInfo
            {
                FileName = model.FileName,
                Title = "Список сгруппированных заказов по датам",
                DateFrom = model.DateFrom!.Value,
                DateTo = model.DateTo!.Value,
                Orders = GetGroupOrders(model)
            });
        }
        /// <summary>
        /// Сохранение заказов в файл-Pdf
        /// </summary>
        /// <param name="model"></param>
        public void SaveOrdersToPdfFile(ReportBindingModel model)
        {
            _saveToPdf.CreateDocOrders(new PdfInfoOrders
            {
                FileName = model.FileName,
                Title = "Список заказов",
                DateFrom = model.DateFrom!.Value,
                DateTo = model.DateTo!.Value,
                Orders = GetOrders(model),
            });
        }

    }
}