using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.Spreadsheet;
using ElectronicsShopContracts.BindingModels;
using ElectronicsShopContracts.BusinessLogicContracts;
using ElectronicsShopContracts.SearchModels;
using ElectronicsShopContracts.ViewModels;
using ElectronicsShopDataModels.Enums;
using ElectronicsShopDataModels.Models;
using ElectronicsShopUserApp.Models;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Globalization;
using System.Net.Mime;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using System.Xml.Serialization;

namespace ElectronicsShopUserApp.Controllers {
    public class HomeController : Controller {
        private readonly ILogger<HomeController> _logger;
        private Dictionary<int, (IProductModel, int)> _productList;
        public int Id;

        public HomeController(ILogger<HomeController> logger) {
            _logger = logger;
            _productList = new Dictionary<int, (IProductModel, int)>();
        }

        [HttpGet]
        public IActionResult Index() {
            if (APIClient.Client == null) {
                return Redirect("~/Home/Enter");
            }
            return View(APIClient.GetRequset<List<PaymeantViewModel>>($"api/client/getpaymeants?_clientid={APIClient.Client.ID}"));
        }

        [HttpGet]
        public IActionResult Privacy() {
            if (APIClient.Client == null) {
                return Redirect("~/home/Enter");
            }
            return View(APIClient.Client);
        }

        [HttpPost]
        public void Privacy(string email, string password, string fio) {
            if (APIClient.Client == null) {
                throw new Exception("���� ��� ��������������");
            }
            if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) {
                throw new Exception("������� �����, ������ � ���");
            }
            APIClient.PostRequest("api/client/updatedata", new ClientBindingModel {
                ID = APIClient.Client.ID,
                ClientFIO = fio,
                Email = email,
                Password = password,
            });

            APIClient.Client.ClientFIO = fio;
            APIClient.Client.Email = email;
            APIClient.Client.Password = password;
            Response.Redirect("Index");
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error() {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }

        [HttpGet]
        public IActionResult Enter() {
            return View();
        }

        [HttpPost]
        public void Enter(string email, string password) {
            if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password)) {
                throw new Exception("������� ����� � ������");
			}
            APIClient.Client = APIClient.GetRequset<ClientViewModel>($"api/Client/Login?email={email}&password={password}");
            if (APIClient.Client == null) {
                throw new Exception("�������� ����� �����/������");
            }
            Response.Redirect("Index");
        }

        [HttpGet]
        public IActionResult Register() {
            return View();
        }
        [HttpPost]
        public void Register(string email, string password, string fio) {
            if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(fio)) {
                throw new Exception("������� �����,������ � ���");
            }
            APIClient.PostRequest("api/client/register", new ClientBindingModel {
                ClientFIO = fio,
                Email = email,
                Password = password
            });
            Response.Redirect("Enter");
            return;
        }

        public IActionResult Orders() {
            if (APIClient.Client == null) {
                return Redirect("~/Home/Enter");
            }

            var view = APIClient.GetRequset<List<OrderViewModel>>($"api/main/getorders?_clientid={APIClient.Client.ID}");

            return View(view);
        }

        [HttpGet]
        public IActionResult CreateOrder() {
            if (APIClient.Client == null) {
                return Redirect("~/Home/Enter");
            }
            APIClient.PostRequest("api/main/createorder", new OrderBindingModel {
                ClientID = APIClient.Client.ID,
                DateCreate = DateTime.Now,
                Status = OrderStatus.����������
            });
            return RedirectToAction("OrderView");
        }

        [HttpGet]
        public IActionResult DeleteOrder(int id) {
            APIClient.PostRequest($"api/main/deleteorders", new OrderBindingModel { ID = id });
            return RedirectToAction("Orders");
        }

        [HttpGet]
        public IActionResult EditOrder(int id) {
            if (APIClient.Client == null) {
                return Redirect("~/Home/Enter");
            }

            if (id == 0) {
                return RedirectToAction("Orders");
            }
            var products = APIClient.GetRequset<List<List<string>>>($"api/main/getorderproducts?_orderid={id}");

            foreach (var pr in products ?? new List<List<string>>()) {
                var product = JsonConvert.DeserializeObject<ProductViewModel>(pr[0]);
                int count = JsonConvert.DeserializeObject<int>(pr[1]);
                _productList.Add(product.ID, (product, count));
            }

            (int, Dictionary<int, (IProductModel, int)>) tuple = (id, _productList);
            return View(tuple);
        }

        [HttpPost]
        public void EditOrder(double sum, int id) {
            if (sum <= 0) {
                APIClient.PostRequest($"api/main/deleteorders", new OrderBindingModel { ID = id });
            }

            Response.Redirect("Orders");
        }

        [HttpGet]
        public IActionResult OrderView() {
            if (APIClient.Client == null) {
                return Redirect("~/Home/Enter");
            }
            var view = APIClient.GetRequset<OrderViewModel>($"api/main/getorder?_clientid={APIClient.Client?.ID}");
            if (view != null) {
                Id = view.ID;
            }

            var products = APIClient.GetRequset<List<List<string>>>($"api/main/getorderproducts?_orderid={view?.ID}");

            foreach (var pr in products) {
                var product = JsonConvert.DeserializeObject<ProductViewModel>(pr[0]);
                int count = JsonConvert.DeserializeObject<int>(pr[1]);
                _productList.Add(product.ID, (product, count));
            }

            (int, Dictionary<int, (IProductModel, int)>) tuple = (Id, _productList);
            return View(tuple);
        }

        [HttpPost]
        public void OrderView(double sum, int id) {
            if (sum <= 0) {
                APIClient.PostRequest($"api/main/deleteorders", new OrderBindingModel { ID = id });
            }
            Response.Redirect("Orders");
        }

        [HttpGet]
        public IActionResult DeleteProductOrder(int orderID, int id) {
            APIClient.PostRequestStr($"api/main/deleteproductorder", orderID, id);

            return Redirect($"https://localhost:7219/Home/EditOrder/{orderID}");
        }

        [HttpGet]
        public IActionResult AddProduct(int id) {
            ViewBag.Products = APIClient.GetRequset<List<ProductViewModel>>($"api/main/getproducts");
            return View(id);
        }

        [HttpPost]
        public void AddProduct(int product, int count, int id) {
            var _product = APIClient.GetRequset<ProductViewModel>($"api/main/getproduct?_productid={product}") 
                                                                    ?? throw new Exception("������ ��������� ������");
			APIClient.ListPostRequest($"api/main/addproduct", _product, count, id);
            // � �� ���� ��� ��� ��� ��������� �������
			Response.Redirect($"https://localhost:7219/Home/EditOrder/{id}");
		}

        [HttpGet]
        public IActionResult Payment(int id) {
            if (APIClient.Client == null) {
                return Redirect("~/Home/Enter");
            }

            if (id == 0) {
                return Redirect("~/Home/Index");
            }
            var products = APIClient.GetRequset<List<List<string>>>($"api/main/getorderproducts?_orderid={id}");

            foreach (var pr in products) {
                var product = JsonConvert.DeserializeObject<ProductViewModel>(pr[0]);
                int count = JsonConvert.DeserializeObject<int>(pr[1]);
                _productList.Add(product.ID, (product, count));
            }

            double sum = APIClient.GetRequset<OrderViewModel>($"api/main/getorder?_orderid={id}").Sum;
													

			(double ,int, Dictionary<int, (IProductModel, int)>) tuple = (sum, id, _productList);
            return View(tuple);
        }

        [HttpPost]
        public void Payment(double sum, double paysum, int id) {
            if (APIClient.Client == null) {
                throw new Exception("������ ��� ��������������");
            }
            if (paysum <= 0) {
                throw new Exception("����� ������� ������ ���� ������ 0");
            }
            if (paysum > sum) {
                throw new Exception("����� ������ �� ������ ��������� ����� � ������");
            }
            APIClient.PostRequest("api/client/createpaymeant", new PaymeantBindingModel {
                OrderID = id,
                SumPayment = paysum,
                PayOption = PayOptionCalc(sum, paysum),
                ClientID = APIClient.Client.ID,
                DatePaymeant = DateTime.Now,
            });
            Response.Redirect("Index");
        }

        [HttpPost]
        public PaymeantOption PayOptionCalc(double sum, double paysum) {
            if (paysum < sum) {
                return PaymeantOption.���������_������;
            }
            else if (paysum == sum) {
                return PaymeantOption.������_������;
            }
            else {
                return PaymeantOption.����������;
            }
        }

        [HttpPost]
        public double Calc(int count, int product) {
            var _product = APIClient.GetRequset<ProductViewModel>($"api/main/getproduct?_productid={product}");
            return count * (_product?.Price ?? 1);
        }

        [HttpGet]
        public IActionResult Report() {
            if (APIClient.Client == null) {
                return Redirect("~/Home/Enter");
            }

            return View();
        }

        [HttpPost]
        public void Report(DateTime DateFrom, DateTime DateTo){
            if (DateTo == DateTime.MinValue || DateFrom > DateTo) {
                throw new Exception("���������� ������ ��������� ��������");
            }
            Response.Redirect($"ReportSearch?_datefrom={DateFrom}&_dateto={DateTo + DateTime.Now.TimeOfDay}");
        }

        [HttpGet]
        public IActionResult ReportSearch(string _datefrom, string _dateto) {

            var reports = APIClient.GetRequset<List<PaymeantViewModel>>($"api/client/getreport?_start={_datefrom}&_end={_dateto}");

			(DateTime, DateTime, List<PaymeantViewModel>?) tuple = (DateTime.Parse(_datefrom), DateTime.Parse(_dateto), reports);
            return View(tuple);
        }

        [HttpGet]
        public IActionResult CreateExcelReport(string DateFrom, string DateTo) {
            var fileMemStream = APIClient.GetRequset<byte[]>($"api/Client/CreateXlsxReport?_clientID={APIClient.Client?.ID}&DateFrom={DateFrom}&" +
                                                            $"DateTo={DateTo}");

            if (fileMemStream == null) {
                throw new Exception("������ �������� ������");
            }

            return File(fileMemStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Report.xlsx");
        }

        [HttpGet]
        public IActionResult CreateWordReport(string DateFrom, string DateTo) {
            var fileMemStream = APIClient.GetRequset<byte[]>($"api/client/CreateDocxReport?_clientID={APIClient.Client?.ID}&DateFrom={DateFrom}&" +
                                                             $"DateTo={DateTo}");

            if (fileMemStream == null) {
                throw new Exception("������ �������� ������");
            }

            return File(fileMemStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Report.docx");
        }

        [HttpGet]
        public IActionResult CreatePdfReport(string DateFrom, string DateTo) {
            APIClient.PostRequest("api/client/SendReportMail", new ReportBindingModel {
                ClientEmail = APIClient.Client?.Email ?? throw new Exception("������ ��������� ������"),
                DateFrom = DateTime.Parse(DateFrom),
                DateTo = DateTime.Parse(DateTo),
                ClientID = APIClient.Client.ID 
			});
            return View("Report");
        }
	}
}