using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Database.Models;
using Database.Repository;
using EpsonPrinter.Model;
using EpsonPrinter.Services;
using Microsoft.Extensions.Configuration;
using Pos.Json;
using Pos.Models;
using RestSharp;
using SixLabors.ImageSharp;
using BodyModel = Pos.Json.BodyModel;
using FooterModel = Pos.Json.FooterModel;
using HeaderModel = Pos.Json.HeaderModel;

namespace Pos.Service
{
    public class SaleService
    {
        private float _totalPrice = 0;
        private SaleRepository _saleRepository = new SaleRepository();

        public void Save(List<SaleGridModel> saleGridModels, List<AmountGridModel> amountGridModels, int employeeNo)
        {
            SaleRepository saleRepository = new SaleRepository();
            SaleEntity saleEntity = saleRepository.New(employeeNo);

            foreach (SaleGridModel model in saleGridModels)
            {
                if(String.IsNullOrEmpty(model.Navn))
                    continue;

                SaleLineEntity saleLineEntity = new SaleLineEntity();
                saleLineEntity.SaleId = saleEntity.Id;
                saleLineEntity.Price = model.SaleGridInternalModel.InternPrice;
                saleLineEntity.Product = model.Navn;
                saleLineEntity.Pieces = model.SaleGridInternalModel.InternPieces;
                saleLineEntity.Total = saleLineEntity.Pieces * saleLineEntity.Price;
                saleRepository.SaveSaleLine(saleLineEntity);
            }

            foreach (AmountGridModel model in amountGridModels)
            {
                PaymentEntity payment = new PaymentEntity();
                payment.Amount = model.Amount;
                payment.Type = model.PaymentMethodText;
                payment.SaleId = saleEntity.Id;
                saleRepository.SavePayment(payment);
            }
        }

        public void PrintReceipt()
        {
            
            SaleEntity sale = _saleRepository.GetLatest();
            if (sale == null)
                return;

            BuildSaleReceipt(sale);
        }

        public void PrintReceipt(int saleId)
        {
            SaleEntity sale = _saleRepository.Get(saleId);
            BuildSaleReceipt(sale);
        }

        public void PrintSaleOfDay(DateTime selectedDate, TotalSaleDetail totalSaleDetail)
        {
            SaleOfDayModel saleOfDayModel = new SaleOfDayModel();
            saleOfDayModel.Date = selectedDate;
            saleOfDayModel.TotalSale = totalSaleDetail.TotalSale;
            saleOfDayModel.TotalCustomers = totalSaleDetail.TotalCustomer;
            foreach (TotalSaleCategory category in totalSaleDetail.TotalSaleCategories)
            {
                SaleOfDayDetail saleOfDayDetail = new SaleOfDayDetail();
                saleOfDayDetail.TotalSale = category.Sale;
                saleOfDayDetail.Category = category.Category;
                saleOfDayModel.SaleOfDayDetail.Add(saleOfDayDetail);
            }

            LoadConfig loadConfig = new LoadConfig();
            IConfiguration config = loadConfig.ByEnvironment();
            string url = config["API:URL"];

            RestClient restClient = new RestClient($"{url}/api/PosPrinter/SaleOfDay");
            RestRequest request = new RestRequest();
            request.AddJsonBody(saleOfDayModel);
            request.Method = Method.Post;
            restClient.Post(request);
        }

        public TotalSaleDetail TotalSale(DateTime selectedDate)
        {
            List<SaleEntity> sales = _saleRepository.GetByDateRange(selectedDate);
            TotalSaleDetail totalSaleDetail = new TotalSaleDetail();
            totalSaleDetail.TotalCustomer = sales.Count;
            foreach (SaleEntity sale in sales)
            {
                List<SaleLineEntity> saleLineBySaleId = _saleRepository.GetSaleLineBySaleId(sale.Id);
                foreach (SaleLineEntity saleLine in saleLineBySaleId)
                {

                    if (totalSaleDetail.TotalSaleCategories.Any(c => c.Category.Contains(saleLine.Product)))
                    {
                        TotalSaleCategory totalSaleCategory = totalSaleDetail.TotalSaleCategories.Single(c => c.Category.Contains(saleLine.Product));
                        totalSaleCategory.Sale += saleLine.Total;
                        totalSaleCategory.SaleString = "Kr. " + totalSaleCategory.Sale.ToString("0.00");
                    }
                    else
                    {
                        TotalSaleCategory totalSaleCategory = new TotalSaleCategory();
                        totalSaleCategory.Sale = saleLine.Total;
                        totalSaleCategory.SaleString ="Kr. " + totalSaleCategory.Sale.ToString("0.00");
                        totalSaleCategory.Category = saleLine.Product;
                        totalSaleDetail.TotalSaleCategories.Add(totalSaleCategory);
                    }

                    totalSaleDetail.TotalSale += saleLine.Total;
                }
            }

            return totalSaleDetail;
        }

        public string LastAndTotalSale()
        {
            SaleEntity saleEntity = _saleRepository.GetLatest();
            List<SaleLineEntity> saleLineBySaleId = _saleRepository.GetSaleLineBySaleId(saleEntity.Id);
            decimal lastSale = 0;
            foreach (SaleLineEntity saleLine in saleLineBySaleId)
            {
                lastSale += saleLine.Total;
            }
            TotalSaleDetail totalSale = TotalSale(DateTime.Now);
            string todaySale = $"Sidste salg: kr. {lastSale.ToString("N")} - Dagens salg: kr. {totalSale.TotalSale.ToString("N")}";
            return todaySale;
        }

        private void BuildSaleReceipt(SaleEntity sale)
        {
            EmployeeRepository employeeRepository = new EmployeeRepository();
            EmployeeEntity employee = employeeRepository.Get(sale.EmployeeId);


            List<SaleLineEntity> salesLines = _saleRepository.GetSaleLineBySaleId(sale.Id);
            List<PaymentEntity> payments = _saleRepository.GetPaymentBySaleId(sale.Id);

            PosReceipt posReceipt = new PosReceipt();
            posReceipt.header = BuildReceiptHeader().ToArray();
            ProductModel[] productModels = BuildSaleLines(salesLines).ToArray();
            posReceipt.bodyModel = BuildBody(sale, employee.Name);
            posReceipt.bodyModel.products = productModels;
            posReceipt.footer = BuildFooter().ToArray();
            posReceipt.logoBase64 = String.Empty;

            LoadConfig loadConfig = new LoadConfig();
            IConfiguration config = loadConfig.ByEnvironment();
            string url = $"{config["API:URL"]}/api/PosPrinter/Receipt";

            RestClient restClient = new RestClient(url);
            RestRequest request = new RestRequest();
            request.AddJsonBody(posReceipt);
            request.Method = Method.Post;
            restClient.Post(request);
        }

        private List<FooterModel> BuildFooter()
        {
            List<FooterModel> footerModels = new List<FooterModel>();
            FooterModel model = new FooterModel();
            model.value = "Tak for handlen";
            model.printStyles = new PrintStylesModel
            {
                bold = false,
                fontB = false,
                doubleHeight = false,
                doubleWidth = false,
                underline = false
            };
            model.feedingLines = 0;
            model.textAlignment = 0;
            footerModels.Add(model);
            return footerModels;
        }

        private List<ProductModel> BuildSaleLines(List<SaleLineEntity> salesLines)
        {
            List<ProductModel> products = new List<ProductModel>();
            foreach (SaleLineEntity salesLine in salesLines)
            {
                ProductModel productModel = new ProductModel();
                productModel.noOfProduct = salesLine.Pieces.ToString();
                productModel.price = (float)salesLine.Price;
                productModel.totalPrice = salesLine.Pieces * productModel.price;
                _totalPrice += productModel.totalPrice;
                productModel.product = salesLine.Product;
                products.Add(productModel);
            }

            return products;
        }

        private BodyModel BuildBody(SaleEntity sale, string employeeName)
        {
            BodyModel body = new BodyModel
            {
                receiptNumber = sale.Id,
                receiptTime = sale.Time.ToString("HH:mm dd-MM-yyyy"),
                staff = employeeName,
                totalPrice = _totalPrice,
                totalVat = (_totalPrice / 100) * 25
            };

            return body;
        }

        private List<HeaderModel> BuildReceiptHeader()
        {
            List<HeaderModel> headerModels = new List<HeaderModel>();

            HeaderModel headerModel = new HeaderModel
            {
                feedingLines = 1,
                textAlignment = 1,
                value = "Blomster Til Alt"
            };
            PrintStylesModel printStylesModel = new PrintStylesModel
            {
                bold = true,
                fontB = false,
                doubleHeight = true,
                doubleWidth = true,
                underline = false
            };
            headerModel.printStyles = printStylesModel;
            headerModels.Add(headerModel);

            printStylesModel = new PrintStylesModel
            {
                bold = false,
                fontB = false,
                doubleHeight = false,
                doubleWidth = false,
                underline = false
            };

            headerModel = new HeaderModel
            {
                feedingLines = 0,
                textAlignment = 1,
                value = "Adelgade 91",
                printStyles = printStylesModel
            };
            headerModels.Add(headerModel);

            headerModel = new HeaderModel
            {
                feedingLines = 0,
                textAlignment = 1,
                value = "5400 Bogense",
                printStyles = printStylesModel
            };
            headerModels.Add(headerModel);

            headerModel = new HeaderModel
            {
                feedingLines = 0,
                textAlignment = 1,
                value = "Tlf: 41 82 71 66",
                printStyles = printStylesModel
            };
            headerModels.Add(headerModel);

            headerModel = new HeaderModel
            {
                feedingLines = 0,
                textAlignment = 1,
                value = "CVR: 37 14 44 36",
                printStyles = printStylesModel
            };
            headerModels.Add(headerModel);

            return headerModels;
        }
    }
}
