using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeWo.Data.Access;
using BeWo.Data.Entities;
using BeWo.Service.Invoicing;
using BS.Shared;
using BS.Shared.Core;
using BS.Shared.DataContracts;
using BS.Shared.DataContracts.Compact;
using BS.Shared.Services;

namespace LHHannover.Invoicing
{
	public class HannoverInvoiceCreation : InvoiceCreation
    {
		private DateTime? accountingPeriodStart = null;
		private DateTime? accountingPeriodEnd = null;

		public override void SetInvoiceBaseData(int invoiceCounter, ServiceInvoice invoice, CostBearer costBearer, DateTimeSpan invoicePeriod,
			IList<CompactSupportConceptDC> supportConceptList)
		{
			if (invoicePeriod != null)
			{
				accountingPeriodStart = invoicePeriod.StartDate;
				accountingPeriodEnd = invoicePeriod.EndDate;
			}
			base.SetInvoiceBaseData(invoiceCounter, invoice, costBearer, invoicePeriod, supportConceptList);
		}

		
		public override IList<InvoiceItem> CreateInvoiceItems(List<ServiceRecordDC> serviceRecordsInPeriod, DateTimeSpan invoicePeriod, SupportConceptApprovalPeriod scap, Calculations calc)
		{
			List<InvoiceItem> list = new List<InvoiceItem>();
			InvoiceItem invoiceItem = null;
			decimal? amountPerUnit = GetHourlyRate(scap);

			foreach (var iServiceRecord in serviceRecordsInPeriod)
			{
				if (iServiceRecord.ServiceDescription.Category.IsBillable)
				{
					var bd = calc.GetBillingData(iServiceRecord);

					if (invoiceItem == null)
					{
						invoiceItem = new InvoiceItem();
						list.Add(invoiceItem);

						invoiceItem.AmountPerUnit = bd.AmountPerUnit;
						if (bd.RateFactor.HasValue)
							invoiceItem.AmountPerUnit *= (100 + bd.RateFactor.Value)/100;
						invoiceItem.ItemPeriodStart = accountingPeriodStart;
						invoiceItem.ItemPeriodEnd = accountingPeriodEnd;
						invoiceItem.RateFactor = bd.RateFactor;

						invoiceItem.AccountingInterval = bd.AccountingInterval;
						invoiceItem.ItemDescription = iServiceRecord.ServiceDescription.Category.Name;

						invoiceItem.UnitCount = 0;
						invoiceItem.AmountTotal = 0;
						invoiceItem.GrossAmountTotal = 0;
					
					}
					

					invoiceItem.UnitCount += bd.UnitCount ?? 0;
					invoiceItem.AmountTotal += bd.GrossAmountTotal ?? 0;
					invoiceItem.GrossAmountTotal += bd.GrossAmountTotal ?? 0;

				}
			}
			if (invoiceItem != null && amountPerUnit.HasValue)
			{
				invoiceItem.AmountPerUnit = amountPerUnit;
				invoiceItem.AmountTotal = invoiceItem.AmountPerUnit*invoiceItem.UnitCount;
				invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;
			}
			if (invoiceItem != null)
			{
				InvoiceItem ttii = CreateTravelTimeInvoiceItem(serviceRecordsInPeriod, scap, calc, invoiceItem);
				if (ttii != null)
					list.Add(ttii);
			}
			return list;
		}

		private decimal? GetHourlyRate(SupportConceptApprovalPeriod scap)
		{
			decimal? hourlyRate = null;

			if (scap.ApprovedBEPerInterval.HasValue && scap.ApprovedBEInterval.HasValue && scap.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Weekly)
			{
				var approvedFlsWeekly = scap.ApprovedBEPerInterval.Value;
				if (approvedFlsWeekly <= 1)
				{
					hourlyRate = 72.96m;
				}
				else if (approvedFlsWeekly < 3)
				{
					hourlyRate = 68.17m;
				}
				else
				{
					hourlyRate = 64.01m;
				}
			}
			return hourlyRate;
		}



		public virtual InvoiceItem CreateTravelTimeInvoiceItem(List<ServiceRecordDC> serviceRecordsInPeriod, SupportConceptApprovalPeriod scap, Calculations calc, InvoiceItem invoiceItemFLS)
		{
			var invoiceItem = new InvoiceItem();

			decimal maxKontakte = GetMaxKontakte(scap);
			
			decimal anzahlKontakte = serviceRecordsInPeriod.Count;
			if (anzahlKontakte > maxKontakte)
				anzahlKontakte = maxKontakte;
			

			invoiceItem.AmountPerUnit = invoiceItemFLS.AmountPerUnit / 2;
			invoiceItem.UnitCount = anzahlKontakte;
			invoiceItem.AmountTotal = anzahlKontakte * invoiceItem.AmountPerUnit;
			invoiceItem.ItemPeriodStart = invoiceItemFLS.ItemPeriodStart;
			invoiceItem.ItemPeriodEnd = invoiceItemFLS.ItemPeriodEnd;
			invoiceItem.RateFactor = 0;
			invoiceItem.GrossAmountTotal = invoiceItem.AmountTotal;

			invoiceItem.ItemDescription = "Fahrtk. ABW";
			if (scap.ApprovedBEPerInterval.HasValue && scap.ApprovedBEInterval.HasValue && scap.ApprovedBEInterval.Value == SupportConceptApprovalInterval.Weekly)
			{
				var approvedFlsWeekly = scap.ApprovedBEPerInterval.Value;
				if (approvedFlsWeekly <= 1)
				{
					invoiceItem.ItemDescription = "Fahrtk. ABW (1/Woche)";
				}
				else if (approvedFlsWeekly < 3)
				{
					invoiceItem.ItemDescription = "Fahrtk. ABW (1,5-2,5/Woche)";
				}
				else
				{
					invoiceItem.ItemDescription = "Fahrtk. ABW (3/Woche)";
				}
			}

			if (scap != null)
				invoiceItem.SupportConceptApprovalPeriodOid = scap.Oid;

			
			return invoiceItem;
		}

		private decimal GetMaxKontakte(SupportConceptApprovalPeriod scap)
		{
			decimal maxKontakte = Decimal.MaxValue;

			if (scap.ContactCountPerInterval.HasValue && scap.ContactCountInterval.HasValue && scap.StartDate.HasValue && scap.EndDate.HasValue)
			{
				var days = scap.EndDate.Value.Subtract(scap.StartDate.Value).Days + 1;

				if (scap.ContactCountInterval.Value == SupportConceptApprovalInterval.Weekly)
				{
					var weeks = days/7;
					maxKontakte = weeks * scap.ContactCountPerInterval.Value;
				}
				else if (scap.ContactCountInterval.Value == SupportConceptApprovalInterval.Monthly)
				{
					var months = days / 30;
					maxKontakte = months * scap.ContactCountPerInterval.Value;
				}



			}
			return maxKontakte;
		}
		
    }
}
