using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LHDN.CRM.Models.ViewModels;
using System.Data;
using LHDN.CRM.BC.Common;
using LHDN.CRM.Models.Models;

namespace LHDN.CRM.BC.Services
{
    public class TaskService : ServiceBase<Models.ViewModels.TaskViewModel>
    {
        private Repositories.TaskRepository repo = new Repositories.TaskRepository();
        public TaskViewModel GetCaseOrActivity(TaskPagedListViewModel paging, out int intCount)
        {
            intCount = 0;

            DataSet ds = repo.GetCaseOrActivity(paging);

            TaskViewModel taskVM = new TaskViewModel();
            List<ActForTaskViewModel> lstActVM = new List<ActForTaskViewModel>();
            List<CaseForTaskViewModel> lstCaseVM = new List<CaseForTaskViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                {
                    if (paging.Regarding == "Case")
                        lstCaseVM = repo.DataTableToList<CaseForTaskViewModel>(ds.Tables[0]).ToList();
                    else if (paging.Regarding == "Activity")
                        lstActVM = repo.DataTableToList<ActForTaskViewModel>(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());
            }
            taskVM.LstActivity = lstActVM;
            taskVM.LstCase = lstCaseVM;

            return taskVM;
        }

        public DropdownViewModel GetDropdown()
        {
            DropdownViewModel ddlVM = new DropdownViewModel();
            ddlVM.ActStatusOptions = Utilities.SortDDL(AdminService.LookupParams.Where(x => x.LookupCode == "ActivityStatus" && x.IsActive == true)
                                    .Select(x => new DropdownDetailViewModel
                                    {
                                        Value = x.LookupParamID,
                                        Text = x.ParamDesc,
                                        IsDefault = x.IsDefault,
                                        Code = x.LookupValue,
                                        SeqNo = x.SeqNo
                                    }).ToList());
            ddlVM.MainKategoriOptions = AdminService.Kategoris.Where(x => x.IsActive == true).OrderBy(x => x.Kategori1Name).ToList<MainKategori>();
            ddlVM.Status1Options = AdminService.StatusLevels.Where(x => x.IsActive == true).ToList<StatusLevel1>();
            ddlVM.ActChannelOptions = AdminService.ActivityChannels.ToList<ActivityChannel>();
            ddlVM.AliranOptions = Utilities.SortDDL(AdminService.LookupParams.Where(x => x.LookupCode == "Aliran" && x.IsActive == true).Select(x => new DropdownDetailViewModel { Value = x.LookupParamID, Text = x.ParamDesc, IsDefault = x.IsDefault, Code = x.LookupValue, SeqNo = x.SeqNo }).ToList());
            ddlVM.ParameterSettings = AdminService.ParameterSettings.Where(x => (x.ParameterID == 22)).ToList<ParameterSettings>();

            return ddlVM;
        }

        public TaskViewModel GetTask(long taskID, UserInfoViewModel currentUser = null)
        {
            TaskViewModel data;
            if (taskID == 0)
            {
                data = new TaskViewModel();
                if (currentUser != null)
                {
                    data.CanSearchCase = currentUser.RolesObj.Any(x => x.RoleCode == Constant.Authentication.Cases.SearchCaseProfile);
                    data.CanSearchAct = currentUser.RolesObj.Any(x => x.RoleCode == Constant.Authentication.Activity.SearchActivityProfile);
                }
                return data;
            }
            else
            {
                data = repo.GetTask(taskID);
                if (data == null)
                    throw new NotFoundException("Task is deleted or not found!");
                else
                {
                    if (currentUser != null)
                    {
                        data.CanSearchCase = currentUser.RolesObj.Any(x => x.RoleCode == Constant.Authentication.Cases.SearchCaseProfile);
                        data.CanSearchAct = currentUser.RolesObj.Any(x => x.RoleCode == Constant.Authentication.Activity.SearchActivityProfile);
                    }
                }
            }

            return data;
        }

        public bool DeleteTask(TaskViewModel model)
        {
            byte[] oriChangeStamp = repo.GetChangeStampbyID(model.TaskID);
            bool blnIsSuccess = false;
            if (!Utilities.CompareByteArray(model.ChangeStamp, oriChangeStamp))
            {
                //TODO Update conflict
                throw new UpdateConflictException();
            }
            blnIsSuccess = repo.DeleteTask(model.TaskID);

            return blnIsSuccess;
        }

        public List<ChangeHistoryUpdateViewModel> UpdateTask(TaskViewModel taskVM, string strLastUpdatedBy, DateTime dtLastUpdatedDateTime, 
                                                            string strLastUpdatedName, string strLastUpdatedEmail,
                                                            out long lngTaskID, out string strTaskRefNo)
        {
            List<ChangeHistoryUpdateViewModel> lst = new List<ChangeHistoryUpdateViewModel>();
            lngTaskID = 0;
            strTaskRefNo = "";

            if (taskVM.TaskID > 0) //if INSERT, skip update conflict and change history
            {
                // Retrieve orginal records for audit and change history 
                TaskViewModel oriTask = GetTask(taskVM.TaskID, null);

                // Check for update conflict
                if (!Utilities.CompareByteArray(taskVM.ChangeStamp, oriTask.ChangeStamp))
                {
                    //TODO Update conflict
                    throw new UpdateConflictException();
                }
                foreach (ChangeHistoryUpdateViewModel changeHistoryItem in taskVM.ChangeHistory)
                {
                    if (changeHistoryItem.FieldName == "RefNo" || changeHistoryItem.FieldName == "Regarding") //Regarding & RefNo already handled in JS
                        continue;

                    //Get object original value
                    string oriValue = string.Empty;

                    var obj = Utilities.GetPropertyValue(oriTask, changeHistoryItem.FieldName);
                    oriValue = obj == null ? "" : obj.ToString();

                    DateTime dDate;
                    if (DateTime.TryParse(oriValue, out dDate))
                    {
                        oriValue = String.Format("{0:dd MMM yyyy}", dDate);
                    }
                    changeHistoryItem.NewValue = changeHistoryItem.FieldName == "AssignToName" ? taskVM.AssignToName : changeHistoryItem.NewValue;
                    changeHistoryItem.OldValue = oriValue;
                    changeHistoryItem.IsChanged = !(changeHistoryItem.OldValue == changeHistoryItem.NewValue);
                }
                lst = taskVM.ChangeHistory.Where(x => x.IsChanged).ToList();
            }

            DataTable dTblResult = repo.UpdateTask(taskVM, strLastUpdatedBy, dtLastUpdatedDateTime, strLastUpdatedName, strLastUpdatedEmail);

            if (dTblResult != null && dTblResult.Rows.Count > 0)
            {
                lngTaskID = Convert.ToInt64(dTblResult.Rows[0]["TaskID"]);
                strTaskRefNo = dTblResult.Rows[0]["TaskRefNo"].ToString();
            }
            return lst;
        }

        public List<TaskViewModel> SearchTask(TaskPagedListViewModel paging, out int intCount)
        {
            intCount = 0;
            DataSet ds = repo.SearchTask(paging);
            List<TaskViewModel> lstTaskVM = new List<TaskViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstTaskVM = repo.DataTableToList<TaskViewModel>(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 lstTaskVM;
        }

        public byte[] ExportExcelSearchTask(TaskPagedListViewModel paging)
        {
            DataSet ds = repo.SearchTask(paging);
            DataTable dtbl = new DataTable();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    dtbl = ds.Tables[0];
            }

            return Utilities.ExportExcel(dtbl);
        }

        public List<TaskViewModel> GetDashboardMyTask(TaskPagedListViewModel paging, string strCurrentUser, out int intCount)
        {
            intCount = 0;
            DataSet ds = repo.GetDashboardMyTask(paging, strCurrentUser);
            List<TaskViewModel> lstTaskVM = new List<TaskViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstTaskVM = repo.DataTableToList<TaskViewModel>(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 lstTaskVM;
        }

        public List<TaskViewModel> GetDashboardMyTaskSubmission(TaskPagedListViewModel paging, string strCurrentUser, out int intCount)
        {
            intCount = 0;
            DataSet ds = repo.GetDashboardMyTaskSubmission(paging, strCurrentUser);
            List<TaskViewModel> lstTaskVM = new List<TaskViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstTaskVM = repo.DataTableToList<TaskViewModel>(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 lstTaskVM;
        }

        public List<RecentActivityViewModel> GetRecentActivity(string strCurrentUser)
        {
            var intRecords = Convert.ToInt32(AdminService.ParameterSettings.Where(x => x.ParameterID == 1).FirstOrDefault().ParameterValue);
            return repo.GetRecentActivity(strCurrentUser, intRecords);
        }

        public long InsertRecentActivity(string strModule, long lngRefID, string strDescription, string strCreatedBy, string strCreatedByName,
                                         DateTime dtCreatedDateTime, string strURL)
        {
            return repo.InsertRecentActivity(strModule, lngRefID, strDescription, strCreatedBy, strCreatedByName, dtCreatedDateTime, strURL);
        }

        public List<WorkflowUserViewModel> GetAllUsers()
        {
            return repo.GetAllUsers();
        }

        public List<TaskListViewModel> GetTaskListByID(TaskListPagedListViewModel paging, out int intCount)
        {
            intCount = 0;

            DataSet ds = repo.GetTaskListByID(paging.SortExpression, paging.PageIndex, paging.Length,
                                            paging.CaseID, paging.ActivityID, paging.StatusID);

            List<TaskListViewModel> lstTaskListVM = new List<TaskListViewModel>();

            if (ds != null && ds.Tables.Count > 0)
            {
                if (ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                    lstTaskListVM = repo.DataTableToList<TaskListViewModel>(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 lstTaskListVM;

           
        }

        public List<TaskForCalendarViewModel> GetTaskForCalendar(string strLoginID)
        {
            return repo.GetTaskForCalendar(strLoginID);
        }
    }
}
