using System;
using System.Data;
using Ease.Core.Model;
using Ease.Core.DataAccess;
using Ease.Core;
using System.Collections.Generic;
using Ease.Core.Utility;
using HRM.BO;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Data.SqlClient;

namespace HRM.DA
{
    public class ProdBonusProcessService : ServiceTemplate, IProdBonusProcessService
    {
        #region Object Mapping

        private void MapObject(ProdBonusProcess oProdBonusProcess, DataReader oReader)
        {
            base.SetObjectID(oProdBonusProcess, (oReader.GetInt32("ProdBonusProcessID").Value));
            oProdBonusProcess.SalaryMonth = oReader.GetDateTime("SalaryMonth").Value;
            oProdBonusProcess.ProcessDate = oReader.GetDateTime("ProcessDate").Value;

            this.SetObjectState(oProdBonusProcess, ObjectState.Saved);
        }


        protected override T CreateObject<T>(DataReader oReader)
        {
            ProdBonusProcess oProdBonusProcess = new ProdBonusProcess();
            MapObject(oProdBonusProcess, oReader);
            return oProdBonusProcess as T;
        }

        private void MapProdBonusProcessEmpObject(ProdBonusProcessEmp oProdBonusProcessEmp, DataReader oReader)
        {
            SetObjectID(oProdBonusProcessEmp, (oReader.GetInt32("ProdBonusProcessEmpID").Value));
            oProdBonusProcessEmp.EmployeeID = oReader.GetInt32("EmployeeID", 0);
            oProdBonusProcessEmp.Description = oReader.GetString("Description");
            oProdBonusProcessEmp.ProdBonusProcessID = oReader.GetInt32("ProdBonusProcessID", 0);
            oProdBonusProcessEmp.Amount =
                oReader.GetDouble("Amount").Value == 0.0 ? 0.0 : oReader.GetDouble("Amount").Value;
            this.SetObjectState(oProdBonusProcessEmp, ObjectState.Saved);
        }

        private ProdBonusProcessEmp CreateProdBonusProcessEmpObject(DataReader oReader)
        {
            ProdBonusProcessEmp item = new ProdBonusProcessEmp();
            MapProdBonusProcessEmpObject(item, oReader);
            return item;
        }

        protected List<ProdBonusProcessEmp> CreateProdBonusProcessEmpObjects(DataReader oReader)
        {
            List<ProdBonusProcessEmp> oItems = new List<ProdBonusProcessEmp>();
            while (oReader.Read())
            {
                ProdBonusProcessEmp item = CreateProdBonusProcessEmpObject(oReader);
                oItems.Add(item);
            }

            return oItems;
        }

        private void MapProdBonusProcessItemObject(ProdBonusProcessItem oProdBonusProcessItem, DataReader oReader)
        {
            SetObjectID(oProdBonusProcessItem, (oReader.GetInt32("ProdBonusProcessItemID").Value));
            oProdBonusProcessItem.ProdBonusSetupID = oReader.GetInt32("ProdBonusSetupID", 0);
            oProdBonusProcessItem.ProdBonusProcessID = oReader.GetInt32("ProdBonusProcessID", 0);
            oProdBonusProcessItem.EmployeeID = oReader.GetInt32("EmployeeID", 0);
            oProdBonusProcessItem.ProdBonusLineID = oReader.GetInt32("ProdBonusLineID", 0);
            oProdBonusProcessItem.Amount =
                oReader.GetDouble("Amount").Value == 0.0 ? 0.0 : oReader.GetDouble("Amount").Value;
            oProdBonusProcessItem.OTHour =
                oReader.GetDouble("OTHour").Value == 0.0 ? 0.0 : oReader.GetDouble("OTHour").Value;
            oProdBonusProcessItem.AchievePercent = oReader.GetDouble("AchievePercent").Value == 0.0
                ? 0.0
                : oReader.GetDouble("AchievePercent").Value;
            oProdBonusProcessItem.WorkingHour = oReader.GetDouble("WorkingHour").Value == 0.0
                ? 0.0
                : oReader.GetDouble("WorkingHour").Value;
            this.SetObjectState(oProdBonusProcessItem, ObjectState.Saved);
        }

        private ProdBonusProcessItem CreateProdBonusProcessItemObject(DataReader oReader)
        {
            ProdBonusProcessItem item = new ProdBonusProcessItem();
            MapProdBonusProcessItemObject(item, oReader);
            return item;
        }

        protected List<ProdBonusProcessItem> CreateProdBonusProcessItemObjects(DataReader oReader)
        {
            List<ProdBonusProcessItem> oItems = new List<ProdBonusProcessItem>();
            while (oReader.Read())
            {
                ProdBonusProcessItem item = CreateProdBonusProcessItemObject(oReader);
                oItems.Add(item);
            }

            return oItems;
        }

        #endregion

        #region Service Implementation

        #region Get All

        public List<ProdBonusProcess> Get()
        {
            List<ProdBonusProcess> oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.Get(tc));
                oProdBonusProcess = this.CreateObjects<ProdBonusProcess>(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcess;
        }

        #endregion

        #region Get All

        public List<ProdBonusProcess> Get(DateTime dtSalaryMonth)
        {
            List<ProdBonusProcess> oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.Get(tc, dtSalaryMonth));
                oProdBonusProcess = this.CreateObjects<ProdBonusProcess>(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcess;
        }
        public DataSet GetDetailItems(DateTime dtSalaryMonth)
        {
            DataSet oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                oProdBonusProcess = ProdBonusProcessDA.GetDetailItems(tc, dtSalaryMonth);
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception
                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);
                #endregion
            }
            return oProdBonusProcess;
        }
        public List<ProdBonusProcessEmp> GetProdBonusProcessEmps(int nID)
        {
            List<ProdBonusProcessEmp> oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.GetProdBonusProcessEmp(tc, nID));
                oProdBonusProcess = this.CreateProdBonusProcessEmpObjects(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcess;
        }
        public List<ProdBonusProcessEmp> GetAllProdBonusProcessEmps()
        {
            List<ProdBonusProcessEmp> oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.GetAllProdBonusProcessEmps(tc));
                oProdBonusProcess = this.CreateProdBonusProcessEmpObjects(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcess;
        }

        public List<ProdBonusProcessItem> GetProdBonusProcessItems(int nID)
        {
            List<ProdBonusProcessItem> oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.GetProdBonusProcessItem(tc, nID));
                oProdBonusProcess = this.CreateProdBonusProcessItemObjects(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcess;
        }

        public List<ProdBonusProcessItem> GetAllProdBonusProcessItems()
        {
            List<ProdBonusProcessItem> oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.GetAllProdBonusProcessItems(tc));
                oProdBonusProcess = this.CreateProdBonusProcessItemObjects(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcess;
        }

        #endregion

        #region Get Single

        public ProdBonusProcess Get(int id)
        {
            ProdBonusProcess oProdBonusProcess = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.Get(tc, id));
                oProdBonusProcess = this.CreateObject<ProdBonusProcess>(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcess;
        }


        public ProdBonusProcessEmp GetProdBonusEmp(int Id, DateTime salaryMonth)
        {
            ProdBonusProcessEmp oProdBonusProcessEmp = null;
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                DataReader oreader = new DataReader(ProdBonusProcessDA.GetProdBonusEmp(tc, Id, salaryMonth));
                if (oreader.Read())
                    oProdBonusProcessEmp = this.CreateProdBonusProcessEmpObject(oreader);
                oreader.Close();
                tc.End();
            }

            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonusProcessEmp;
        }

        #endregion

        #region Get DataSet For Report

        public DataSet GetMontlyProdBonus(DateTime dBonusMonth)
        {
            DataSet oProdBonus = new DataSet();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                oProdBonus = BonusProcessDA.GetMontlyProdBonus(tc, dBonusMonth);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonus;
        }

        public DataSet GetProdBonusDetail(int designID)
        {
            DataSet oProdBonus = new DataSet();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                oProdBonus = BonusProcessDA.GetProdBonusDetail(tc, designID);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonus;
        }

        public DataSet EmpDesignWiseProdBonus(DateTime dBonusMonth)
        {
            DataSet oProdBonus = new DataSet();

            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin();
                oProdBonus = BonusProcessDA.EmpDesignWiseProdBonus(tc, dBonusMonth);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }

            return oProdBonus;
        }

        #endregion

        #region Insert

        public void Save(List<ProdBonusProcess> items)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                if (items.Count > 0)
                    ProdBonusProcessDA.DeleteBySalaryMonth(tc, items[0].SalaryMonth);
                foreach (ProdBonusProcess item in items)
                {
                    tc.End();
                    item.ProdBonusProcessEmps = new ProdBonusProcessService().GetProdBonusProcessEmps(item.ID);
                    item.ProdBonusProcessItems = new ProdBonusProcessService().GetProdBonusProcessItems(item.ID);

                    tc = TransactionContext.Begin(true);
                    int id = tc.GenerateID("ProdBonusProcess", "ProdBonusProcessID");
                    base.SetObjectID(item, (id));
                    ProdBonusProcessDA.Save(tc, item);
                    foreach (ProdBonusProcessEmp og in item.ProdBonusProcessEmps)
                    {
                        int id1 = tc.GenerateID("ProdBonusProcessEmp", "ProdBonusProcessEmpID");
                        base.SetObjectID(og, (id1));
                        og.ProdBonusProcessID = item.ID;
                        ProdBonusProcessDA.SaveEmp(tc, og);
                    }

                    foreach (ProdBonusProcessItem og in item.ProdBonusProcessItems)
                    {
                        int id1 = tc.GenerateID("ProdBonusProcessItem", "ProdBonusProcessItemID");
                        base.SetObjectID(og, (id1));
                        og.ProdBonusProcessID = item.ID;
                        ProdBonusProcessDA.SaveItem(tc, og);
                    }
                }

                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        public void Save(ProdBonusProcess item)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                ProdBonusProcessDA.DeleteBySalaryMonth(tc, item.SalaryMonth);
                int id = tc.GenerateID("ProdBonusProcess", "ProdBonusProcessID");
                base.SetObjectID(item, (id));
                ProdBonusProcessDA.Save(tc, item);

                DataTable prodemp = new DataTable("ProdBonusProcessEmp");
                prodemp.Columns.Add(new DataColumn("ProdBonusProcessEmpID", typeof(int)));
                prodemp.Columns.Add(new DataColumn("ProdBonusProcessID", typeof(int)));
                prodemp.Columns.Add(new DataColumn("EmployeeID", typeof(int))); // NULL
                prodemp.Columns.Add(new DataColumn("Amount", typeof(double))); // NULL
                prodemp.Columns.Add(new DataColumn("Description", typeof(string)));
                int id1 = tc.GenerateID("ProdBonusProcessEmp", "ProdBonusProcessEmpID");
                foreach (ProdBonusProcessEmp og in item.ProdBonusProcessEmps)
                {
                    id1 = id1 + 1;

                    prodemp.Rows.Add(
                    id1,
                    item.ID,
                    og.EmployeeID,
                    og.Amount,
                    og.Description
                    );

                }

                using (SqlBulkCopy bulkCopy = new SqlBulkCopy((SqlConnection)tc.Connection, SqlBulkCopyOptions.Default, (SqlTransaction)tc.Transaction))
                {
                    bulkCopy.BulkCopyTimeout = 6000; // in seconds
                    bulkCopy.DestinationTableName = "ProdBonusProcessEmp";

                    bulkCopy.WriteToServer(prodemp);
                }


                //foreach (ProdBonusProcessItem og in item.ProdBonusProcessItems)
                //{
                //    int id1 = tc.GenerateID("ProdBonusProcessItem", "ProdBonusProcessItemID");
                //    base.SetObjectID(og, (id1));
                //    og.ProdBonusProcessID = item.ID;
                //    ProdBonusProcessDA.SaveItem(tc, og);
                //}


                DataTable attnProcessEntryTable = new DataTable("ProdBonusProcessItem");
                attnProcessEntryTable.Columns.Add(new DataColumn("ProdBonusProcessItemID", typeof(int)));
                attnProcessEntryTable.Columns.Add(new DataColumn("ProdBonusProcessID", typeof(int)));
                attnProcessEntryTable.Columns.Add(new DataColumn("ProdBonusSetupID", typeof(int)));
                attnProcessEntryTable.Columns.Add(new DataColumn("Amount", typeof(double))); // NULL
                attnProcessEntryTable.Columns.Add(new DataColumn("ProdBonusLineID", typeof(int))); // NULL
                attnProcessEntryTable.Columns.Add(new DataColumn("OTHour", typeof(double)));
                attnProcessEntryTable.Columns.Add(new DataColumn("AchievePercent", typeof(double)));
                attnProcessEntryTable.Columns.Add(new DataColumn("WorkingHour", typeof(double)));
                attnProcessEntryTable.Columns.Add(new DataColumn("EmployeeID", typeof(int))); // NULL
                id1 = tc.GenerateID("ProdBonusProcessItem", "ProdBonusProcessItemID");
                foreach (ProdBonusProcessItem og in item.ProdBonusProcessItems)
                {
                    id1 = id1 + 1;

                    attnProcessEntryTable.Rows.Add(
                    id1,
                    item.ID,
                    og.ProdBonusSetupID,
                    og.Amount,
                    og.ProdBonusLineID,
                    og.OTHour,
                    og.AchievePercent,
                    og.WorkingHour,
                    og.EmployeeID
                    );

                }

                using (SqlBulkCopy bulkCopy = new SqlBulkCopy((SqlConnection)tc.Connection, SqlBulkCopyOptions.Default, (SqlTransaction)tc.Transaction))
                {
                    bulkCopy.BulkCopyTimeout = 6000; // in seconds
                    bulkCopy.DestinationTableName = "ProdBonusProcessItem";
                    bulkCopy.WriteToServer(attnProcessEntryTable);

                }

                new ADParameterEmployeeService().BulkSave(tc, item.ADParamEmps, item.SalaryMonth);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }
        #endregion

        #region Delete

        public void Delete(int id)
        {
            TransactionContext tc = null;
            try
            {
                tc = TransactionContext.Begin(true);
                ProdBonusProcessDA.Delete(tc, id);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        #endregion

        #region Process

        public ProdBonusProcess Process(List<ProductionBonusSetup> _oProductionBonusSetups, DateTime dtpSalaryMonth, int payrollTypeId)
        {
            ProdBonusProcess _oProdBonusProcess = new ProdBonusProcess();
            try
            {
                _oProdBonusProcess.SalaryMonth = GlobalFunctions.LastDateOfMonth(dtpSalaryMonth);
                _oProdBonusProcess.ProcessDate = DateTime.Today;
                _oProdBonusProcess.ProdBonusProcessItems = new List<ProdBonusProcessItem>();
                _oProdBonusProcess.ProdBonusProcessEmps = new List<ProdBonusProcessEmp>();
                List<ProdBonusAttn> prodAttn = null;
                List<ProdBonusProcessEmp> oProcessEmps = new List<ProdBonusProcessEmp>();
                //List<Shift> oShifts = new ShiftService().GetAllShift();
                Shift oShift = null;
                ProdBonusProcessEmp oProcessEmp = null;
                int setupID = 21;
                DateTime? bonusIntime = DateTime.MinValue;
                DateTime? bonusOuttime = DateTime.MinValue;
                ADParameter _ADParam = new ADParameterService().Get(setupID, payrollTypeId);

                List<ProdBonusAttn> prodAttns = new ProdBonusAttnService().GetBySetupIDs(_oProductionBonusSetups.CommaSeparatedIDs());
                 List<ProdBonusSupervisor> allProdBonusSupervisors = 
                    new ProdBonusSupervisorService().GetBySetupLineIDByInSQL(_oProductionBonusSetups.CommaSeparatedIDs()
                  );
                List<DailyAttnProcess> alldailyAttm = new DailyAttnProcessService().GetshotListForProdBonus(_oProductionBonusSetups.CommaSeparatedIDs(), GlobalFunctions.FirstDateOfMonth(_oProdBonusProcess.SalaryMonth.AddMonths(-3)),
                _oProdBonusProcess.SalaryMonth);

                //DataTable empBasic = new EmployeeService().GetBasicSalary(); 
                DataTable empBasic = new EmployeeService().GetBasicSalaryWithDiscontinue(_oProdBonusProcess.SalaryMonth);

                foreach (ProductionBonusSetup oProductionBonusSetup in _oProductionBonusSetups)
                {
                                       
                    prodAttn = prodAttns.Where(x => x.ProdBonusSetupID == oProductionBonusSetup.ID).ToList();//ToObjectsTemplate();
                    ProdBonusProcessItem oProcessItem = null;
                    foreach (ProdBonusLine oLine in oProductionBonusSetup.ProductionBonusLinesNew)
                    {
                        List<ProdBonusAttn> lineAttns = prodAttns.Where(x => x.ProdBonusSetupID == oProductionBonusSetup.ID
                         && x.ProdBonusLineID == oLine.ID).ToList();
                        var gropBonuAttn =
                              from attn in lineAttns
                              group attn by attn.EmployeeID into newGroup
                              orderby newGroup.Key
                              select newGroup;

                        foreach (var item in gropBonuAttn)
                        {
                            double oth = 0;
                            double hour = 0;
                            double basicSal = 0;
                            DataRow[] foundRows = empBasic.Select("EMPLOYEEID =" + item.Key.ToString());
                            if (foundRows != null)
                            {
                                foreach (DataRow dr in foundRows)
                                {
                                    basicSal = Convert.ToDouble(dr["BASICSALARY"]);
                                   
                                }
                            }
                          

                            bool isSuperVisor = allProdBonusSupervisors.FindIndex(x => x.EmployeeID == item.Key
                             && x.ProdBonusLineID == oLine.ID) == -1 ? false : true;
                              List<DailyAttnProcess> dailyAttm = alldailyAttm.FindAll(x => x.EmployeeID == item.Key);
                           
                            if (isSuperVisor == false) 
                            {
                                
                                #region Not Supervisor
                                foreach (var tAtt in item)
                                {
                                    DailyAttnProcess dailyAtt = dailyAttm.FirstOrDefault(o => o.AttnDate.Date == tAtt.InTime.Date);
                                    double wh = 0;
                                    
                                    if (dailyAtt != null)
                                    {
                                        bonusIntime = dailyAtt.InTime;
                                        bonusOuttime = dailyAtt.OutTime;
                                        if (dailyAtt.OutTime != DateTime.MinValue && dailyAtt.InTime != DateTime.MinValue)
                                        {
                                            // oShift = oShifts.FirstOrDefault(x => x.ID == dailyAtt.ShiftID);
                                            if (oProductionBonusSetup.FromDate.Date == dailyAtt.AttnDate.Date)
                                                bonusIntime = oProductionBonusSetup.FromDate > dailyAtt.InTime ? oProductionBonusSetup.FromDate : dailyAtt.InTime;
                                            else if (dailyAtt.InTime.GetValueOrDefault().TimeOfDay < tAtt.InTime.TimeOfDay)
                                                bonusIntime = dailyAtt.InTime.GetValueOrDefault().Date.AddHours(tAtt.InTime.Hour).AddMinutes(tAtt.InTime.Minute);
                                            if (oProductionBonusSetup.ToDate.Date == dailyAtt.AttnDate.Date)
                                                bonusOuttime = oProductionBonusSetup.ToDate < dailyAtt.OutTime ? oProductionBonusSetup.ToDate : dailyAtt.OutTime;
                                            else if (dailyAtt.OutTime.GetValueOrDefault().TimeOfDay > tAtt.OutTime.TimeOfDay)
                                                bonusOuttime = dailyAtt.OutTime.GetValueOrDefault().Date.AddHours(tAtt.OutTime.Hour).AddMinutes(tAtt.OutTime.Minute);
                                            //else if (oShift != null && dailyAtt.InTime.GetValueOrDefault().TimeOfDay < oShift.InTime.TimeOfDay)
                                            //    bonusIntime = dailyAtt.InTime.GetValueOrDefault().Date.AddHours(oShift.InTime.Hour).AddMinutes(oShift.InTime.Minute);

                                            TimeSpan ts = (TimeSpan)(bonusOuttime - bonusIntime);
                                            if (ts.Minutes < 16 && ts.Hours < 5)
                                                wh = ts.Hours;
                                            else if (ts.Minutes < 16)
                                                wh = ts.Hours - 1;
                                            else if (ts.TotalHours < 5)
                                                wh = ts.TotalHours;
                                            else
                                                wh = ts.TotalHours - 1;

                                            hour += wh < 0 ? 0 : wh;
                                        }
                                    }
                                }
                                oth = (double)hour * (double)oProductionBonusSetup.OTHour / (double)oLine.ScheduledHour;
                                if (oth > 0 && !double.IsInfinity(oth))
                                {
                                    oProcessItem = new ProdBonusProcessItem();
                                    oProcessItem.EmployeeID = item.Key;
                                    oProcessItem.OTHour = oth;
                                    
                                                                      
                                    oProcessItem.Amount = Math.Round(((double)basicSal / 208 * oth) * 2, 2);
                                    //if(oProcessItem.EmployeeID == 55388)
                                    //{

                                    //}
                                    //oProcessItem.Amount = Math.Round( (new EmployeeService().Get(item.Key).BasicSalary / 208 * oth) * 2, 2);
                                    oProcessItem.AchievePercent = 0;
                                    oProcessItem.WorkingHour = hour;
                                    oProcessItem.ProdBonusSetupID = oProductionBonusSetup.ID;
                                    oProcessItem.ProdBonusLineID = oLine.ID;
                                    oProcessItem.Description = oProductionBonusSetup.ProgramName;
                                    _oProdBonusProcess.ProdBonusProcessItems.Add(oProcessItem);
                                }
                                #endregion Not Supervisor
                            }
                            else
                            {
                                foreach (ProdBonusAttn tAtt in item)
                                {

                                    DailyAttnProcess dailyAtt = dailyAttm.FirstOrDefault(o => o.AttnDate.Date == tAtt.InTime.Date);
                                    double wh = 0;
                                    if (dailyAtt != null)
                                    {
                                        if (dailyAtt.OutTime != DateTime.MinValue && dailyAtt.InTime != DateTime.MinValue)
                                        {
                                            bonusIntime = dailyAtt.InTime;
                                            bonusOuttime = dailyAtt.OutTime;
                                            //oShift = oShifts.FirstOrDefault(x => x.ID == dailyAtt.ShiftID);

                                            if (oProductionBonusSetup.FromDate.Date == dailyAtt.AttnDate.Date)
                                                bonusIntime = oProductionBonusSetup.FromDate > dailyAtt.InTime ? oProductionBonusSetup.FromDate : dailyAtt.InTime;
                                            else if (dailyAtt.InTime.GetValueOrDefault().TimeOfDay < tAtt.InTime.TimeOfDay)
                                                bonusIntime = dailyAtt.InTime.GetValueOrDefault().Date.AddHours(tAtt.InTime.Hour).AddMinutes(tAtt.InTime.Minute);
                                            if (oProductionBonusSetup.ToDate.Date == dailyAtt.AttnDate.Date)
                                                bonusOuttime = oProductionBonusSetup.ToDate < dailyAtt.OutTime ? oProductionBonusSetup.ToDate : dailyAtt.OutTime;
                                            else if (dailyAtt.OutTime.GetValueOrDefault().TimeOfDay > tAtt.OutTime.TimeOfDay)
                                                bonusOuttime = dailyAtt.OutTime.GetValueOrDefault().Date.AddHours(tAtt.OutTime.Hour).AddMinutes(tAtt.OutTime.Minute);
                                            //else if (oShift != null && dailyAtt.InTime.GetValueOrDefault().TimeOfDay < oShift.InTime.TimeOfDay)
                                            //    bonusIntime = dailyAtt.InTime.GetValueOrDefault().Date.AddHours(oShift.InTime.Hour).AddMinutes(oShift.InTime.Minute);

                                            TimeSpan ts = (TimeSpan)(bonusOuttime - bonusIntime);
                                            if (ts.Minutes < 16 && ts.Hours < 5)
                                                wh = ts.Hours;
                                            else if (ts.Minutes < 16)
                                                wh = ts.Hours - 1;
                                            else if (ts.TotalHours < 5)
                                                wh = ts.TotalHours;
                                            else
                                                wh = ts.TotalHours - 1;

                                            // hour += ts.Hours < 0 ? 0 : ts.Hours;
                                            hour += wh < 0 ? 0 : wh;
                                        }
                                    }
                                }


                                oth = (double)hour * (double)oProductionBonusSetup.OTHour / (double)oLine.ScheduledHour;
                                if (oth > 0 && !double.IsInfinity(oth))
                                {
                                    oProcessItem = new ProdBonusProcessItem();
                                    oProcessItem.EmployeeID = item.Key;
                                    oProcessItem.OTHour = oth;
                                    if (oLine.ProdBonusSupervisors == null)
                                        oLine.ProdBonusSupervisors = allProdBonusSupervisors.FindAll(x => x.ProdBonusSetupID == oProductionBonusSetup.ID
                                        && x.ProdBonusLineID == oLine.ID);
                                    //Amount mismatch hude ammount
                                    //if (oProcessItem.EmployeeID == 27388 || oProcessItem.EmployeeID == 27620 || oProcessItem.EmployeeID == 31161 || oProcessItem.EmployeeID == 1822
                                    //    || oProcessItem.EmployeeID == 36901 || oProcessItem.EmployeeID == 37542 || oProcessItem.EmployeeID == 41160 || oProcessItem.EmployeeID == 44495
                                    //    || oProcessItem.EmployeeID == 44495 || oProcessItem.EmployeeID == 46607 || oProcessItem.EmployeeID == 49783 || oProcessItem.EmployeeID == 55041
                                    //    || oProcessItem.EmployeeID == 55155 || oProcessItem.EmployeeID == 55388)
                                    //{

                                    //}
                                    //if(oProcessItem.EmployeeID == 27620)
                                    //{
                                    //    double x = ((double)oLine.ProdBonusSupervisors.First(o => o.EmployeeID == item.Key).BonusPercent / 100);
                                    //}
                                    oProcessItem.Amount = Math.Round(((double)basicSal / 208 * (double)oth * 
                                        ((double)oLine.ProdBonusSupervisors.First(o => o.EmployeeID == item.Key).BonusPercent / 100)) * 2, 2);
                                    oProcessItem.AchievePercent = 0;
                                    oProcessItem.WorkingHour = hour;
                                    oProcessItem.ProdBonusSetupID = oProductionBonusSetup.ID;
                                    oProcessItem.ProdBonusLineID = oLine.ID;
                                    oProcessItem.Description = oProductionBonusSetup.ProgramName;
                                    _oProdBonusProcess.ProdBonusProcessItems.Add(oProcessItem);
                                }
                            }
                        }

                    }
                }



                var empGroup = _oProdBonusProcess.ProdBonusProcessItems
                                .GroupBy(o => o.EmployeeID)
                                    .Select(x =>
                                            new
                                            {
                                                EmployeeID = x.Key,
                                                Amount = x.Sum(y => y.Amount),
                                                Description = x.Aggregate(new StringBuilder(),
                                                                          (sb, z) => sb.Append(z.Description + ","),
                                                                          sb => sb.ToString().Trim(','))
                                            });
                foreach (var item in empGroup)
                {

                    oProcessEmp = new ProdBonusProcessEmp();
                    oProcessEmp.EmployeeID = item.EmployeeID;
                    //Amount mismatch hude ammount
                    
                    oProcessEmp.Amount = Math.Round((double)item.Amount, 2);
                    oProcessEmp.Description = item.Description;
                    _oProdBonusProcess.ProdBonusProcessEmps.Add(oProcessEmp);

                    #region Effect os Salary
                    ADParameterEmployee adEmp = new ADParameterEmployee();
                    adEmp.EmployeeID = item.EmployeeID;
                    adEmp.ADParameterID = setupID;
                    adEmp.AllowDeductID = _ADParam.AllowDeductID;
                    adEmp.ADEmpType = EnumADEmpType.AppliedToIndividual;
                    adEmp.Periodicity = EnumPeriodicity.OneOff;
                    adEmp.FormDate = GlobalFunctions.FirstDateOfMonth(dtpSalaryMonth);
                    adEmp.TillDate = GlobalFunctions.LastDateOfMonth(dtpSalaryMonth);
                    adEmp.MonthlyAmount = Math.Round((double)item.Amount, 2);
                    adEmp.ValueType = EnumValueType.Amount;
                    adEmp.Arreartype = EnumArrearType.NotPresent;

                    _ADParam.ADParameterEmployees.Add(adEmp);
                    #endregion

                }
                _oProdBonusProcess.ADParamEmps = _ADParam.ADParameterEmployees;
            }
            catch (Exception e)
            {
                #region Handle Exception

                //if (tc != null)
                //    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
            return _oProdBonusProcess;
        }

        #endregion

        #region Undo

        public void UndoProcess(List<ProdBonusProcess> oProdBonusProsses, ADParameter _ADParam, DateTime dtSalaryMonth)
        {
            TransactionContext tc = null;
            try
            {
                //tc = TransactionContext.Begin(true);
                List<ProdBonusProcessEmp> oProdBonusProcessEmps = new ProdBonusProcessService().GetAllProdBonusProcessEmps();
                List<ProdBonusProcessItem> oProdBonusProcessItems = new ProdBonusProcessService().GetAllProdBonusProcessItems();
                //tc.End();
                string empids = "";
                foreach (ProdBonusProcess item in oProdBonusProsses)
                {
                    //item.ProdBonusProcessEmps = new ProdBonusProcessService().GetProdBonusProcessEmps(item.ID);
                    //item.ProdBonusProcessItems = new ProdBonusProcessService().GetProdBonusProcessItems(item.ID);
                    item.ProdBonusProcessEmps = oProdBonusProcessEmps.Where(x=> x.ProdBonusProcessID == item.ID).ToList();
                    item.ProdBonusProcessItems = oProdBonusProcessItems.Where(x => x.ProdBonusProcessID == item.ID).ToList();

                    List<int> employeeIdList = new List<int>();
                    //tc = TransactionContext.Begin(true);
                    foreach (ProdBonusProcessItem processItem in item.ProdBonusProcessItems)
                    {
                        //ADParameterEmployeeDA.DeleteByAllowDeductMonth(tc, processItem.EmployeeID,
                        //    _ADParam.AllowDeductID, dtSalaryMonth);
                        employeeIdList.Add(processItem.EmployeeID);

                    }

                    empids = string.Join(", ", employeeIdList);
                }
                tc = TransactionContext.Begin(true);
                ADParameterEmployeeDA.DeleteByAllowDeductMonth(tc, empids,
                            _ADParam.AllowDeductID, dtSalaryMonth);
                ProdBonusProcessDA.DeleteBySalaryMonth(tc, dtSalaryMonth);
                tc.End();
            }
            catch (Exception e)
            {
                #region Handle Exception

                if (tc != null)
                    tc.HandleError();
                ExceptionLog.Write(e);
                throw new ServiceException(e.Message, e);

                #endregion
            }
        }

        #endregion

        #endregion
    }
}