using CarCenterBusinessLogic.BusinessLogics;
using CarCenterContracts.BusinessLogicsContracts;
using CarCenterContracts.SearchModels;
using CarCenterDataBaseImplement.Models;
using Microsoft.AspNetCore.Mvc;
using CarCenterContracts.ViewModels;
using CarCenterContracts.BindingModels;
using CarCenterDataBaseImplement;
using CarCenterBusinessLogic.MailWorker;
using DocumentFormat.OpenXml.Spreadsheet;


namespace CarCenterRestApi.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class MainController : Controller
    {
        private readonly ILogger _logger;
        private readonly IEmployeeLogic _employee;
        private readonly ISaleLogic _sale;
        private readonly IPreSaleWorkLogic _preSaleWork;
        private readonly ICarLogic _car;
        private readonly IInspectionLogic _inspection;
        private readonly IEquipmentLogic _equipment;

        private readonly AbstractMailWorker _mailWorker;

        private readonly IReportLogicAdministrator _reportAdministrator;

        public MainController(ILogger<MainController> logger, IEmployeeLogic employee, ISaleLogic sale, IPreSaleWorkLogic preSaleWork, ICarLogic car, 
            IInspectionLogic inspection, IEquipmentLogic equipment, IReportLogicAdministrator reportAdministrator, AbstractMailWorker mailWorker)
        {
            _logger = logger;
            _employee = employee;
            _sale = sale;
            _preSaleWork = preSaleWork;
            _car = car;
            _inspection = inspection;
            _equipment = equipment;
            _reportAdministrator = reportAdministrator;
            _mailWorker = mailWorker;
        }

        [HttpGet]
        public List<EmployeeViewModel>? GetEmployeeList(int managerId)
        {
            try
            {
                return _employee.ReadList(new EmployeeSearchModel
                {
                    ManagerId = managerId,
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка сотрудников");
                throw;
            }
        }

        [HttpGet]
        public List<SaleViewModel>? GetSaleList(int managerId)
        {
            try
            {
                return _sale.ReadList(new SaleSearchModel
                {
                    ManagerId = managerId,
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка продаж");
                throw;
            }
        }

        [HttpGet]
        public List<PreSaleWorkViewModel>? GetPreSaleWorkList(int managerId)
        {
            try
            {
                return _preSaleWork.ReadList(new PreSaleWorkSearchModel
                {
                    ManagerId = managerId,
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка препродажной работы");
                throw;
            }
        }

        [HttpGet]
        public List<CarViewModel>? GetCarList(int administratorId)
        {
            try
            {
                return _car.ReadList(new CarSearchModel
                {
                    AdministratorId = administratorId,
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка машин");
                throw;
            }
        }

        [HttpGet]
        public List<InspectionViewModel>? GetInspectionList(int administratorId)
        {
            try
            {
                return _inspection.ReadList(new InspectionSearchModel
                {
                    AdministratorId = administratorId,
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка осмотров");
                throw;
            }
        }

        [HttpGet]
        public List<EquipmentViewModel>? GetEquipments()
        {
            try
            {
                return _equipment.ReadList(null);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка комплектаций");
                throw;
            }
        }

        [HttpGet]
        public List<EquipmentViewModel>? GetEquipmentList(int administratorId)
        {
            try
            {
                return _equipment.ReadList(new EquipmentSearchModel
                {
                    AdministratorId = administratorId,
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка комплектаций");
                throw;
            }
        }

        [HttpPost]
        public void UpdateSale(SaleBindingModel model)
        {
            try
            {
                _sale.Update(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка обновления данных");
                throw;
            }
        }

        [HttpGet]
        public SaleViewModel? GetSale(int saleId)
        {
            try
            {
                return _sale.ReadElement(new SaleSearchModel
                {
                    Id = saleId
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения продажи по id={Id}", saleId);
                throw;
            }
        }

        [HttpPost]
        public void CreateSale(SaleBindingModel model)
        {
            try
            {
                _sale.Create(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка создания продажи");
                throw;
            }
        }

        [HttpPost]
        public void DeleteSale(SaleBindingModel model)
        {
            try
            {
                _sale.Delete(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка удаления продажи");
                throw;
            }
        }

        [HttpPost]
        public void UpdateCar(CarBindingModel model)
        {
            try
            {
                _car.Update(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка обновления данных о машинах");
                throw;
            }
        }

        [HttpGet]
        public CarViewModel? GetCar(int carId)
        {
            try
            {
                return _car.ReadElement(new CarSearchModel
                {
                    Id = carId
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения машины по id={Id}", carId);
                throw;
            }
        }

        [HttpPost]
        public void CreateCar(CarBindingModel model)
        {
            try
            {
                _car.Create(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка создания машины");
                throw;
            }
        }

        [HttpPost]
        public void DeleteCar(CarBindingModel model)
        {
            try
            {
                _car.Delete(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка удаления машины");
                throw;
            }
        }

        [HttpPost]
        public void CreateEmployee(EmployeeBindingModel model)
        {
            try
            {
                _employee.Create(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка создания сотрудника");
                throw;
            }
        }

        [HttpPost]
        public void UpdateEmployee(EmployeeBindingModel model)
        {
            try
            {
                model.EmployeeSales = null!;
                _employee.Update(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка обновления данных");
                throw;
            }
        }

        [HttpGet]
        public Tuple<EmployeeViewModel, List<Tuple<DateTime?, string>>>? GetEmployee(int employeeId)
        {
            try
            {
                var elem = _employee.ReadElement(new EmployeeSearchModel { Id = employeeId });
                if (elem == null)
                    return null;
                return System.Tuple.Create(elem, elem.EmployeeSales.Select(x => System.Tuple.Create(x.Value.SaleDate, x.Value.SalePrice)).ToList());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения сотрудника по id={Id}", employeeId);
                throw;
            }
        }

        [HttpPost]
        public void DeleteEmployee(EmployeeBindingModel model)
        {
            try
            {
                _employee.Delete(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка удаления сотрудника");
                throw;
            }
        }

        [HttpPost]
        public void AddSaleToEmployee(Tuple<EmployeeSearchModel, SaleViewModel> model)
        {
            try
            {
                _employee.AddSaleToEmployee(model.Item1, model.Item2);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка добавления продажи в сотрудника.");
                throw;
            }
        }

        [HttpPost]
        public void CreatePreSaleWork(PreSaleWorkBindingModel model)
        {
            try
            {
                _preSaleWork.Create(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка создания предпродажной работы");
                throw;
            }
        }

        [HttpPost]
        public void UpdatePreSaleWork(PreSaleWorkBindingModel model)
        {
            try
            {
                model.PreSaleWorkSales = null!;
                _preSaleWork.Update(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка обновления данных");
                throw;
            }
        }

        [HttpGet]
        public Tuple<PreSaleWorkViewModel, List<Tuple<DateTime?, string>>, List<Tuple<string, double>>>? GetPreSaleWork(int preSaleWorkId)
        {
            try
            {
                using var context = new CarCenterDataBase(); 
                var elem = _preSaleWork.ReadElement(new PreSaleWorkSearchModel { Id = preSaleWorkId });
                if (elem == null)
                    return null;
                return System.Tuple.Create(elem, elem.PreSaleWorkSales.Select(x => System.Tuple.Create(x.Value.SaleDate, x.Value.SalePrice)).ToList(), context.Equipments.Where(x => x.PreSaleWorkId == elem.Id).Select(x => System.Tuple.Create(x.EquipmentName, x.EquipmentPrice)).ToList());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения препродажной работы по id={Id}", preSaleWorkId);
                throw;
            }
        }

        [HttpPost]
        public void DeletePreSaleWork(PreSaleWorkBindingModel model)
        {
            try
            {
                _preSaleWork.Delete(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка удаления препродажной работы");
                throw;
            }
        }

        [HttpPost]
        public void AddSaleToPreSaleWork(Tuple<PreSaleWorkSearchModel, SaleViewModel> model)
        {
            try
            {
                _preSaleWork.AddSaleToPreSaleWork(model.Item1, model.Item2);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка добавления продажи в препродажную работу.");
                throw;
            }
        }

        [HttpPost]
        public void CreateEquipment(EquipmentBindingModel model)
        {
            try
            {
                _equipment.Create(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка создания комплектации");
                throw;
            }
        }

        [HttpPost]
        public void CreateInspection(InspectionBindingModel model)
        {
            try
            {
                _inspection.Create(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка создания осмотра");
                throw;
            }
        }

        [HttpPost]
        public void UpdateEquipment(EquipmentBindingModel model)
        {
            try
            {
                /*model.EquipmentCars = null!;*/
                _equipment.Update(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка обновления данных");
                throw;
            }
        }

        [HttpGet]
        public EquipmentViewModel GetEquipmentById(int equipmentId)
        {
            try
            {
                var elem = _equipment.ReadElement(new EquipmentSearchModel { Id = equipmentId });
                if (elem == null)
                    return null;
                return elem;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения комплектации по id={Id}", equipmentId);
                throw;
            }
        }

        [HttpGet]
        public Tuple<EquipmentViewModel, List<Tuple<string, string>>>? GetEquipment(int equipmentId)
        {
            try
            {
                var elem = _equipment.ReadElement(new EquipmentSearchModel { Id = equipmentId });
                if (elem == null)
                    return null;
                return System.Tuple.Create(elem, elem.EquipmentCars.Select(x => System.Tuple.Create(x.Value.BrandCar, x.Value.Model)).ToList());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения комплектации по id={Id}", equipmentId);
                throw;
            }
        }

        [HttpPost]
        public void DeleteEquipment(EquipmentBindingModel model)
        {
            try
            {
                _equipment.Delete(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка удаления комплектации");
                throw;
            }
        }

        [HttpPost]
        public void AddCarToEquipment(Tuple<EquipmentSearchModel, CarViewModel> model)
        {
            try
            {
                _equipment.AddCarToEquipment(model.Item1, model.Item2);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка добавления машины в комплектацию.");
                throw;
            }
        }
        [HttpPost]
        public void UpdateInspection(InspectionBindingModel model)
        {

            try
            {
                /*model.InspectionCars = null!;*/
                _inspection.Update(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка обновления данных");
                throw;
            }
        }

        [HttpGet]
        public Tuple<InspectionViewModel, List<Tuple<string, string>>>? GetInspection(int inspectionId)
        {
            try
            {
                var elem = _inspection.ReadElement(new InspectionSearchModel { Id = inspectionId });
                if (elem == null)
                    return null;
                return System.Tuple.Create(elem, elem.InspectionCars.Select(x => System.Tuple.Create(x.Value.BrandCar, x.Value.Model)).ToList());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения по id={Id}", inspectionId);
                throw;
            }
        }

        [HttpPost]
        public void DeleteInspection(InspectionBindingModel model)
        {
            try
            {
                _inspection.Delete(model);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка удаления осмотра");
                throw;
            }
        }

        [HttpPost]
        public void AddCarToInspection(Tuple<InspectionSearchModel, CarViewModel> model)
        {
            try
            {
                _inspection.AddCarToInspection(model.Item1, model.Item2);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка добавления машины в план питания.");
                throw;
            }
        }

        [HttpGet]
        public List<EmployeeViewModel>? GetEmployees()
        {
            try
            {
                return _employee.ReadList(null);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения списка конференций");
                throw;
            }
        }

        [HttpGet]
        public InspectionViewModel GetInspectionById(int inspectionId)
        {
            try
            {
                var elem = _inspection.ReadElement(new InspectionSearchModel { Id = inspectionId });
                if (elem == null)
                    return null;
                return elem;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка получения по id={Id}", inspectionId);
                throw;
            }
        }

		[HttpGet]
		public List<PreSaleWorkViewModel>? GetPreSaleWorks()
		{
			try
			{
				return _preSaleWork.ReadList(null);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "Ошибка получения списка конференций");
				throw;
			}
		}


        [HttpGet]
        public List<ReportEquipmentsEmployeesViewModel> GetEquipmentsEmployeesReport(string dateFrom, string dateTo, int administratorId)
        {
            try
            {
                DateTime DateFrom = DateTime.Parse(dateFrom);
                DateTime DateTo = DateTime.Parse(dateTo);
                ReportEquipmentsEmployeesBindingModel model = new();
                model.DateFrom = DateFrom;
                model.DateTo = DateTo;
                model.AdministratorId = administratorId;
                return _reportAdministrator.GetEquipmentsEmployees(model);
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        [HttpPost]
        public void SendEquipmentsEmployeesReportToEmail(ReportEquipmentsEmployeesBindingModel model)
        {
            try
            {
                _reportAdministrator.SaveCarsToPdfFile(model);
                _mailWorker.MailSendAsync(new MailSendInfoBindingModel
                {
                    MailAddress = model.Email!,
                    Subject = "Отчет по машинам",
                    Text = "отчет"
                });
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        [HttpPost]
        public void CreatePreSaleWorkListWordFile(ReportPreSaleWorkCarBindingModel model)
        {
            try
            {
                _reportAdministrator.SavePreSaleWorksToWordFile(model);
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        [HttpPost]
        public void CreatePreSaleWorkListExcelFile(ReportPreSaleWorkCarBindingModel model)
        {
            try
            {
                _reportAdministrator.SavePreSaleWorksToExcelFile(model);
            }
            catch (Exception ex)
            {
                throw;
            }
        }



    }
}
