using IceCreamShopBusinessLogic.OfficePackage;
using IceCreamShopBusinessLogic.OfficePackage.HelperModels;
using IceCreamShopContracts.BindingModels;
using IceCreamShopContracts.BusinessLogicsContracts;
using IceCreamShopContracts.SearchModels;
using IceCreamShopContracts.StoragesContracts;
using IceCreamShopContracts.ViewModels;

namespace IceCreamShopBusinessLogic.BusinessLogics
{
    public class ReportLogic : IReportLogic
    {
        private readonly IIceCreamStorage _iceCreamStorage;

        private readonly IOrderStorage _orderStorage;

        private readonly IShopStorage _shopStorage;

        private readonly AbstractSaveToExcel _saveToExcel;

        private readonly AbstractSaveToWord _saveToWord;

        private readonly AbstractSaveToPdf _saveToPdf;

        public ReportLogic(IIceCreamStorage iceCreamStorage, IComponentStorage componentStorage, IOrderStorage orderStorage, IShopStorage shopStorage,
            AbstractSaveToExcel saveToExcel, AbstractSaveToWord saveToWord, AbstractSaveToPdf saveToPdf)
        {
            _iceCreamStorage = iceCreamStorage;
            _orderStorage = orderStorage;
            _shopStorage = shopStorage;

            _saveToExcel = saveToExcel;
            _saveToWord = saveToWord;
            _saveToPdf = saveToPdf;
        }
 
        public List<ReportIceCreamComponentViewModel> GetIceCreamComponents()
        {
            var iceCreams = _iceCreamStorage.GetFullList();

            var list = new List<ReportIceCreamComponentViewModel>();

            foreach (var iceCream in iceCreams)
            {
                var record = new ReportIceCreamComponentViewModel
                {
                    IceCreamName = iceCream.IceCreamName,
                    Components = new List<(string Component, int Count)>(),
                    TotalCount = 0,
                };
                foreach (var component in iceCream.IceCreamComponents)
                {
                    record.Components.Add(new(component.Value.Item1.ComponentName, component.Value.Item2));
                    record.TotalCount += component.Value.Item2;
                }

                list.Add(record);
            }

            return list;
        }

        public List<ReportShopIceCreamViewModel> GetShopIceCreams()
        {
            var shops = _shopStorage.GetFullList();

            var list = new List<ReportShopIceCreamViewModel>();

            foreach (var shop in shops)
            {
                var record = new ReportShopIceCreamViewModel
                {
                    ShopName = shop.ShopName,
                    IceCreams = new List<(string IceCream, int Count)>(),
                    TotalCount = 0,
                };
                foreach (var iceCream in shop.ShopIceCreams)
                {
                    record.IceCreams.Add(new(iceCream.Value.Item1.IceCreamName, iceCream.Value.Item2));
                    record.TotalCount += iceCream.Value.Item2;
                }

                list.Add(record);
            }

            return list;
        }

        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,
                        IceCreamName = x.IceCreamName,
                        OrderStatus = x.Status.ToString(),
                        Sum = x.Sum
                    })
                    .ToList();
        }

        public List<ReportOrdersByDateViewModel> GetGroupedByDateOrders()
        {
            return _orderStorage.GetFullList().GroupBy(x => x.DateCreate.Date)
                     .Select(x => new ReportOrdersByDateViewModel
                     {
                         Date = x.Key,
                         Count = x.Count(),
                         Sum = x.Sum(y => y.Sum)
                     })
                     .ToList();
        }

        public void SaveIceCreamsToWordFile(ReportBindingModel model)
        {
            _saveToWord.CreateDoc(new WordInfo
            {
                FileName = model.FileName,
                Title = "Список мороженого",
                IceCreams = _iceCreamStorage.GetFullList()
            });
        }

        public void SaveShopsToWordFile(ReportBindingModel model)
        {
            _saveToWord.CreateShopsTable(new WordInfo
            {
                FileName = model.FileName,
                Title = "Список магазинов",
                Shops = _shopStorage.GetFullList()
            });
        }

        public void SaveIceCreamComponentToExcelFile(ReportBindingModel model)
        {
            _saveToExcel.CreateReport(new ExcelInfo
            {
                FileName = model.FileName,
                Title = "Список мороженого",
                IceCreamComponents = GetIceCreamComponents()
            });
        }

        public void SaveShopIceCreamToExcelFile(ReportBindingModel model)
        {
            _saveToExcel.CreateShopReport(new ExcelInfo
            {
                FileName = model.FileName,
                Title = "Загруженность магазинов",
                ShopIceCreams = GetShopIceCreams()
            });
        }

        public void SaveOrdersToPdfFile(ReportBindingModel model)
        {
            _saveToPdf.CreateDoc(new PdfInfo
            {
                FileName = model.FileName,
                Title = "Список заказов",
                DateFrom = model.DateFrom!.Value,
                DateTo = model.DateTo!.Value,
                Orders = GetOrders(model)
            });
        }

        public void SaveGroupedOrdersToPdfFile(ReportBindingModel model)
        {
            _saveToPdf.CreateDocWithGroupedOrders(new PdfInfo
            {
                FileName = model.FileName,
                Title = "Заказы по датам",
                GroupedOrders = GetGroupedByDateOrders()
            });
        }
    }
}