using DocumentFormat.OpenXml.Office.CustomUI;
using ElectronicsShopBusinessLogic.OfficePackage;
using ElectronicsShopBusinessLogic.OfficePackage.HelperModels;
using ElectronicsShopContracts.BindingModels;
using ElectronicsShopContracts.BusinessLogicContracts;
using ElectronicsShopContracts.SearchModels;
using ElectronicsShopContracts.StorageContracts;
using ElectronicsShopContracts.ViewModels;
using PdfSharp.Pdf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ElectronicsShopBusinessLogic.BusinessLogic
{
    public class ReportEmployeeLogic : IReportEmployeeLogic
    {
        private readonly IProductStorage _productStorage;
        private readonly IPaymeantStorage _paymeantStorage;
        private readonly IOrderStorage _orderStorage;
        private readonly AbstractSaveToPdfEmployee _saveToPdf;
        private readonly AbstractSaveToWordEmployee _saveToWord;
        private readonly AbstractSaveToExcelEmployee _saveToExcel;

        public ReportEmployeeLogic(AbstractSaveToExcelEmployee abstractSaveToExcelEmployee, AbstractSaveToWordEmployee abstractSaveToWordEmployee, 
                                    AbstractSaveToPdfEmployee abstractSaveToPdfEmployee ,IProductStorage productStorage, 
                                    IPaymeantStorage paymeantStorage, IOrderStorage orderStorage) {
            _productStorage = productStorage;
            _paymeantStorage = paymeantStorage;
			_orderStorage = orderStorage;
			_saveToExcel = abstractSaveToExcelEmployee;
            _saveToWord = abstractSaveToWordEmployee;
            _saveToPdf = abstractSaveToPdfEmployee;
        }
        public List<ReportProductInPaymeantsViewModel> GetProducts(ReportProductBindingModel model)
        {
            var paymeants = _paymeantStorage.GetFillteredList(new PaymeantSearchModel {
                DateFrom = model.DateFrom,
                DateTo = model.DateTo,
            });
            List<PaymeantProduct> paymeantProductList = new();

            foreach (var paymeant in paymeants) {
                var order = _orderStorage.GetElement(new OrderSearchModel { ID = paymeant.OrderID }) ?? throw new Exception("Ошибка получения данных");
                foreach (var product in order.ProductList) {
                    paymeantProductList.Add(new(paymeant.ID, product.Key, product.Value.Item2, paymeant.ClientID));
                }
            }

            return CreateProducntInPaymenatList(paymeantProductList);
		}

        public List<ReportProductInPaymeantsViewModel> GetProductsFix(List<ProductViewModel> products) {
            var paymeants = _paymeantStorage.GetFullList();
            List<PaymeantProduct> paymeantProducts = new();

            foreach (var paymeant in paymeants) {
                var order = _orderStorage.GetElement(new OrderSearchModel { ID = paymeant.ID }) ?? throw new Exception("Ошибка получения данных");
                foreach (var product in order.ProductList) {
                    foreach (var fixProduct in products) {
                        if (product.Value.Item1.ID == fixProduct.ID) {
                            paymeantProducts.Add(new(paymeant.ID, product.Key, product.Value.Item2, paymeant.ClientID));
                        }
                    }
                }
            }

            return CreateProducntInPaymenatList(paymeantProducts);
        }

        public List<ReportProductInPaymeantsViewModel> CreateProducntInPaymenatList(List<PaymeantProduct> paymeantProducts) {
            paymeantProducts.OrderBy(x => x.ProductID);

            List<ReportProductInPaymeantsViewModel> ansProductsList = new();
            List<string> productNames = new();

            foreach (var pp in paymeantProducts) {
                var product = _productStorage.GetElement(new ProductSearchModel { ID = pp.ProductID })
                                                            ?? throw new Exception("Ошибка получения данных");
                if (productNames.Contains(product.ProductName) == false) {
                    productNames.Add(product.ProductName);

                    // создаем запись
                    var record = new ReportProductInPaymeantsViewModel {
                        ProductName = product.ProductName,
                        Values = new(),
                        Total = 0
                    };
                    ansProductsList.Add(record);
                }

                // Ищем запись и вносим изменения
                int index = ansProductsList.IndexOf(ansProductsList.First(x => x.ProductName == product.ProductName));

                var paymeant = _paymeantStorage.GetElement(new PaymeantSearchModel { ID = pp.PaymeantID })
                                                             ?? throw new Exception("Ошибка получения данных");

                ansProductsList[index].Values.Add(new(pp.PaymeantID, pp.Count, paymeant.PayOption.ToString(), product.Price * pp.Count, pp.ClientID));
                ansProductsList[index].Total++;

            }
            return ansProductsList;
        }

        public byte[]? SaveProductsToExcelFile(List<ProductViewModel> products)
        {
            var document = _saveToExcel.CreateReport(new ExcelInfoEmployee
            {
                Title = "Список оплат электротоваров",
                ListProduct = GetProductsFix(products)
            });
            return document;
        }

		public PdfDocument SaveProductsToPdfFile(ReportProductBindingModel model) {
            var document = _saveToPdf.CreateDoc(new PdfInfoEmployee {
                Title = "Список оплат электротоваров",
                DateFrom = model.DateFrom,
                DateTo = model.DateTo,
                ListProduct = GetProducts(model),
                FileName = "Report"
            });

            return document;
		}

		public byte[]? SaveProductsToWordFile(List<ProductViewModel> products)
        {
            var document = _saveToWord.CreateDoc(new WordInfoEmployee {
                Title = "Список оплат электротоваров",
                ListProduct = GetProductsFix(products)
            });
            return document;
        }
	}
}