using System;
using System.Linq;
using BeWo.Service.Plugins;
using BS.Shared;
using BeWo.Report;
using BeWo.Report.ReportObjects;
using BeWo.Data.Entities;
using BeWo.Data.Access;
using System.Collections.Generic;
using BS.Shared.Core;
using BS.Shared.Extensions;
using BS.Shared.Services;
using BS.Shared.DataContracts;
using BeWo.Service.DCEntityMapper;

namespace BeWo.HPHBersenbrueck
{
	public partial class Abrechnungsbogen : DevExpress.XtraReports.UI.XtraReport, IBeWoReport<QueryRO>
    {

		public Abrechnungsbogen()
        {
            InitializeComponent();
        }

        public void SetReportDataSource(QueryRO pRO)
        {

            this.bindingSource1.DataSource = CreateDataSource(pRO);
        }

        private QueryRO CreateDataSource(QueryRO ro)
        {
            QueryRO newQueryRo = new QueryRO();


            int customerOid = 0;

            Int32.TryParse(ro.Rows[0].Field1.ToString(), out customerOid);
			DateTime reportingDate;
			if (DateTime.TryParse(ro.Rows[0].Field2.ToString(), out reportingDate))
	        {
				reportingDate = new DateTime(reportingDate.Year, reportingDate.Month, reportingDate.Day);
	        }
	        else
	        {
				reportingDate = DateTime.Now.Date;
	        }

	        IList<SupportConcept> supportConcepts = null;
			
	        if (customerOid == 0)
	        {
				supportConcepts = DAOFactory.GenericDAO.GetAllActive<SupportConcept>();
				
	        }
	        else
	        {
		        var customer = DAOFactory.GenericDAO.LoadByID<Customer>(customerOid);
				supportConcepts = new List<SupportConcept>();
				supportConcepts.AddRange(customer.SupportConcepts.Where(s => s.IsActive == ActivationTypeId.Active));

	        }

			var calc = PluginLoader.FindClass<Calculations>();

            foreach (var sc in supportConcepts)
            {

	            foreach (var c2s in sc.CostBearer2SupportConceptList)
	            {
					if (c2s.StartDate != DateTime.MinValue && c2s.EndDate != DateTime.MaxValue && InDateRange(c2s, reportingDate))
		            {
			            
			            var relDc = MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.MapToNewDC(c2s);


			            DateTime approvedDate = reportingDate;
			            if (c2s.StartDate.Value > approvedDate)
				            approvedDate = c2s.StartDate.Value;
			            if (c2s.EndDate.Value < approvedDate)
				            approvedDate = c2s.EndDate.Value;

						decimal bewilligtProWocheReportingDate = calc.GetApprovedBEPerWeek(relDc, approvedDate) ?? 0;


			            var scRow = new QueryRO.Row();
			            scRow.ChildRows1 = new List<QueryRO.Row>();
			            scRow.Field1 = String.Format("{0}, {1}", sc.Customer.Person.LastName, sc.Customer.Person.FirstName);
			            scRow.Field2 = c2s.CustomerReferenceNumber;
			            scRow.Field3 = String.Format("{0:dd.MM.yyyy} bis {1:dd.MM.yyyy}", c2s.StartDate, c2s.EndDate);

						scRow.Field4 = String.Format("{0:0.##}", bewilligtProWocheReportingDate);
						scRow.Field5 = String.Format("{0:0.##}", bewilligtProWocheReportingDate * 4.3m);

			            newQueryRo.Rows.Add(scRow);



			            var serviceRecordList = DAOFactory.SearchDAO.FindServiceRecords(null, c2s.Oid.Value);

			            var month2TotalSummary = new Dictionary<String, TotalSummary>();

						var groupBookingDict = new Dictionary<long, long>();

			            foreach (var serviceRecord in serviceRecordList)
			            {
				            String key = String.Format("{0:yyyyMM}", serviceRecord.Start);

				            if (!month2TotalSummary.ContainsKey(key))
				            {
					            var total = new TotalSummary();
					            total.startDate = DateTime.MaxValue;
					            total.endDate = DateTime.MinValue;

					            month2TotalSummary.Add(key, total);
				            }

				            TotalSummary ts = month2TotalSummary[key];
				            if (serviceRecord.Start < ts.startDate)
					            ts.startDate = serviceRecord.Start.Value;
				            if (serviceRecord.Start > ts.endDate)
					            ts.endDate = serviceRecord.Start.Value;


				            if (serviceRecord.ServiceDescription.ServiceCategory.IsBillable)
				            {
					            if (!serviceRecord.GroupOid.HasValue || !groupBookingDict.ContainsKey(serviceRecord.GroupOid.Value))
					            {
						            ts.erbrachteStunden += serviceRecord.RoundedDuration;

									if (serviceRecord.GroupOid.HasValue)
									{
										groupBookingDict.Add(serviceRecord.GroupOid.Value, serviceRecord.GroupOid.Value);
									}
					            }
								
				            }

			            }

			            DateTime minDate = c2s.StartDate.Value;
			            DateTime maxDate = c2s.EndDate.Value;

			            decimal totalBewilligt = 0;
			            decimal totalGeleistet = 0;

			            while (minDate < maxDate)
			            {
				            var row = new QueryRO.Row();
				            row.Field1 = String.Format("{0:MMMM yy}", minDate);
				            

							DateTime end = new DateTime(minDate.Year, minDate.Month, 1).AddMonths(1).AddDays(-1);
							if (end > maxDate)
								end = maxDate;

							decimal bewilligtProWocheAktMonat = calc.GetApprovedBEPerWeek(relDc, minDate) ?? 0;

							decimal bew = BerechnetBewilligteStundenMonat(bewilligtProWocheAktMonat, minDate, end);

							row.Field2 = String.Format("{0:0.##}", bewilligtProWocheAktMonat);
				            row.Field3 = String.Format("{0:0.00}", bew);
				            row.Field4 = "0";
				            row.Field5 = String.Format("{0:0.00}", -bew);

				            String key = String.Format("{0:yyyyMM}", minDate);
				            row.Field10 = key;

				            if (month2TotalSummary.ContainsKey(key))
				            {
					            var ts = month2TotalSummary[key];

								decimal bewMonat = BerechnetBewilligteStundenMonat(bewilligtProWocheAktMonat, minDate, end);
					            row.Field4 = String.Format("{0:0.00}", ts.erbrachteStunden / 60);
								row.Field5 = String.Format("{0:0.00}", (ts.erbrachteStunden / 60m)- bewMonat);

					            totalBewilligt += bewMonat;
					            totalGeleistet += ts.erbrachteStunden/60;
				            }
				            else
				            {
					            totalBewilligt += bew;
				            }

				            scRow.ChildRows1.Add(row);

				            minDate = new DateTime(minDate.AddMonths(1).Year, minDate.AddMonths(1).Month, 1);
			            }
			            scRow.Field6 = String.Format("{0:0.00}", totalBewilligt);
						scRow.Field7 = String.Format("{0:0.00}", totalGeleistet);
						scRow.Field8 = String.Format("{0:0.00}", totalGeleistet - totalBewilligt);
		            }
	            }

            }

			



            foreach (var scr in newQueryRo.Rows)
            {
				scr.ChildRows1.Sort((a, b) => a.Field10.ToString().CompareTo(b.Field10));
            }
			newQueryRo.Rows.Sort((a, b) => a.Field1.ToString().CompareTo(b.Field1));
            return newQueryRo;
        }

		private bool InDateRange(CostBearer2SupportConcept c2s, DateTime dt)
		{
			if (c2s.StartDate.Value.AddMonths(-1) < dt && c2s.EndDate.Value >= dt)
			{
				return true;
			}
			return false;
		}

		private decimal BerechnetBewilligteStundenMonat(decimal bewilligtProWoche, DateTime minDate, DateTime maxDate)
		{
			if (minDate.Date.Day == 1 && maxDate.Date.Day == DateTime.DaysInMonth(maxDate.Year, maxDate.Month))
			{
				return bewilligtProWoche*4.3m;
			}

			int days = (int)maxDate.Subtract(minDate).TotalDays + 1;

			return bewilligtProWoche * 4.3m * ((decimal)days/DateTime.DaysInMonth(maxDate.Year, maxDate.Month));
		}

        
    }

    internal class TotalSummary
    {
	    internal DateTime startDate;
		internal DateTime endDate;
        internal decimal bewilligtProWoche;
        internal decimal bewilligtProMonat;
        internal decimal erbrachteStunden;
    }
}
