using System.Collections.Generic;
using LHDN.CRM.Models.ViewModels;
using System.Data;
using System.Linq;
using LHDN.CRM.Models.Models;
using System;
using System.Reflection;
using LHDN.CRM.BC.Common;
using System.Transactions;

namespace LHDN.CRM.BC.Services
{
    public class TaxPayerService : ServiceBase<Models.ViewModels.TaxPayerViewModel>
    {
        private Repositories.TaxPayerRepository repo = new Repositories.TaxPayerRepository();
        private Services.UserProfileService userSvc = new Services.UserProfileService();

        public TaxPayerViewModel GetById(long TPID)
        {
            TaxPayerViewModel tp = null;
            tp = repo.GetTaxPayer(TPID);

            if (tp == null)
            {
                throw new NotFoundException("Tax payer not found!");
            }

            if (!VerifyUserBranch(Constant.TableType.TaxPayer, tp.VIPCode, tp.CWPenaksiranCPID,
                                tp.CWPungutanCKHTID, tp.CWPenaksiranCKHTID,
                                tp.CWPungutanCPID, tp.CWGuamanSivilID))
            {
                throw new PageAccessUnauthorizedException(String.Format(Constant.ExceptionMessages.TPProfileAccess, tp.TPID));
            }
            //int intCWPenaksiranCPID = tp.CWPenaksiranCPID.HasValue ? tp.CWPenaksiranCPID.Value : 0;
            //int intCWPungutanCKHTID = tp.CWPungutanCKHTID.HasValue ? tp.CWPungutanCKHTID.Value : 0;
            //int intCWPenaksiranCKHTID = tp.CWPenaksiranCKHTID.HasValue ? tp.CWPenaksiranCKHTID.Value : 0;
            //int intCWPungutanCPID = tp.CWPungutanCPID.HasValue ? tp.CWPungutanCPID.Value : 0;
            //int intCWGuamanSivilID = tp.CWGuamanSivilID.HasValue ? tp.CWGuamanSivilID.Value : 0;

            //UserInfoViewModel user = userSvc.UserInfo;
            //int intBranchID = 0;
            //if (user.Unit.Branch != null)
            //    intBranchID = user.Unit.Branch.UnitID;
            //List<BranchListViewModel> lstBranch = new List<BranchListViewModel>();
            //lstBranch = userSvc.GetBranchByHierarchy(userSvc.UserInfo.Unit.UnitID);
            //if (!Utilities.VerifyUserAccessToViewTP(Constant.TableType.TaxPayer, user, lstBranch, tp.VIPCode,
            //                                        intCWPenaksiranCPID, intCWPenaksiranCKHTID, intCWPungutanCPID,
            //                                        intCWPungutanCKHTID, intCWGuamanSivilID))
            //{
            //    throw new PageAccessUnauthorizedException(String.Format(Constant.ExceptionMessages.TPProfileAccess, tp.TPID));
            //}

            return tp;
        }

        public bool VerifyUserBranch(Constant.TableType enumPageType, string TPBranchCode, int? CWPenaksiranCPID, int? CWPenaksiranCKHTID, int? CWPungutanCPID,
                                                    int? CWPungutanCKHTID,
                                                    int? CWGuamanSivilID)
        {
            bool blnIsValid = false;
            int intCWPenaksiranCPID = CWPenaksiranCPID.HasValue ? CWPenaksiranCPID.Value : 0;
            int intCWPungutanCKHTID = CWPenaksiranCKHTID.HasValue ? CWPenaksiranCKHTID.Value : 0;
            int intCWPenaksiranCKHTID = CWPungutanCPID.HasValue ? CWPungutanCPID.Value : 0;
            int intCWPungutanCPID = CWPungutanCKHTID.HasValue ? CWPungutanCKHTID.Value : 0;
            int intCWGuamanSivilID = CWGuamanSivilID.HasValue ? CWGuamanSivilID.Value : 0;

            UserInfoViewModel user = userSvc.UserInfo;
            int intBranchID = 0;
            if (user.Unit.Branch != null)
                intBranchID = user.Unit.Branch.UnitID;
            List<BranchListViewModel> lstBranch = new List<BranchListViewModel>();
            lstBranch = userSvc.GetBranchByHierarchy(userSvc.UserInfo.Unit.UnitID);
            if (Utilities.VerifyUserAccessToViewTP(enumPageType, user, lstBranch, TPBranchCode,
                                                   intCWPenaksiranCPID, intCWPenaksiranCKHTID, intCWPungutanCPID,
                                                   intCWPungutanCKHTID, intCWGuamanSivilID))
            {
                blnIsValid = true;
            }

            return blnIsValid;
        }

        public List<ChangeHistoryUpdateViewModel> SaveInOutBoundDetails(TaxPayerUpdateViewModel model, string strUserName, string strUserID, DateTime dtUpdated)
        {
            int i = 0;
            List<ChangeHistoryUpdateViewModel> lst = null;

            // Retrieve orginal records for audit and change history 
            TaxPayerViewModel oriTP = GetById(Convert.ToInt32(model.TaxpayerCorrespondence.TPID));

            // Check for update conflict
            if (!Utilities.CompareByteArray(model.TaxpayerCorrespondence.ChangeStamp, oriTP.ChangeStamp))
            {
                //TODO Update conflict
                throw new Exception("Update Conflict!");
            }

            foreach (ChangeHistoryUpdateViewModel changeHistoryItem in model.ChangeHistory)
            {
                //Get object original value
                var obj = Utilities.GetPropertyValue(oriTP, changeHistoryItem.FieldName);

                string oriValue = obj != null ? obj.ToString() : "";
                changeHistoryItem.OldValue = oriValue;
                changeHistoryItem.IsChanged = !(changeHistoryItem.OldValue == changeHistoryItem.NewValue);
            }

            // TODO : Transaction Scope
            using (var scope = new TransactionScope(TransactionScopeOption.Required))
            {
                i = repo.SaveBoundDetail(model.TaxpayerCorrespondence, strUserName, strUserID, dtUpdated);
                lst = InsertChangeHistory(model.ChangeHistory, strUserName, strUserID, dtUpdated);
                scope.Complete();
            }

            return lst;
        }

        public List<ChangeHistoryUpdateViewModel> InsertChangeHistory(List<ChangeHistoryUpdateViewModel> model, string strUserName, string strUserID, DateTime dtUpdated)
        {
            int intReturnValue = 0;
            List<ChangeHistoryUpdateViewModel> lst = model.Where(x => x.IsChanged).ToList();
            intReturnValue = repo.InsertChangeHistory(lst, strUserName, strUserID, dtUpdated);

            return lst;
        }

        public List<ChangeHistoryViewModel> GetChangesHistory(ChangeHistoryPagedListViewModel paging, out int intCount)
        {
            intCount = 0;

            DataSet ds = repo.GetChangesHistory(paging.SortExpression, paging.PageIndex, paging.Length,
                                            paging.TPID, paging.ActivityID, paging.CaseID, paging.ReMSDataID, paging.JenisKempenID, paging.EmailDataID, paging.FieldName, paging.LastUpdatedBy, paging.DateFrom, paging.DateTo);

            List<ChangeHistoryViewModel> lstChangeHistoryVM = new List<ChangeHistoryViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstChangeHistoryVM = repo.DataTableToList<ChangeHistoryViewModel>(ds.Tables[0]).ToList();
                if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0)
                    intCount = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());
            }

            return lstChangeHistoryVM;

            //return repo.GetChangesHistory(TPID, ActivityID, CaseID);
        }

        public CountCaseOutboundHeaderViewModel GetCountHeaderDetailByID(long TPID)
        {
            return repo.GetHeaderCountDetailByID(TPID);
        }

        public List<TPForActivityViewModel> SearchTaxPayer(ActSearchTPViewModel model)
        {
            List<TPForActivityViewModel> lstTP = new List<TPForActivityViewModel>();
            lstTP = repo.SearchTaxPayer(model.IDTypeID, model.IDNo, null, null,model.NoCukai);
            if (lstTP != null)
            {
                foreach (TPForActivityViewModel objTP in lstTP)
                {
                    // Check if user contains access to view verification tab
                    if (VerifyUserBranch(Constant.TableType.Activity, objTP.VIPCode, objTP.CWPenaksiranCPID,
                                objTP.CWPungutanCKHTID, objTP.CWPenaksiranCKHTID,
                                objTP.CWPungutanCPID, objTP.CWGuamanSivilID))
                    {
                        objTP.ViewVerificationTab = true;
                    }
                }
            }

            return lstTP;
        }

        //public TPForActivityViewModel GetDummyTPByTPID(long lngTPID)
        //{
        //    TPForActivityViewModel vmTP;
        //    vmTP = repo.GetTPForActivity(lngTPID);
        //    vmTP.ViewVerificationTab = false;
        //    //if (vmTP != null)
        //    //{
        //    //    foreach (TPForActivityViewModel objTP in lstTP)
        //    //    {
        //    //        // Check if user contains access to view verification tab
        //    //        if (VerifyUserBranch(Constant.TableType.Activity, objTP.VIPCode, objTP.CWPenaksiranCPID,
        //    //                    objTP.CWPungutanCKHTID, objTP.CWPenaksiranCKHTID,
        //    //                    objTP.CWPungutanCPID, objTP.CWGuamanSivilID))
        //    //        {
        //    //            objTP.ViewVerificationTab = true;
        //    //        }
        //    //    }
        //    //}

        //    return vmTP;
        //}


        public DropdownViewModel GetDropdown()
        {
            List<LookupParam> _lst = null;
            List<LookupParamSys> _lstsys = null;
            _lst = AdminService.LookupParams;
            _lstsys = AdminService.LookupParamSys;

            DropdownViewModel ddlVM = new DropdownViewModel();
            ddlVM.MainKategoriOptions = AdminService.Kategoris.Where(x => x.IsActive == true).ToList<MainKategori>();
            ddlVM.ActChannelOptions = AdminService.ActivityChannels.ToList<ActivityChannel>();
            ddlVM.AliranOptions = _lst.Where(x => x.LookupCode == "Aliran" && x.IsActive == true)
                                .Select(x => new DropdownDetailViewModel
                                {
                                    Value = x.LookupParamID,
                                    Text = x.ParamDesc,
                                    IsDefault = x.IsDefault,
                                    Code = x.LookupValue
                                }).ToList();
            ddlVM.ActStatusOptions = _lst.Where(x => x.LookupCode == "ActivityStatus" && x.IsActive == true)
                                .Select(x => new DropdownDetailViewModel
                                {
                                    Value = x.LookupParamID,
                                    Text = x.ParamDesc,
                                    IsDefault = x.IsDefault,
                                    Code = x.LookupValue
                                }).ToList();

            ddlVM.JenisLejarOptions = _lstsys.Where(x => x.LookupCode == "JenisLejer")
                                    .Select(x => new DropdownDetailViewModel
                                    {
                                        Value = x.LookupParamSysID,
                                        Text = x.ParamDesc
                                    }).ToList();

            ddlVM.JenisKempenOptions = AdminService.JenisKempens.Where(x => x.JenisKempenKategoriSysID != 26 && x.IsActive == true) //exclude KempenHCL
                                                    .Select(x => new DropdownDetailViewModel
                                                    {
                                                        Value = x.JenisKempenID,
                                                        Text = x.JenisKempenName
                                                    }).ToList();
            ddlVM.OutboundCampaignOption = AdminService.OutboundCampaign.Select(x => new DropdownDetailViewModel
            {
                Value = x.CampaignID,
                Text = x.CampaignName
            }).ToList();

            ddlVM.OutboundStatusOption = _lstsys.Where(x => x.LookupCode == "OutboundStatus").Select(x => new DropdownDetailViewModel
            {
                Value = x.LookupParamSysID,
                Text = x.ParamDesc
            }).ToList();

            return ddlVM;
        }

        public List<OutboundTabPageListViewModel> GetOutboundListByTP(OutboundTabPageListViewModel paging, out int intCount)
        {
            intCount = 0;

            DataSet ds = repo.GetOuboundList(paging);

            List<OutboundTabPageListViewModel> lst = new List<OutboundTabPageListViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lst = repo.DataTableToList<OutboundTabPageListViewModel>(ds.Tables[0]).ToList();
                if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0)
                    intCount = Convert.ToInt32(ds.Tables[1].Rows[0][0].ToString());//Demo
            }

            return lst;
        }

        public TPAdditionalDataViewModel GetAdditionalDataByTP(TaxPayerParamViewModel model)
        {
            TPAdditionalDataViewModel vm = repo.GetAdditionalDataByTP(model);
            if (vm != null)
            {
                vm.Jantina = AdminService.LookupParams.Where(x => x.LookupCode == "Jantina" && x.IsActive == true && x.LookupValue == vm.JantinaCode).Select(x => x.ParamDesc).FirstOrDefault();
                vm.StatusKahwin = AdminService.LookupParams.Where(x => x.LookupCode == "Marital" && x.IsActive == true && x.LookupValue == vm.StatusKahwinCode).Select(x => x.ParamDesc).FirstOrDefault();
                vm.Warganegara = AdminService.LookupParams.Where(x => x.LookupCode == "Negara" && x.IsActive == true && x.LookupValue == vm.WarganegaraCode).Select(x => x.ParamDesc).FirstOrDefault();
                vm.NegaraMastautin = AdminService.LookupParams.Where(x => x.LookupCode == "Negara" && x.IsActive == true && x.LookupValue == vm.NegaraCode).Select(x => x.ParamDesc).FirstOrDefault();


                if (vm.FailPenduaList != null)
                {
                    foreach (TPFailPenduaViewModel item in vm.FailPenduaList)
                    {
                        item.JenisPengenalan = AdminService.LookupParams.Where(x => x.LookupCode == "JenisPengenalan" && x.IsActive == true && x.LookupValue == item.JenisPengenalanCode).Select(x => x.ParamDesc).FirstOrDefault();
                    }
                }
            }
            return vm;
        }

        public List<TPRingkasanByrBalikViewModel> GetRingkasanBayaranBalikTP(TaxPayerParamViewModel model)
        {
            List<TPRingkasanByrBalikViewModel> lst = repo.GetRingkasanBayaranBalikTP(model);

            return lst;
        }

        public List<TPLejerViewModel> GetLejerDataByTP(TaxPayerParamViewModel model)
        {
            List<TPLejerViewModel> lst = repo.GetLejerDataByTP(model);

            return lst;
        }

        public List<TPLejerViewModel> GetRingkasanLejerByTP(TaxPayerParamViewModel model)
        {
            List<TPLejerViewModel> lst = repo.GetRingkasanLejerByTP(model);

            return lst;
        }

        public List<TPKawalTerimaBorangViewModel> GetKawalBorangDataByTP(TaxPayerParamViewModel model)
        {
            List<TPKawalTerimaBorangViewModel> lst = repo.GetKawalBorangDataByTP(model);

            return lst;
        }

        public List<TPAnsuranViewModel> GetAllAnsuranByTP(TaxPayerParamViewModel model)
        {
            List<TPAnsuranViewModel> lst = repo.GetAllAnsuranByTP(model);

            return lst;
        }

        public List<TPAnggaranViewModel> GetAllAnggaranByTP(TaxPayerParamViewModel model)
        {
            List<TPAnggaranViewModel> lst = repo.GetAllAnggaranByTP(model);

            return lst;
        }

        public List<TPRingkasanTaksiranViewModel> GetRingkasanTaksiranByTP(TaxPayerParamViewModel model)
        {
            List<TPRingkasanTaksiranViewModel> lst = repo.GetRingkasanTaksiranByTP(model);

            return lst;
        }


        public TPPungutanCPViewModel GetPungutanCPbyTP(TaxPayerParamViewModel model)
        {
            int intTPFileTypeID = AdminService.TPFileType.Where(x => x.TPFileTypePrefix.Any(y => y.TPFileTypePrefix == model.NoCukaiCode)).Select(x => x.TPFileTypeID).FirstOrDefault();

            TPPungutanCPViewModel vm = null;

            if (intTPFileTypeID != 2 && intTPFileTypeID != 3) //Non Company
            {
                vm = repo.GetPungutanCPbyTPForNC(model.NoCukaiSTS);
            }
            else if (intTPFileTypeID == 2)
            {

                vm = repo.GetPungutanCPbyTPForCompany(model.NoCukaiSTS);
            }

            return vm;
        }

        public TPPungutanCKHTViewModel GetPungutanCKHTbyTP(TaxPayerParamViewModel model)
        {
            int intTPFileTypeID = AdminService.TPFileType.Where(x => x.TPFileTypePrefix.Any(y => y.TPFileTypePrefix == model.NoCukaiCode)).Select(x => x.TPFileTypeID).FirstOrDefault();

            TPPungutanCKHTViewModel vm = null;

            if (intTPFileTypeID == 1 || intTPFileTypeID == 4) //Non Company
            {
                vm = repo.GetPungutanCKHTbyTPForNC(model.NoCukaiSTS);
            }

            return vm;
        }

        public List<TPStatusBayaranBalikViewModel> GetStatusBayaranBalikbyTP(TaxPayerParamViewModel model)
        {
            List<TPStatusBayaranBalikViewModel> lst = repo.GetStatusBayaranBalikbyTP(model);

            return lst;

        }

        public List<LanguageResponseViewModel> GetLanguageRequest(LanguageRequestViewModel LanguageRequest)
        {
            List<LanguageResponseViewModel> LanguageVM = new List<LanguageResponseViewModel>();
            LanguageVM = repo.GetLanguageRequest(LanguageRequest);

            return LanguageVM;
        }

        public List<VerifyResponseViewModel> GetVerifyRequest(VerifyRequestViewModel VerifyRequest)
        {
            List<VerifyResponseViewModel> VerifyVM = new List<VerifyResponseViewModel>();
            VerifyVM = repo.GetVerifyRequest(VerifyRequest);

            return VerifyVM;
        }

        public BlacklistResponseViewModel GetBlacklistRequest(BlacklistRequestViewModel BlacklistRequest)
        {
            BlacklistResponseViewModel BlackListVM = new BlacklistResponseViewModel();
            BlackListVM = repo.GetBlacklistRequest(BlacklistRequest);

            return BlackListVM;
        }

        public List<ServiceVerificationResponseViewModel> GetServiceVerificationRequest(ServiceVerificationRequestViewModel ServiceVerificationRequest)
        {
            List<ServiceVerificationResponseViewModel> VerifyVM = new List<ServiceVerificationResponseViewModel>();
            VerifyVM = repo.GetServiceVerificationRequest(ServiceVerificationRequest);
            return VerifyVM;
        }

        public List<HotlineResponseViewModel> GetHotlineRequest(HotlineRequestViewModel HotlineRequest)
        {
            List<HotlineResponseViewModel> HotlineVM = new List<HotlineResponseViewModel>();
            HotlineVM = repo.GetHotlineRequest(HotlineRequest);
            return HotlineVM;
        }

        public TaxPayerViewModel GetLanguageID(UpdateLanguageRequestViewModel model)
        {
            TaxPayerViewModel vm = null;
            vm = repo.GetLanguageID(model);
            return vm;
        }

        public List<ChangeHistoryUpdateViewModel> UpdateLanguageID(UpdateLanguageRequestViewModel model, string strUserName, string strUserID, DateTime dtUpdated, out int intCount)
        {
            int i = 0;
            List<ChangeHistoryUpdateViewModel> lst = new List<ChangeHistoryUpdateViewModel>();

            // Retrieve orginal records for audit and change history
            TaxPayerViewModel ori = GetLanguageID(model);

            if (ori != null)
            {
                ChangeHistoryUpdateViewModel changeHistoryItem = new ChangeHistoryUpdateViewModel();
                changeHistoryItem.ID = ori.TPID;
                changeHistoryItem.FieldName = "LanguageID";
                changeHistoryItem.DisplayName = "Language Preference"; //  = Field name column in tp_change history
                changeHistoryItem.OldValue = ori.LanguageID ==null ? "":ori.LanguageID.ToString();
                changeHistoryItem.NewValue = model.LanguageID.ToString();
                changeHistoryItem.IsChanged = !(changeHistoryItem.OldValue == changeHistoryItem.NewValue); //TODO If user only update attachments
                lst.Add(changeHistoryItem);
            }

            // TODO : Transaction Scope
            using (var scope = new TransactionScope(TransactionScopeOption.Required))
            {
                intCount = repo.UpdateLanguageID(model, strUserName, strUserID, dtUpdated);
                if (intCount == 1)
                {
                    InsertChangeHistory(lst, strUserName, strUserID, dtUpdated);
                }
                scope.Complete();
            }

            return lst;
        }

        public bool ValidateUpdateLanguage(UpdateLanguageRequestViewModel model)
        {
            bool blnIsValid = true;

            if (model == null) { blnIsValid = false; }
            else
            {
                if (!Enum.IsDefined(typeof(Constant.LanguageType), model.LanguageID))
                {
                    blnIsValid = false;
                }
                bool blnContainPhone = !string.IsNullOrEmpty(model.PhoneNo);
                if ((!blnContainPhone && (model.IDType == 0 || string.IsNullOrEmpty(model.IDNo))) ||
                    (model.IDType == 0 && !blnContainPhone))
                {
                    blnIsValid = false;
                }
            }

            return blnIsValid;
        }
    }
}
