using DynamicExpresso;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using wispro.sp.api.Utility;
using wispro.sp.entity;
using wispro.sp.share;
using wispro.sp.utility;

namespace wispro.sp.api.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    //[Authorize]
    public class PerformanceItemController : ControllerBase
    {
        spDbContext Context;

        public PerformanceItemController(spDbContext context)
        {
            Context = context;
        }
        public ApiSaveResponse New(PerformanceItem item)
        {
            ApiSaveResponse ret = new ApiSaveResponse();
            ret.Success = true;

            using (Context.Database.BeginTransaction())
            {
                try
                {
                    var results = Context.PerformanceItems.Where<PerformanceItem>(x =>
                       x.CaseNo == item.CaseNo && x.DoItem == item.DoItem && x.DoItem != "提出报告" && x.CaseStage == item.CaseStage);
                   
                    var items = results.Include(pi => pi.CalMonth).FirstOrDefault<PerformanceItem>();

                    if (items != null)
                    {
                        item.AgentFeedbackMemo = "已算绩效";
                        item.DoItemMemo = $"{items.DoItemMemo}\r\n{items.CalMonth.Year}-{items.CalMonth.Month}已计算！";
                        item.BasePoint = 0;
                    }

                    if (item.CalMonth != null)
                    {
                        var calMonth = Context.CalMonths.Where<CalMonth>(c => c.Year  == item.CalMonth.Year && c.Month == item.CalMonth.Month).FirstOrDefault();
                        
                        if(calMonth == null)
                        {
                            Context.CalMonths.Add(item.CalMonth);
                            Context.SaveChanges();
                        }
                        else
                        {
                            item.CalMonth = calMonth;
                        }

                        item.CalMonthId = item.CalMonth.Id;
                        item.CalMonth = null;
                    }

                    if (!string.IsNullOrEmpty(item.Customer.Name))
                    {
                        var temCustomer = Context.Customers.Where<Customer>(c => c.Name == item.Customer.Name).FirstOrDefault();

                        if (temCustomer == null)
                        {
                            Context.Customers.Add(item.Customer);
                            Context.SaveChanges();
                        }
                        else
                        {
                            item.Customer = temCustomer;
                        }

                        item.CustomerId = item.Customer.Id;
                        item.Customer = null;
                    }
                    else
                    {
                        item.Customer = null;
                    }

                    
                    var ItemStaffs = item.ItemStaffs;
                    item.ItemStaffs = null;

                    Context.PerformanceItems.Add(item);
                    Context.SaveChanges();

                    foreach (ItemStaff itemStaff in ItemStaffs)
                    {
                        itemStaff.ItemId = item.Id;
                        itemStaff.Item = null;

                        if (itemStaff.DoPersonId == 0 && itemStaff.DoPerson != null)
                        {
                            var temStaff = Context.Staffs.FirstOrDefault<Staff>(s => s.Name == itemStaff.DoPerson.Name);

                            if (temStaff != null)
                            {
                                itemStaff.DoPersonId = temStaff.Id;
                                itemStaff.DoPerson = null;
                            }
                            else
                            {
                                Context.Staffs.Add(itemStaff.DoPerson);
                                Context.SaveChanges();
                                itemStaff.DoPersonId = itemStaff.DoPerson.Id;
                                itemStaff.DoPerson = null;
                            }
                        }
                    }

                    Context.ItemStaffs.AddRange(ItemStaffs);
                    Context.SaveChanges();
                        
                    

                    Context.Database.CommitTransaction();
                }
                catch (Exception ex)
                {
                    ret.Success = false;
                    ret.ErrorMessage = ex.Message;
                    Context.Database.RollbackTransaction();
                }
            }
            

            return ret;
        }

        /// <summary>
        /// 更新绩效记录信息
        /// </summary>
        /// <param name="id">绩效记录编号</param>
        /// <param name="field">栏位，多个位以|杠隔开</param>
        /// <param name="value">栏位值，多个以|杠隔开</param>
        /// <returns></returns>
        public ApiSaveResponse UpdateFieldValue(int id,string field,string value)
        {
            ApiSaveResponse ret = new ApiSaveResponse();
            ret.Success = true;

            var item = Context.PerformanceItems.FirstOrDefault<PerformanceItem>(p => p.Id == id);

            if (item == null)
            {
                ret.Success = false;
                ret.ErrorMessage = $"不存在的{id}";

                return ret;
            }

            if(string.IsNullOrEmpty(field) )
            {
                ret.Success = false;
                ret.ErrorMessage = $"参数不对！";

                return ret;
            }

            string[] fields = field.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

            string[] values = new string[] { null };
            if (!string.IsNullOrEmpty(value))
            {
                values = value.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            }

            if (fields.Length != values.Length) {
                ret.Success = false;
                ret.ErrorMessage = "栏位和值对不匹配";
            }
            else 
            {
                for(int i = 0; i < fields.Length; i++)
                {
                    string temField = fields[i];
                    string temValue = values[i];
                    switch (temField)
                    {
                        case "AgentFeedbackMemo":
                            item.AgentFeedbackMemo = temValue;

                            break;
                        case "CaseCoefficient":
                            item.CaseCoefficient = temValue;

                            //此处添加保存到流程系统的代码
                            break;
                        case "DoItemCoefficient":
                            item.DoItemCoefficient = temValue;

                            //此处添加保存到流程系统的代码
                            break;
                        case "WordCount":
                            int wordCount;
                            if (int.TryParse(temValue, out wordCount))
                            {
                                item.WordCount = wordCount;
                            }
                            else
                            {
                                ret.Success = false;
                                ret.ErrorMessage = "所给的栏位值不能转换成数字！";
                                return ret;
                            }
                            break;
                        case "ReturnCasseNo":
                            item.ReturnCasseNo = temValue;
                            break;
                    }
                }
                
                 Utility.Utility.CalBasePoint(item, Context.BasePointRules.ToList());

                Context.SaveChanges();
            }
            
            return ret;
        }
        public ListApiResponse<PerformanceItem> Query(int pageIndex,int pageSize)
        {
            ListApiResponse<PerformanceItem> ret = new ListApiResponse<PerformanceItem>();
            var results = Context.PerformanceItems
                .Where<PerformanceItem>(s => 
                    (s.ItemStaffs.Where<ItemStaff>(iStaff => iStaff.DoPerson.Name == User.Identity.Name).Count() > 0 || s.Reviewer.Name == User.Identity.Name) 
                    && s.CalMonth.Status != 4);

            ret.TotalCount = results.Count();

            List<PerformanceItem> retList = results
                .Include(pi=>pi.ItemStaffs).ThenInclude(iStaff=>iStaff.DoPerson)
                .Include(pi=>pi.Reviewer)
                .Include(pi=>pi.Customer)
                .Include(pi=>pi.CalMonth)
                .OrderByDescending(o=>o.Id)
                .Skip<PerformanceItem>((pageIndex - 1) * pageSize).Take(pageSize).ToList<PerformanceItem>();

            #region 将某些属性设为null，避免循环取值造成返回json过大
            foreach (PerformanceItem item in retList)
            {
                foreach (ItemStaff itemStaff in item.ItemStaffs)
                {
                    itemStaff.DoPerson.ItemStaffs = null;
                    itemStaff.DoPerson.ReviewerItems = null;
                    itemStaff.Item = null;
                }

                item.Reviewer.ReviewerItems = null;
                item.Reviewer.Customers = null;
                item.Reviewer.ItemStaffs = null;

                item.Customer.PerformanceItems = null;
                item.CalMonth.PerformanceItems = null;
            }
            #endregion

            ret.Results = retList;

            return ret;
        }

        public PerformanceItem Get(int Id)
        {
            var results = Context.PerformanceItems
                .Where<PerformanceItem>(s =>s.Id == Id);

            PerformanceItem item = results
                .Include(pi => pi.ItemStaffs).ThenInclude(iStaff => iStaff.DoPerson)
                .Include(pi => pi.Reviewer)
                .Include(pi => pi.Customer)
                .Include(pi => pi.CalMonth)
                .OrderByDescending(o => o.Id)
                .FirstOrDefault();

            #region 将某些属性设为null，避免循环取值造成返回json过大
            foreach (ItemStaff itemStaff in item.ItemStaffs)
            {
                itemStaff.DoPerson.ItemStaffs = null;
                itemStaff.DoPerson.ReviewerItems = null;
                itemStaff.Item = null;
            }

            item.Reviewer.ReviewerItems = null;
            item.Reviewer.Customers = null;
            item.Reviewer.ItemStaffs = null;

            item.Customer.PerformanceItems = null;
            item.CalMonth.PerformanceItems = null;
            #endregion

            return item;
        }
        /// <summary>
        /// 获取给定用户的绩效清单
        /// </summary>
        /// <param name="userid">用户id</param>
        /// <param name="type">获取类型；0：处理中；1：所有；4：已归档</param>
        /// <returns></returns>
        public ListApiResponse<PerformanceItem> GetMyList(int userid, int type,int pageIndex=1,int pageSize = 10)
        {
            ListApiResponse<PerformanceItem> ret = new ListApiResponse<PerformanceItem>();
            var results = Context.PerformanceItems
                .Where<PerformanceItem>(s =>
                    (s.ItemStaffs.Where<ItemStaff>(iStaff => iStaff.DoPerson.Id  == userid ).Count() > 0 || s.Reviewer.Id  == userid )
                    && s.CalMonth.Status == type);

            
            ret.TotalCount = results.Count();

            List<PerformanceItem> retList = results
                .Include(pi => pi.ItemStaffs).ThenInclude(iStaff => iStaff.DoPerson)
                .Include(pi => pi.Reviewer)
                .Include(pi => pi.Customer)
                .Include(pi => pi.CalMonth)                
                .OrderByDescending(o => o.Id)
                .Skip<PerformanceItem>((pageIndex - 1) * pageSize).Take(pageSize)
                .ToList<PerformanceItem>();

            #region 将某些属性设为null，避免循环取值造成返回json过大
            foreach (PerformanceItem item in retList)
            {
                foreach(ItemStaff itemStaff in item.ItemStaffs)
                {
                    itemStaff.DoPerson.ItemStaffs = null;
                    itemStaff.DoPerson.ReviewerItems = null;
                    itemStaff.Item = null;
                }

                item.Reviewer.ReviewerItems = null;
                item.Reviewer.Customers = null;
                item.Reviewer.ItemStaffs = null;

                item.Customer.PerformanceItems = null;
                item.CalMonth.PerformanceItems = null;
            }
            #endregion

            ret.Results = retList;

            return ret;
        }



        /// <summary>
        /// 计算指定用户，指定年月的绩效统计信息
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="year"></param>
        /// <param name="month"></param>
        /// <returns></returns>
        public List<StaffStatistics> CalMyStatistics(int year,int month, int? userid=null)
        {
            CalMonth calMonth = Context.CalMonths.Where<CalMonth>(c => c.Month == month && c.Year == year).FirstOrDefault();
            
            if(calMonth == null)
            {
                return null;
            }
            else
            {
                if(calMonth.Status  == 4)
                {
                    //已归档，归档数据库中直接取出记录
                    return null;
                }
                else
                {
                    //未归档，从绩效记录中统计数据

                    var results = Context.PerformanceItems.Where<PerformanceItem>(s =>s.CalMonth.Id == calMonth.Id);

                    if (userid != null)
                    {
                        results = Context.PerformanceItems.Where<PerformanceItem>(s =>
                            (s.ItemStaffs.Where<ItemStaff>(iStaff => iStaff.DoPerson.Id == userid).Count() > 0 || s.Reviewer.Id == userid)
                            && s.CalMonth.Id == calMonth.Id);
                    }

                    List<PerformanceItem> ItemList = results
                        .Include(pi => pi.ItemStaffs).ThenInclude(iStaff => iStaff.DoPerson)
                        .Include(pi => pi.Reviewer)
                        .OrderByDescending(o => o.Id)
                        .ToList<PerformanceItem>();

                    List<StaffStatistics> retList = new List<StaffStatistics>();
                    List<VerifyCoefficient> verifyCoefficients = Context.VerifyCoefficients.ToList<VerifyCoefficient>();

                    foreach (PerformanceItem item in ItemList)
                    {
                        
                        if (item.BasePoint != null && item.BasePoint.Value > 0)
                        {
                            double doPersonBasePoint = item.BasePoint.Value;
                            
                            System.Collections.Hashtable doPersonsBL = new System.Collections.Hashtable();

                            bool isPJFP = true;
                            double total = item.ItemStaffs.Count();
                            if(item.ItemStaffs.Where<ItemStaff>(p=>p.PerformancePoint == null || p.PerformancePoint ==0).Count() == 0)
                            {
                                total = item.ItemStaffs.Select(i => i.PerformancePoint.Value).Sum();
                                isPJFP = false;
                            }

                            List<StaffStatistics> itemStatistics = new List<StaffStatistics>();

                            if (item.Reviewer != null)
                            {
                                Context.Entry(item.Reviewer).Reference(b => b.StaffGrade).Load();
                            }

                            foreach (ItemStaff itemStaff in item.ItemStaffs)
                            {
                                Context.Entry(itemStaff).Reference(b => b.DoPerson).Load();
                                Context.Entry(itemStaff.DoPerson).Reference(b => b.StaffGrade).Load();

                                #region 计算审核人绩效点数，核稿人绩效点数按照核稿人与个处理人的核稿系数计算后加总，没有找到核稿系数（比如同级别），核稿系数为0
                                if (item.ReviewerId != null && userid == item.ReviewerId)
                                {
                                    #region 取审核人等级审核等级系数
                                    VerifyCoefficient vcoefficient = verifyCoefficients.Where<VerifyCoefficient>(v =>
                                            v.CheckerId == item.Reviewer.StaffGrade.Id
                                            && v.DoPersonId == itemStaff.DoPerson.StaffGradeId)
                                    .FirstOrDefault<VerifyCoefficient>();
                                    #endregion

                                    if (vcoefficient != null)
                                    {
                                        double reviewerBasePoint = item.BasePoint.Value * vcoefficient.Coefficient;


                                        string temJxType = $"{item.Type}审核";

                                        var temReviewerStatic = itemStatistics.Where<StaffStatistics>(s => s.StaffId == item.ReviewerId && s.jxType == temJxType && s.CalMonth.Id == calMonth.Id).FirstOrDefault();
                                        if (temReviewerStatic != null)
                                        {
                                            temReviewerStatic.totalBasePoint += reviewerBasePoint;
                                        }
                                        else
                                        {
                                            if (item.Reviewer.IsOnJob)  //判断是否在职
                                            {
                                                temReviewerStatic = new StaffStatistics()
                                                {
                                                    CalMonth = calMonth,
                                                    CalMonthId = calMonth.Id,
                                                    StaffId = item.ReviewerId.Value,
                                                    totalBasePoint = reviewerBasePoint,
                                                    jxType = temJxType
                                                };

                                                itemStatistics.Add(temReviewerStatic);
                                            }
                                        }
                                    }
                                }
                                #endregion

                                #region 计算个处理人的绩效点数
                                double handlerBasePoint;
                                if (isPJFP) {
                                    handlerBasePoint = item.BasePoint.Value * 1.0/total;
                                }
                                else
                                {
                                    handlerBasePoint = item.BasePoint.Value * itemStaff.PerformancePoint.Value / total;
                                }

                                string handlerJxType = $"{item.Type}处理";
                                var temStatic = itemStatistics.Where<StaffStatistics>(s => s.StaffId == itemStaff.DoPersonId && s.jxType == handlerJxType && s.CalMonth.Id == calMonth.Id).FirstOrDefault();
                                if (temStatic != null)
                                {
                                    temStatic.totalBasePoint += handlerBasePoint * itemStaff.DoPerson.StaffGrade.Coefficient;
                                }
                                else
                                {
                                    if (itemStaff.DoPerson.StaffGrade != null && itemStaff.DoPerson.IsOnJob)
                                    {
                                        temStatic = new StaffStatistics()
                                        {
                                            CalMonth = calMonth,
                                            CalMonthId = calMonth.Id,
                                            StaffId = itemStaff.DoPersonId,
                                            totalBasePoint = handlerBasePoint * itemStaff.DoPerson.StaffGrade.Coefficient,
                                            jxType = handlerJxType
                                        };


                                        itemStatistics.Add(temStatic);
                                    }
                                }
                                #endregion
                            }

                            List<StaffStatistics> temItemStatics;

                            if(userid != null)
                            {
                                temItemStatics = itemStatistics.Where<StaffStatistics>(s => s.StaffId == userid).ToList();
                            }
                            else
                            {
                                temItemStatics = itemStatistics;
                            }
                            
                            foreach (StaffStatistics  retUserValue in temItemStatics)
                            {
                                var temValue = retList.Where<StaffStatistics>(s => s.StaffId == retUserValue.StaffId && s.jxType == retUserValue.jxType && s.CalMonthId == calMonth.Id).FirstOrDefault();
                                if (temValue != null)
                                {
                                    temValue.totalBasePoint += retUserValue.totalBasePoint;
                                }
                                else
                                {
                                    retList.Add(retUserValue);
                                }
                            }
                        }

                    }

                    foreach(StaffStatistics ss in retList)
                    {
                        ss.CalMonth.PerformanceItems  = null;
                    }
                    return retList;
                }
            }
            

            
        }

        
        private string GetExpress(IList<FieldCondition> conditions)
        {
            string str = "";

            foreach(var c in conditions)
            {
                if (string.IsNullOrEmpty(str))
                {
                    str = c.ToExpressString("s");
                }
                else
                {
                    if(c.LogicOperate == LogicEnum.And)
                    {
                        str = $"({str}) && {c.ToExpressString("s")}";
                    }
                    else
                    {
                        str = $"({str}) || {c.ToExpressString("s")}";
                    }
                }
            }

            return str;
        }
        [HttpPost]
        public ListApiResponse<PerformanceItem> QueryFilter(QueryFilter queryFilter)
        {

            ListApiResponse<PerformanceItem> ret = new ListApiResponse<PerformanceItem>();

            string strExpress = "";
            

            if (!string.IsNullOrEmpty(strExpress))
            {
                strExpress = $"{strExpress} && s.CalMonth.Status == {Convert.ToInt32(queryFilter.jxType)}";
            }
            else
            {
                strExpress = $"s.CalMonth.Status == {Convert.ToInt32(queryFilter.jxType)}";
            }

            if (queryFilter.ConditionTree != null)
            {
                string strTem = GetExpress(queryFilter.ConditionTree);

                if (!string.IsNullOrEmpty(strTem))
                {
                    strExpress = $"{strExpress} && ({strTem})";
                }
            }

            var interpreter = new Interpreter();
            Expression<Func<PerformanceItem, bool>> dynamicWhere = interpreter.ParseAsExpression<Func<PerformanceItem, bool>>(strExpress, "s");

            IQueryable<PerformanceItem> response;
            if (queryFilter.userId > 0)
            {
                 response = Context.PerformanceItems.Where<PerformanceItem>(dynamicWhere).Where(s => (s.ItemStaffs.Where<ItemStaff>(iStaff => iStaff.DoPerson.Id == queryFilter.userId).Count() > 0 || s.ReviewerId == queryFilter.userId));

            }
            else
            {
                 response = Context.PerformanceItems.Where<PerformanceItem>(dynamicWhere);

            }

            int totals;
            response = response
                .Include(pi => pi.ItemStaffs).ThenInclude(iStaff => iStaff.DoPerson)
                .Include(pi => pi.Reviewer)
                .Include(pi => pi.Customer)
                .Include(pi => pi.CalMonth)
                .OrderConditions<PerformanceItem>(queryFilter.Sorts)
                .Pager<PerformanceItem>(queryFilter.PageIndex,queryFilter.PageSize,out totals);
            ret.TotalCount = totals;

            var retList = response.ToList<PerformanceItem>();

            #region 将某些属性设为null，避免循环取值造成返回json过大
            foreach (PerformanceItem item in retList)
            {

                foreach (ItemStaff itemStaff in item.ItemStaffs)
                {
                    itemStaff.DoPerson.ItemStaffs = null;
                    itemStaff.DoPerson.ReviewerItems = null;
                    itemStaff.Item = null;
                }

                if (item.Reviewer != null)
                {
                    item.Reviewer.ReviewerItems = null;
                    item.Reviewer.Customers = null;
                    item.Reviewer.ItemStaffs = null;
                }

                if (item.Customer != null)
                {
                    item.Customer.PerformanceItems = null;
                }

                if (item.CalMonth != null)
                {
                    item.CalMonth.PerformanceItems = null;
                }
            }
            #endregion

            ret.Results = retList;

            return ret;
        }


    }
}
