using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup.Localizer;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Database.Models;
using Pos.Models;
using Pos.Service;

namespace Pos
{
    /// <summary>
    /// Interaction logic for SalesWindow.xaml
    /// </summary>
    public partial class SalesWindow : Window
    {
        private ObservableCollection<EmployeeEntity> _employees;
        private ObservableCollection<ProductGroupEntity> _productGroups;
        private ObservableCollection<SaleGridModel> _saleGridModels;
        private ObservableCollection<AmountGridModel> _paymentGridModels;
        private List<PriceLineModel> _priceLineModels;

        private ProductEntity _selectedProduct;
        private ProductGroupEntity _selectedProductGroup;

        private int _employeeId = -1;
        private int _productGroupId = -1;
        private int _productId = -1;
        private int _numberOfProducts = 1;
        private int _selectedSaleGridIndex = -1;

        private int _maxCharOfName = 0;
        
        private decimal _price = 0;
        private decimal _totalPrice = 0;

        private Button _prevEmpButton = new Button();
        private Button _prevProductGroupButton = new Button();
        private Button _prevProduct = new Button();

        public SalesWindow()
        {
            InitializeComponent();
            InitialLoad();
        }

        private void InitialLoad()
        {
            CacheService.Invalidate();
            _employees = CacheService.GetEmployee() as ObservableCollection<EmployeeEntity>;
            _productGroups = CacheService.GetProductGroupsIncludeProducts() as ObservableCollection<ProductGroupEntity>;
            _saleGridModels = new ObservableCollection<SaleGridModel>();
            _priceLineModels = new List<PriceLineModel>();
            _paymentGridModels = new ObservableCollection<AmountGridModel>();
            SaleGrid.ItemsSource = _saleGridModels;
            PaymentGrid.ItemsSource = _paymentGridModels;
            BuildEmployee();
            BuildProductGroup();
            ManipulateBuySection();
            UpdateWindowTitle();

            foreach (var productGroup in _productGroups)
            {
                if (_maxCharOfName < productGroup.Name.Length)
                    _maxCharOfName = productGroup.Name.Length;

                foreach (ProductEntity product in productGroup.Products)
                {
                    if (_maxCharOfName < product.Name.Length)
                        _maxCharOfName = product.Name.Length;
                }
            }
        }

 

        private void BtnPrGr_Click(object sender, RoutedEventArgs e)
        {
            _productId = -1;
            _prevProductGroupButton.Style = (Style)FindResource("SaleButtons");
            Button button = sender as Button;
            _prevProductGroupButton = button;
            button.Style = (Style)FindResource("SaleButtonsActive");
            _productGroupId = (int)button.Tag;
            _selectedProductGroup = _productGroups.Single(c => c.Id == _productGroupId);
            BuildProducts(_selectedProductGroup.Products);
            ManipulateBuySection();
        }

        private void BtnProduct_Click(object sender, RoutedEventArgs e)
        {
            _prevProduct.Style = (Style)FindResource("SaleButtons");
            Button button = sender as Button;
            _prevProduct = button;
            button.Style = (Style)FindResource("SaleButtonsActive");
            _productId = (int)button.Tag;
            _selectedProduct = _selectedProductGroup.Products.Single(c => c.Id == _productId);
            ManipulateBuySection();
        }

        private void BtnEmp_Click(object sender, RoutedEventArgs e)
        {
            _prevEmpButton.Style = (Style)FindResource("SaleButtons");
            _prevProductGroupButton.Style = (Style)FindResource("SaleButtons");
            //DockProduct.Children.Clear();
            Button button = sender as Button;
            _prevEmpButton = button;
            button.Style = (Style)FindResource("SaleButtonsActive");
            _employeeId = (int) button.Tag;
            UIElementCollection employees = DockProductGroup.Children;
            foreach (UIElement emp in employees)
            {
                button = (Button)emp;
                button.IsEnabled = true;
            }

        }

        private void SaleGrid_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            DataGrid dg = (DataGrid)sender;
            _selectedSaleGridIndex = dg.SelectedIndex;

        }

        private void NumberOfProducts_GotFocus(object sender, RoutedEventArgs e)
        {
            NumberOfProducts.Text = string.Empty;
        }

        private void Buy_Click(object sender, RoutedEventArgs e)
        {
            bool isValid = ValidatePriceInput();
            if (!isValid)
                return;

            isValid = ValidateNumberOfProductsInput();
            if (!isValid)
                return;

            decimal price = Convert.ToDecimal(Price.Text);
            int number = Convert.ToInt32(NumberOfProducts.Text);
            NumberOfProducts.Text = "1";
            Price.Text = string.Empty;
            TotalPrice.Content = "0";
            BuildPrice(false);
            _productId = -1;
            _productGroupId = -1;
            ManipulateBuySection();
        }

        private void Payment_Click(object sender, RoutedEventArgs e)
        {
            //bool isValid = ValidateAmountInput();
            //if (!isValid)
            //    return;
            decimal amount = -1;
            if (!string.IsNullOrEmpty(Amount.Text))
                amount = Convert.ToDecimal(Amount.Text);

            Amount.Text = string.Empty;
            Button button = sender as Button;
            BuildAmuntDataGrid(amount,(string)button.Tag);
        }

        private void NumberOfProducts_LostFocus(object sender, RoutedEventArgs e)
        {
            bool isValid = ValidateNumberOfProductsInput();
            if (!isValid)
                return;

            CalculateSubPrice();
        }

        private void Price_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                Buy_Click(null,null);
            }
            else
            {
                CalculateSubPrice();
            }
            
        }

        private void BuildEmployee()
        {
            DockProductGroup.Children.Clear();
            //DockProduct.Children.Clear();
            DockEmployee.Children.Clear();
            bool firstEmployee = true;
            foreach (EmployeeEntity employee in _employees)
            {
                Button btnEmp = new Button();
                btnEmp.Style = (Style)FindResource("SaleButtons");
                btnEmp.Content = employee.Name;
                btnEmp.Tag = employee.Id;
                btnEmp.Click += BtnEmp_Click;
                DockEmployee.Children.Add(btnEmp);

                if (firstEmployee)
                {
                    firstEmployee = false;
                    btnEmp.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent));
                }
            }
        }

        private void BuildProductGroup()
        {
            DockProductGroup.Children.Clear();
            foreach (ProductGroupEntity productGroup in _productGroups)
            {
                Button btnPrGr = new Button();
                btnPrGr.Style = (Style)FindResource("SaleButtons");
                btnPrGr.Content = productGroup.Name;
                btnPrGr.Tag = productGroup.Id;
                btnPrGr.Click += BtnPrGr_Click;
                if (_employeeId == -1)
                    btnPrGr.IsEnabled = false;
                DockProductGroup.Children.Add(btnPrGr);
            }
        }

        private void BuildProducts(ICollection<ProductEntity> products)
        {
           // DockProduct.Children.Clear();
            foreach (ProductEntity product in products)
            {
                Button btnProduct = new Button();
                btnProduct.Style = (Style)FindResource("SaleButtons");
                btnProduct.Content = product.Name;
                btnProduct.Tag = product.Id;
                btnProduct.Click += BtnProduct_Click;
               // DockProduct.Children.Add(btnProduct);
            }

        }
        private void BuildPrice(bool returnProduct)
        {
            PriceLineModel pModel = new PriceLineModel();
            pModel.NumberProducts = _numberOfProducts;
            pModel.Price = _price;
            if (_selectedProduct != null)
            {
                pModel.Id = _selectedProduct.Id;
                pModel.Name = _selectedProduct.Name;
                pModel.IsProductGroup = false;
            }
            else
            {
                pModel.Id = _selectedProductGroup.Id;
                pModel.Name = _selectedProductGroup.Name;
                pModel.IsProductGroup = true;
            }

            BuildPriceDataGrid(pModel);
            //BuildEmployee();
            BuildProductGroup();
        }

        private void CalculateSubPrice()
        {
            _price = 0;
            bool isValid = decimal.TryParse(Price.Text, out _price);
            if (!isValid)
                return;

            isValid = Int32.TryParse(NumberOfProducts.Text, out _numberOfProducts);
            if (!isValid)
                return;

            TotalPrice.Content = _price * _numberOfProducts;
        }

        private void CalculateTotalLine()
        {
            _totalPrice = 0;
            foreach (PriceLineModel model in _priceLineModels)
            {
                _totalPrice += model.Price * model.NumberProducts;
            }

            Total.Content = $"At betale: Kr. {_totalPrice}";
        }

        private void BuildPriceDataGrid(PriceLineModel priceLineModel)
        {
            _selectedProduct = null;
            _selectedProductGroup = null;
            _numberOfProducts = 1;

            _priceLineModels.Add(priceLineModel);
            CalculateTotalLine();

            SaleGridModel model = new SaleGridModel();
            model.Navn = priceLineModel.Name;
            model.Pris = $"kr. {priceLineModel.Price}";
            model.Stk = $"- {priceLineModel.NumberProducts} stk. à";
            model.Total = $"= Kr. {priceLineModel.NumberProducts * priceLineModel.Price}";
            SaleGridInternalModel saleGridInternalModel = new SaleGridInternalModel();
            saleGridInternalModel.InternPrice = priceLineModel.Price;
            saleGridInternalModel.InternPieces = priceLineModel.NumberProducts;
            model.SaleGridInternalModel = saleGridInternalModel;
            //model.InternPrice = priceLineModel.Price;
            //model.InternPieces = priceLineModel.NumberProducts;
            _saleGridModels.Add(model);
        }

        private bool ValidateNumberOfProductsInput()
        {
            int notUsed;
            bool isValid = Int32.TryParse(NumberOfProducts.Text, out notUsed);
            if (!isValid)
            {
                MessageBox.Show($"{NumberOfProducts.Text} er ikke en gyldig værdi! \nSætter 1 som standard værdi ", "Ikke gyldig værdi",
                    MessageBoxButton.OK, MessageBoxImage.Error);
                NumberOfProducts.Text = "1";
                return false;
            }

            return true;
        }

        private bool ValidatePriceInput()
        {
            decimal p = 0;
            bool isValid = Decimal.TryParse(Price.Text, out p);
            if (!isValid)
            {
                string msg = "";
                if (string.IsNullOrEmpty(Price.Text))
                {
                    msg = "En tom pris er ikke en gyldig værdi!";
                }
                else
                {
                    msg = $"{Price.Text} er ikke en gyldig pris!";
                }

                MessageBox.Show(msg, "Ugyldig pris", MessageBoxButton.OK,
                    MessageBoxImage.Error);
                return false;
            }

            return true;
        }

        private bool ValidateAmountInput()
        {
            decimal p = 0;
            bool isValid = Decimal.TryParse(Amount.Text, out p);
            if (!isValid)
            {
                string msg = "";
                if (string.IsNullOrEmpty(Amount.Text))
                {
                    msg = "Et tomt beløb er ikke en gyldig værdi!";
                }
                else
                {
                    msg = $"{Amount.Text} er ikke et gyldigt beløb!";
                }

                MessageBox.Show(msg, "Ugyldigt beløb", MessageBoxButton.OK,
                    MessageBoxImage.Error);
                return false;
            }

            return true;

        }

        private void ManipulateBuySection()
        {
            bool enabled = _productGroupId > 0 || _productId > 0;

            PricePanel.IsEnabled = enabled;
            NumberOfProducts.IsEnabled = enabled;
            Price.IsEnabled = enabled;
            Price.Focus();
            BtnBuy.IsEnabled = enabled;
            LblStk.IsEnabled = enabled;
            LblPrice.IsEnabled = enabled;
            LblTotal.IsEnabled = enabled;
            TotalPrice.IsEnabled = enabled;
        }

        private void BuildAmuntDataGrid(decimal amount, string paymentMethod)
        {
            if (amount == -1)
            {
                amount = 0;
                foreach (PriceLineModel lineModel in _priceLineModels)
                {
                    amount += (lineModel.Price * lineModel.NumberProducts);
                }
            }

            AmountGridModel amountGridModel = new AmountGridModel();
            amountGridModel.Amount = amount;
            amountGridModel.AmountText = $"Kr. {amount}";
            switch (paymentMethod)
            {
                case "PaymentMethod.Card":
                    amountGridModel.PaymentMethodText = "Kort";
                    break;

                case "PaymentMethod.Cash":
                    amountGridModel.PaymentMethodText = "Kontant";
                    break;

                case "PaymentMethod.GiftCard":
                    amountGridModel.PaymentMethodText = "Gavekort";
                    break;

                case "PaymentMethod.MobilePay":
                    amountGridModel.PaymentMethodText = "MobilePay";
                    break;
            }
            _paymentGridModels.Add(amountGridModel);

            AmountPayed();
        }

        private void AmountPayed()
        {
            decimal amountPayed = 0;
            foreach (AmountGridModel paymentGridModel in _paymentGridModels)
            {
                amountPayed += paymentGridModel.Amount;
            }

            if (amountPayed == _totalPrice)
            {
                btnFinish_Click(null,null);
                return;
            }

            if (amountPayed > _totalPrice)
            {
                lblRecived.Content = $"Byttepenge: Kr. {amountPayed - _totalPrice}";
                Style style = this.FindResource("BoldLabelWarningNoMargin") as Style;
                lblRecived.Style = style;
                btnFinish.IsEnabled = true;
            }
            else
            {
                lblRecived.Content = $"At betale: Kr. {_totalPrice - amountPayed}";
                Style style = this.FindResource("BoldLabelNoMargin") as Style;
                lblRecived.Style = style;
            }
        }


        private void SaleGrid_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Delete)
            {
                if (_selectedSaleGridIndex == -1)
                    return;
                int index = _selectedSaleGridIndex;
                //_saleGridModels.RemoveAt(_selectedSaleGridIndex);
                _priceLineModels.RemoveAt(index);
                _selectedSaleGridIndex = -1;
                CalculateTotalLine();
            }
        }

        private void btnFinish_Click(object sender, RoutedEventArgs e)
        {
            SaleService saleService = new SaleService();
            saleService.Save(_saleGridModels.ToList(),_paymentGridModels.ToList(),_employeeId);
            _paymentGridModels.Clear();
            _priceLineModels.Clear();
            UpdateWindowTitle();
            _totalPrice = 0;
            _saleGridModels.Clear();
            lblRecived.Content = string.Empty;
            _selectedSaleGridIndex = -1;
            btnFinish.IsEnabled = false;
            CalculateTotalLine();
            BuildEmployee();
            BuildProductGroup();
            ManipulateBuySection();
        }

        private void BtnPrint_Click(object sender, RoutedEventArgs e)
        {
            SaleService saleService = new SaleService();
            saleService.PrintReceipt();
        }

        private void UpdateWindowTitle()
        {
            SaleService saleService = new SaleService();
            Title  = saleService.LastAndTotalSale();
        }
    }
}
