using System;
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;
using DevExpress.XtraPivotGrid.Data.Wrappers;

namespace BeWo.BetreuWoReports.Kostenstellenauswertung3
{
    public partial class Kostenstellenauswertung : DevExpress.XtraReports.UI.XtraReport, IBeWoReport<QueryRO>
    {
        
        public Kostenstellenauswertung()
        {
            InitializeComponent();
        }

        public void SetReportDataSource(QueryRO pRO)
        {

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

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

            Dictionary<long, QueryRO.Row> customerCareTypes2Row = new Dictionary<long, QueryRO.Row>();
            Dictionary<long, TotalSummary> customerCareTypes2TotalSummary = new Dictionary<long, TotalSummary>();
			Dictionary<String, QueryRO.Row> customer2Row = new Dictionary<String, QueryRO.Row>();
			Dictionary<String, TotalSummary> customer2TotalSummary = new Dictionary<String, TotalSummary>();
			Dictionary<String, QueryRO.Row> emp2Row = new Dictionary<String, QueryRO.Row>();
			Dictionary<String, TotalSummary> emp2TotalSummary = new Dictionary<String, TotalSummary>();

	        CostBearer2SupportConcept cb2scFls = null;
			CostBearer2SupportConcept cb2scAls = null;
			CostBearer2SupportConcept cb2scFud = null;
			CostBearer2SupportConcept cb2scPflege = null;

            int customerCareTypeOid = 0;

            Int32.TryParse(ro.Rows[0].Field3.ToString(), out customerCareTypeOid);

            DateTime startDate = DateTime.Parse(ro.Rows[0].Field1.ToString());
            DateTime endDate = DateTime.Parse(ro.Rows[0].Field2.ToString());
            DateTimeSpan span = new DateTimeSpan();
            span.StartDateTime = startDate;
            span.EndDateTime = endDate;

            var serviceRecordList = DAOFactory.SearchDAO.FindServiceRecordsInSpan(span, null);
            
            IList<Employee> employees = DAOFactory.GenericDAO.GetAllActiveAndArchived<Employee>();
            Dictionary<long, Employee> empDict = new Dictionary<long, Employee>();
            foreach (var item in employees)
            {
                empDict.Add(item.Oid.Value, item);
            }


            IList<Customer> customers = DAOFactory.GenericDAO.GetAllActiveAndArchived<Customer>();
            Dictionary<long, Customer> custDict = new Dictionary<long, Customer>();
            foreach (var item in customers)
            {
                custDict.Add(item.Oid.Value, item);
            }

            TotalSummary totalSummary = new TotalSummary();
            
            foreach (var sr in serviceRecordList)
            {
                //Kategorien: LVR Fachleistung, ALS Assistenz, Hausmeister 0,5, FLS-HD
                if (sr.ServiceDescription != null && (sr.ServiceDescription.ServiceCategory.Oid == 1 || sr.ServiceDescription.ServiceCategory.Oid == 4 ||
					sr.ServiceDescription.ServiceCategory.Oid == 27 || sr.ServiceDescription.ServiceCategory.Oid == 30 || sr.ServiceDescription.ServiceCategory.Name.StartsWith("FuD") || sr.ServiceDescription.ServiceCategory.Name.StartsWith("Pflege")))
                {
                    if (sr.CustomerOid.HasValue && custDict.ContainsKey(sr.CustomerOid.Value) &&
                        empDict.ContainsKey(sr.EmployeeOid.Value))
                    {
                        Customer customer = custDict[sr.CustomerOid.Value];
                        Employee employee = empDict[sr.EmployeeOid.Value];

                        
                        var customerCareTypes = customer.ValueList.FindByType(ValueListEntryType.CustomerCareType);

                        bool addedToTotal = false;
                        foreach (var valueListEntry2Object in customerCareTypes)
                        {
                            if (valueListEntry2Object.Entry.IsActive == ActivationTypeId.Active &&
                                (customerCareTypeOid == 0 ||
                                 customerCareTypeOid == valueListEntry2Object.Entry.Oid.Value))
                            {
                                QueryRO.Row customerCareTypeRow = null;
                                TotalSummary customerCareSummary = null;
                                if (customerCareTypes2Row.ContainsKey(valueListEntry2Object.Entry.Oid.Value))
                                {
                                    customerCareTypeRow = customerCareTypes2Row[valueListEntry2Object.Entry.Oid.Value];
                                    customerCareSummary =
                                        customerCareTypes2TotalSummary[valueListEntry2Object.Entry.Oid.Value];
                                }
                                else
                                {
                                    customerCareTypeRow = new QueryRO.Row();
                                    //customerCareTypeRow.Field1 = String.Format("{0}, {1:dd.MM.yyyy}-{2:dd.MM.yyyy}",
                                    //                                           valueListEntry2Object.Entry.Value,
                                    //                                           startDate, endDate.AddDays(-1));


									//###Hier weitermachen
									customerCareTypeRow.Field1 = String.Format("Kostenstelle: {0}",
										valueListEntry2Object.Entry.Value);
									customerCareTypeRow.Field2 = String.Format("Abfragezeitraum {0:dd.MM.yyyy}-{1:dd.MM.yyyy}",
										startDate, endDate.AddDays(-1));

                                    customerCareTypeRow.ChildRows1 = new List<QueryRO.Row>();
                                    newQueryRo.Rows.Add(customerCareTypeRow);

                                    customerCareTypes2Row[valueListEntry2Object.Entry.Oid.Value] = customerCareTypeRow;

                                    customerCareSummary = new TotalSummary();
                                    customerCareTypes2TotalSummary[valueListEntry2Object.Entry.Oid.Value] =
                                        customerCareSummary;
                                }

								QueryRO.Row empRow = null;
                                TotalSummary empSummary = null;
								String empkey = String.Format("{0}_{1}", employee.Oid, valueListEntry2Object.Entry.Oid);
								if (emp2Row.ContainsKey(empkey))
	                            {
									empRow = emp2Row[empkey];
									empSummary = emp2TotalSummary[empkey];
	                            }
	                            else
	                            {
									empRow = new QueryRO.Row();
									empRow.ChildRows1 = new List<QueryRO.Row>();

									empRow.Field1 = String.Format("{0}, {1}", employee.Person.LastName, employee.Person.FirstName);
									
									customerCareTypeRow.ChildRows1.Add(empRow);

									emp2Row[empkey] = empRow;

									empSummary = new TotalSummary();
									emp2TotalSummary[empkey] = empSummary;
	                            }

	                            QueryRO.Row customerRow = null;
                                TotalSummary customerSummary = null;

	                            String key = String.Format("{0}_{1}", employee.Oid, customer.Oid);
								if (customer2Row.ContainsKey(key))
                                {
									customerRow = customer2Row[key];
									customerSummary = customer2TotalSummary[key];
                                }
                                else
                                {
                                    customerRow = new QueryRO.Row();
									customerRow.Field1 = String.Format("{0}, {1}", customer.Person.LastName, customer.Person.FirstName);

									empRow.ChildRows1.Add(customerRow);

									customer2Row[key] = customerRow;

                                    customerSummary = new TotalSummary();
									customer2TotalSummary[key] = customerSummary;

                                    List<CostBearer2SupportConcept> cbsInSpan = new List<CostBearer2SupportConcept>();
                                    foreach (var sc in customer.SupportConcepts)
                                    {
                                        foreach (var c2s in sc.CostBearer2SupportConceptList)
                                        {
                                            if (c2s.StartDate.HasValue && c2s.EndDate.HasValue && c2s.StartDate.Value < endDate && c2s.EndDate.Value >= startDate)
                                            {
                                                cbsInSpan.Add(c2s);
                                            }

                                        }
                                    }
                                    if (cbsInSpan.Count > 0)
                                    {
                                        foreach (var c2s in cbsInSpan)
                                        {
                                            Calculations calc = Calculations.GetInstance(c2s.CostBearer.ID);
                                            SupportConceptCostBearerRelDC relDC =
                                                MapperFactory.SupportConceptCostBearerRelDC_CostBearer2SupportConcept.
                                                    MapToNewDC(c2s);
                                            decimal approvedHours =
                                                calc.GetApprovedHoursForPeriod(relDC, startDate, endDate.AddDays(-1)) ;

                                            
                                            if (c2s.CostBearer.Organisation.Name.ToLower() == "lvr fls")
                                            {
	                                            cb2scFls = c2s;
                                                customerSummary.bewilligteFls += approvedHours;
												empSummary.bewilligteFls += approvedHours;
                                            }
                                            else if (c2s.CostBearer.Organisation.Name.ToLower() == "lvr als")
                                            {
	                                            cb2scAls = c2s;
	                                            customerSummary.bewilligteAls += approvedHours;
												empSummary.bewilligteAls += approvedHours;
                                            }
											else if (c2s.CostBearer.Organisation.Name.ToLower() == "fud pflegekassen")
											{
												cb2scFud = c2s;
	                                            customerSummary.bewilligteFud += approvedHours;
												empSummary.bewilligteFud += approvedHours;
                                            }
	                                        
                                            else
                                            {
                                                customerSummary.bewilligteSonstige += approvedHours;
												empSummary.bewilligteSonstige += approvedHours;
                                            }
                                        }
                                        
                                    }
                                }

								

	                            if (sr.CostBearer2SupportConcept.CostBearer.Organisation.Name.ToLower() == "lvr fls")
	                            {
		                            cb2scFls = sr.CostBearer2SupportConcept;
									customerSummary.geleisteteFls += sr.RoundedDuration;
									empSummary.geleisteteFls += sr.RoundedDuration;
								}
								else if (sr.CostBearer2SupportConcept.CostBearer.Organisation.Name.ToLower() == "lvr als")
								{
									cb2scAls = sr.CostBearer2SupportConcept;
									customerSummary.geleisteteAls += sr.RoundedDuration;
									empSummary.geleisteteAls += sr.RoundedDuration;
								}
								else if (sr.CostBearer2SupportConcept.CostBearer.Organisation.Name.ToLower() == "fud pflegekassen")
								{
									cb2scFud = sr.CostBearer2SupportConcept;
									customerSummary.geleisteteFud += sr.RoundedDuration;
									empSummary.geleisteteFud += sr.RoundedDuration;
								}
								else
								{
									customerSummary.geleisteteSonstige += sr.RoundedDuration;
									empSummary.geleisteteSonstige += sr.RoundedDuration;
								}


								
                                customerSummary.countTotal++;
                                customerSummary.geleistetGesamt += sr.RoundedDuration;
                                //customerSummary.personalKosten += (sr.RoundedDuration/60)*hourlyRate;

								empSummary.countTotal++;
								empSummary.geleistetGesamt += sr.RoundedDuration;
								//empSummary.personalKosten += (sr.RoundedDuration / 60) * hourlyRate;

                                customerCareSummary.countTotal++;
								customerCareSummary.geleistetGesamt += sr.RoundedDuration;
								//customerCareSummary.personalKosten += (sr.RoundedDuration / 60) * hourlyRate;


                                if (!addedToTotal)
                                {
                                    totalSummary.countTotal++;
									totalSummary.geleistetGesamt += sr.RoundedDuration;
									//totalSummary.personalKosten += (sr.RoundedDuration / 60) * hourlyRate;
                                    addedToTotal = true;
                                }
                            }
                        }
                    }
                }
            }

			
	        decimal hourlyRateFls = GetHourlyRate(cb2scFls, startDate);
			decimal hourlyRateAls = GetHourlyRate(cb2scAls, startDate);
			decimal hourlyRateFud = GetHourlyRate(cb2scFud, startDate);
			decimal hourlyRatePflege = GetHourlyRate(cb2scPflege, startDate);

			decimal rateFactorFls = GetRateFactor(cb2scFls, startDate);
			decimal rateFactorAls = GetRateFactor(cb2scAls, startDate);
			decimal rateFactorFud = GetRateFactor(cb2scFud, startDate);
			decimal rateFactorPflege = GetRateFactor(cb2scPflege, startDate);

			foreach (var totalSummaryKey in customer2TotalSummary.Keys)
			{
				QueryRO.Row customerRow = customer2Row[totalSummaryKey];
				TotalSummary ts = customer2TotalSummary[totalSummaryKey];

				ts.einnahmeFls = Math.Round(ts.geleisteteFls / 60, 2, MidpointRounding.AwayFromZero) * hourlyRateFls *
								 rateFactorFls;
				ts.einnahmeAls = Math.Round(ts.geleisteteAls / 60, 2, MidpointRounding.AwayFromZero) * hourlyRateAls *
								 rateFactorAls;
				ts.einnahmeFud = Math.Round(ts.geleisteteFud / 60, 2, MidpointRounding.AwayFromZero) * hourlyRateFud *
								 rateFactorFud;
				ts.einnahmePflege = Math.Round(ts.geleistetePflege / 60, 2, MidpointRounding.AwayFromZero) * hourlyRatePflege *
								 rateFactorPflege;

				//DateTime end = sr.Start.Value.AddMinutes((double)sr.RoundedDuration);

				customerRow.Field2 = String.Format("{0:0.00}", ts.geleisteteFls / 60);
				customerRow.Field3 = String.Format("{0:0.00}", ts.einnahmeFls);

				customerRow.Field4 = String.Format("{0:0.00}", ts.geleisteteAls / 60);
				customerRow.Field5 = String.Format("{0:0.00}", ts.einnahmeAls);

				customerRow.Field6 = String.Format("{0:0.00}", ts.geleisteteFud / 60);
				customerRow.Field7 = String.Format("{0:0.00}", ts.einnahmeFud);

				customerRow.Field8 = String.Format("{0:0.00}", ts.geleistetePflege / 60);
				customerRow.Field9 = String.Format("{0:0.00}", ts.einnahmePflege);

			}

			foreach (var totalSummaryKey in emp2TotalSummary.Keys)
			{
				QueryRO.Row row = emp2Row[totalSummaryKey];
				TotalSummary ts = emp2TotalSummary[totalSummaryKey];

				ts.einnahmeFls = Math.Round(ts.geleisteteFls / 60, 2, MidpointRounding.AwayFromZero) * hourlyRateFls *
								 rateFactorFls;
				ts.einnahmeAls = Math.Round(ts.geleisteteAls / 60, 2, MidpointRounding.AwayFromZero) * hourlyRateAls *
								 rateFactorAls;
				ts.einnahmeFud = Math.Round(ts.geleisteteFud / 60, 2, MidpointRounding.AwayFromZero) * hourlyRateFud *
								 rateFactorFud;
				ts.einnahmePflege = Math.Round(ts.geleistetePflege / 60, 2, MidpointRounding.AwayFromZero) * hourlyRatePflege *
								 rateFactorPflege;

				
				row.Field2 = String.Format("{0:0.00}", ts.geleisteteFls / 60);
				row.Field3 = String.Format("{0:0.00}", ts.einnahmeFls);

				row.Field4 = String.Format("{0:0.00}", ts.geleisteteAls / 60);
				row.Field5 = String.Format("{0:0.00}", ts.einnahmeAls);

				row.Field6 = String.Format("{0:0.00}", ts.geleisteteFud / 60);
				row.Field7 = String.Format("{0:0.00}", ts.einnahmeFud);

				row.Field8 = String.Format("{0:0.00}", ts.geleistetePflege / 60);
				row.Field9 = String.Format("{0:0.00}", ts.einnahmePflege);

				row.Field10 = String.Format("{0:0.00}", ts.einnahmeFls + ts.einnahmeAls + ts.einnahmeFud + ts.einnahmePflege);
				


				decimal betragProStundeBrutto = 0;

				long empoid = Int64.Parse(totalSummaryKey.Split('_')[0]);
				var employee = empDict[empoid];

				Contract contract = employee.GetValidContractForDate(endDate);

				if (contract != null)
				{
					var hourlyRate = contract.HourlyRate ?? 0;
					var weeklyHours = contract.WeeklyTotalHours ?? 0;

					var betragProMonat = hourlyRate*weeklyHours*4.35m;

					if (contract.EmploymentType != null && !String.IsNullOrEmpty(contract.EmploymentType.Name))
					{
						decimal sonderzahlung = 0;
						decimal sozialversicherung = 1;
						decimal personalnebenkosten = 1;
						if (contract.EmploymentType.Name.ToLower().EndsWith("gfb"))
						{
							sozialversicherung = 1.30m;
							personalnebenkosten = 1.30m;
						}
						else //if (contract.EmploymentType.Name.ToLower().EndsWith("vz") || contract.EmploymentType.Name.ToLower().EndsWith("tz"))
						{
							sonderzahlung = betragProMonat*0.75m;

							sozialversicherung = 1.214m;
							personalnebenkosten = 1.2m;
						}

						decimal betragProJahr = (betragProMonat*12) + sonderzahlung;
						decimal betragProStunde = (betragProJahr/12)/(weeklyHours*4.35m);
						betragProStundeBrutto = betragProStunde*sozialversicherung*personalnebenkosten;
					}

					ts.personalKosten = (ts.geleistetGesamt / 60) *betragProStundeBrutto;
				}

				row.Field11 = String.Format("{0:0.00}", ts.personalKosten);
			}

            foreach (var totalSummaryKey in customerCareTypes2TotalSummary.Keys)
            {
                QueryRO.Row customerCareTypeRow = customerCareTypes2Row[totalSummaryKey];
                TotalSummary ts = customerCareTypes2TotalSummary[totalSummaryKey];

				
	            if (customerCareTypeRow.ChildRows1 != null)
	            {
					foreach (var row in customerCareTypeRow.ChildRows1)
					{
						ts.einnahmeFls += Decimal.Parse(row.Field3.ToString());
						ts.einnahmeAls += Decimal.Parse(row.Field5.ToString());
						ts.einnahmeFud += Decimal.Parse(row.Field7.ToString());
						ts.einnahmePflege += Decimal.Parse(row.Field9.ToString());
					}
	            }
                //DateTime end = sr.Start.Value.AddMinutes((double)sr.RoundedDuration);
                
                customerCareTypeRow.Field3 = String.Format("{0:0.00}", ts.einnahmeFls);
				customerCareTypeRow.Field4 = String.Format("{0:0.00}", ts.einnahmeAls);
				customerCareTypeRow.Field5 = String.Format("{0:0.00}", ts.einnahmeFud);
				customerCareTypeRow.Field6 = String.Format("{0:0.00}", ts.einnahmePflege);
				customerCareTypeRow.Field7 = String.Format("{0:0.00}", ts.einnahmeFls + ts.einnahmeAls + ts.einnahmeFud + ts.einnahmePflege);

				//customerCareTypeRow.Field8 = String.Format("{0:c}", ts.personalKosten);
            }

            

			//lblTotalSummary.Text = String.Format("FLS Gesamt: {0:0.00}, Gesamtbetrag: {1:c}", totalSummary.geleistetGesamt / 60,
			//									 totalSummary.personalKosten);

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

            return newQueryRo;
        }

		private decimal GetRateFactor(CostBearer2SupportConcept cb2sc, DateTime date)
		{
			if (cb2sc != null)
			{
				var costRateDcs =
					MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(cb2sc.CostBearer.CostRatePeriods);

				var rfcr = costRateDcs.GetCostRatePeriodForDate(CostRatePeriodType.RateFactor, date);
				if (rfcr != null && rfcr.CostRateValue.HasValue)
				{
					return (rfcr.CostRateValue.Value + 100m)/100m;

				}
			}
			return 1;
		}

		private decimal GetHourlyRate(CostBearer2SupportConcept cb2sc, DateTime date)
		{
			if (cb2sc != null)
			{
				var costRateDcs =
					MapperFactory.CostRatePeriodDC_CostRatePeriod.MapToNewDCs(cb2sc.CostBearer.CostRatePeriods);

				var cr = costRateDcs.GetCostRatePeriodForDate(CostRatePeriodType.HourlyRate, date);
				if (cr != null && cr.CostRateValue.HasValue)
				{
					return cr.CostRateValue.Value;
				}
			}
			return 0;
		}

        private QueryRO.Row CreateMonatsRow(DateTime dt)
        {
            QueryRO.Row row = new QueryRO.Row();

            row.Field1 = String.Format("{0:MMM yyyy}", dt);

            row.ChildRows2 = new List<QueryRO.Row>();

            return row;
        }

        

    }

    internal class TotalSummary
    {
        internal decimal geleisteteFls;
		internal decimal bewilligteFls;
		internal decimal einnahmeFls;
		internal decimal geleisteteAls;
		internal decimal bewilligteAls;
		internal decimal einnahmeAls;
		internal decimal geleisteteFud;
		internal decimal bewilligteFud;
		internal decimal einnahmeFud;
		internal decimal geleistetePflege;
		internal decimal bewilligtePflege;
		internal decimal einnahmePflege;
		internal decimal geleisteteSonstige;
		internal decimal bewilligteSonstige;
		internal decimal einnahmeSonstige;
		internal decimal geleistetGesamt;
		internal decimal personalKosten;

        internal int countTotal;
        
    }
}
