using Caliburn.Micro;
using Gremlin.MVVM.Models;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace Gremlin.MVVM.ViewModels
{
	public class QuoteViewModel : PropertyChangedBase
	{
		private string quoteType = "ein Analysegerät";
		private string quotePath = AppDomain.CurrentDomain.BaseDirectory;
		private LineItemViewModel selectedLineItem;
		private ObservableCollection<LineItemViewModel> lineItemsVM = new();
		private ContactViewModel recipient = new();
		private ContactViewModel salesRep = new();
		private string quoteNumber;
		private int warranty = 12;
		private int validity = 60;
		private decimal vAT = 19;
		private decimal freight = 3;
		private bool? showBrutto = true;
		private bool? singlePrices = true;
		private bool? attachBrochures;
		private bool? attachDataSheets;
		private bool? useMailTemplate;
		private bool? showDiscounts = true;
		private int oppID;
		private bool preisinformation = false;
		private decimal totalListprice;
		private decimal totalNet;
		private decimal totalFreightOnly;
		private decimal totalFreight;
		private decimal totalVAT;
		private decimal totalGross;

		private readonly List<LineItemViewModel> lineItemsWithoutCustomDescription = new();

		public LineItemViewModel SelectedLineItem { get => selectedLineItem; set { selectedLineItem = value; NotifyOfPropertyChange(() => SelectedLineItem); DebugSelectedLineItem(); } }
		public ObservableCollection<LineItemViewModel> LineItemsVM { get => lineItemsVM; set { lineItemsVM = value; NotifyOfPropertyChange(() => LineItemsVM); } }
		public ContactViewModel Recipient { get => recipient; set { recipient = value; NotifyOfPropertyChange(() => Recipient); Validity = CheckForAcademic(Recipient); } }
		public ContactViewModel SalesRep { get => salesRep; set { salesRep = value; NotifyOfPropertyChange(() => SalesRep); } }

		public string QuoteType { get => quoteType; set { quoteType = value; NotifyOfPropertyChange(() => QuoteType); } }
		public string QuotePath { get => quotePath; set { quotePath = CorrectQuotePath(value); NotifyOfPropertyChange(() => QuotePath); } }
		public bool? ShowBrutto { get => showBrutto; set { showBrutto = value; NotifyOfPropertyChange(() => ShowBrutto); } }
		public string QuoteNumber { get => quoteNumber; set { quoteNumber = value; NotifyOfPropertyChange(() => QuoteNumber); } }
		public int Warranty { get => warranty; set { warranty = value; NotifyOfPropertyChange(() => Warranty); } }
		public int Validity { get => validity; set { validity = value; NotifyOfPropertyChange(() => Validity); } }
		public bool? SinglePrices { get => singlePrices; set { singlePrices = value; NotifyOfPropertyChange(() => SinglePrices); } }
		public bool? AttachBrochures { get => attachBrochures; set { attachBrochures = value; NotifyOfPropertyChange(() => AttachBrochures); } }
		public bool? AttachDataSheets { get => attachDataSheets; set { attachDataSheets = value; NotifyOfPropertyChange(() => AttachDataSheets); } }
		public bool? UseMailTemplate { get => useMailTemplate; set { useMailTemplate = value; NotifyOfPropertyChange(() => UseMailTemplate); } }
		public bool? ShowDiscounts { get => showDiscounts; set { showDiscounts = value; NotifyOfPropertyChange(() => ShowDiscounts); } }
		public decimal VAT { get => vAT; set { vAT = value; NotifyOfPropertyChange(() => VAT); } }
		public int OppID { get => oppID; set { oppID = value; NotifyOfPropertyChange(() => OppID); } }
		public bool Preisinformation { get => preisinformation; set { preisinformation = value; NotifyOfPropertyChange(() => Preisinformation); } }
		public decimal Freight { get => freight; set { freight = value; NotifyOfPropertyChange(() => Freight); } }

		public decimal TotalListprice { get => totalListprice; set { totalListprice = value; NotifyOfPropertyChange(() => TotalListprice); } }
		public decimal TotalNet { get => totalNet; set { totalNet = value; NotifyOfPropertyChange(() => TotalNet); } }
		public decimal TotalFreightOnly { get => totalFreightOnly; set { totalFreightOnly = value; NotifyOfPropertyChange(() => TotalFreightOnly); } }
		public decimal TotalFreight { get => totalFreight; set { totalFreight = value; NotifyOfPropertyChange(() => TotalFreight); } }
		public decimal TotalVAT { get => totalVAT; set { totalVAT = value; NotifyOfPropertyChange(() => TotalVAT); } }
		public decimal TotalGross { get => totalGross; set { totalGross = value; NotifyOfPropertyChange(() => TotalGross); } }

		public decimal AverageDiscount => GetTotal("AverageDiscount");
		public bool QuoteContains3PP => DoesContains("3PP");
		public bool QuoteContainsRB => DoesContains("RB");

		public QuoteViewModel()
		{
			LineItemsVM = new();
			ResetTotals();

			//Debug-Standard
			SalesRep.LastName = "Woitschetzki";

			Random random = new();
			QuoteNumber = SalesRep.LastName switch
			{
				"Woitschetzki" => $"DE-83PE89-{DateTime.Now:My}-{random.Next(999999)}",
				"Welsch" => $"DE-83RE32-{DateTime.Now:My}-{random.Next(999999)}",
				_ => $"DE-XXYYXX-{DateTime.Now:My}-{random.Next(999999)}",
			};
		}

		private void DebugSelectedLineItem()
		{
			Debug.WriteLine($"Ausgewähltes LineItem: {SelectedLineItem.ProductNumber}#{SelectedLineItem.OptionNumber}: {SelectedLineItem.CustomDescriptionVM.Heading} ({SelectedLineItem.CustomDescriptionVM.DescriptionText})");
		}

		private static int CheckForAcademic(ContactViewModel recipient)
		{
			return recipient == null || recipient.AccountTypeCode == null ? 0 : recipient.AccountTypeCode.StartsWith("N") ? 90 : 60;
		}

		public bool ReadLineItems(QuoteViewModel quoteVM)
		{
			ResetTotals();

			LineItemsVM = LineItemModel.ReadLineItemsFromClipboard(quoteVM);

			if (LineItemsVM == null)
			{
				return false;
			}
			else
			{
				//Wähle erstes Item standardmäßig aus
				SelectedLineItem = LineItemsVM[0];
			}

			foreach (LineItemViewModel lineItemVM in LineItemsVM)
			{
				if (lineItemVM.OptionNumber != null)
				{
					// normale Gewährleistungsverlängerung
					if (lineItemVM.OptionNumber.StartsWith("8D"))
					{
						Warranty = int.Parse(lineItemVM.OptionNumber.Last().ToString()) * 12;
					}

					//24 Monate Gewährleistung für Akademia
					if (lineItemVM.OptionNumber == "9EC")
					{
						Warranty = 24;
					}

					//36 Monate Gewährleistung für Akademia
					if (lineItemVM.OptionNumber == "9CC")
					{
						Warranty = 36;
					}
				}

				//Checke auf fehlende CustomDescriptions
				if (!lineItemVM.CustomDescriptionVM.IsAvailable)
				{
					lineItemsWithoutCustomDescription.Add(lineItemVM);
				}

				//AddToTotal
				TotalListprice += lineItemVM.ListPrice;
				TotalNet += lineItemVM.CalcTotalNet;
			}

			CalculateTotals();

			if (lineItemsWithoutCustomDescription.Count != 0)
			{
				string fehlendeCustomDescriptions = "Folgende LineItems haben keine CustomDescription:\n";
				foreach (LineItemViewModel lineItemWithoutCustomDescription in lineItemsWithoutCustomDescription)
				{
					fehlendeCustomDescriptions += lineItemWithoutCustomDescription.ProductNumber + "#" + lineItemWithoutCustomDescription.OptionNumber + ": " + lineItemWithoutCustomDescription.CustomDescriptionVM.Heading + "\n";
				}
			}

			return LineItemsVM.Count != 0 && Recipient.LastName != "lastName";
		}

		private static decimal GetFreight(decimal net, decimal freight)
		{
			decimal freightNet = net * freight / 100;
			return freightNet < 3000 ? freightNet : 3000;
		}

		private void CalculateTotals()
		{
			TotalFreightOnly = GetFreight(TotalNet, Freight);
			TotalFreight = TotalNet + TotalFreightOnly;
			TotalVAT = TotalFreight * VAT / 100;
			TotalGross = TotalFreight * (100 + VAT) / 100;
		}

		private void ResetTotals()
		{
			TotalListprice = 0;
			TotalNet = 0;
			TotalFreightOnly = 0;
			TotalFreight = 0;
			TotalVAT = 0;
			TotalGross = 0;
			lineItemsWithoutCustomDescription.Clear();
		}

		private static string CorrectQuotePath(string quotePath)
		{
			if (quotePath.EndsWith("\\"))
			{
				return quotePath;
			}
			else
			{
				return $"{quotePath}\\";
			}
		}

		public void ChooseQuotePath()
		{
			OpenFileDialog openFileDialog = new()
			{
				Multiselect = false,
				InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
			};

			if (openFileDialog.ShowDialog() == true)
			{
				FileInfo fileInfo = new(openFileDialog.FileName);
				QuotePath = fileInfo.DirectoryName;
			}
		}

		private decimal GetTotal(string type)
		{
			decimal total = 0;

			foreach (LineItemViewModel lineItemVM in LineItemsVM)
			{
				switch (type)
				{
					case "TotalListprice":
						total += lineItemVM.ListPrice;
						break;
					case "TotalNet":
						total += lineItemVM.CalcTotalNet;
						break;
					case "AverageDiscount":
						total += lineItemVM.TotalDiscount;
						break;
				}
			}

			if (type == "AverageDiscount" & LineItemsVM.Count != 0) { total /= LineItemsVM.Count; }

			return total;
		}

		private bool DoesContains(string type)
		{
			foreach (LineItemViewModel lineItemVM in LineItemsVM)
			{
				switch (type)
				{
					case "3PP":
						if (lineItemVM.ProductLine == "3PP")
						{
							Debug.WriteLine($"Quote containts 3PP with ProductNumber {lineItemVM.ProductNumber}");
							NotifyOfPropertyChange(() => QuoteContains3PP);
							return true;
						}
						break;
					case "RB":
						if (lineItemVM.ProductLine == "RB" & lineItemVM.ProductNumber != "R2005A")
						{
							Debug.WriteLine($"Quote containts RB with ProductNumber {lineItemVM.ProductNumber}");
							NotifyOfPropertyChange(() => QuoteContainsRB);
							return true;
						}
						break;
				}
			}
			return false;
		}
	}
}