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.Threading.Tasks;
using wispro.sp.api.Job;
using wispro.sp.entity;
using wispro.sp.share;

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

        }

        private void replaceDataforCycleSerialze(List<ProjectInfo> projects)
        {
            foreach (var project in projects)
            {
                if (project.Customer != null)
                {
                    var temCustomer = new Customer()
                    {
                        Address = project.Customer.Address,
                        Name = project.Customer.Name,
                        Id = project.Customer.Id
                    };

                    project.Customer = temCustomer;
                }

                if (project.Reviewer != null)
                {
                    var temStaff = new Staff()  
                    {
                        Name = project.Reviewer.Name,
                        Id = project.Reviewer.Id,
                    };

                    project.Reviewer  = temStaff;
                }

                if (project.WorkflowUser != null)
                {
                    var temStaff = new Staff()
                    {
                        Name = project.WorkflowUser.Name,
                        Id = project.WorkflowUser.Id,
                    };

                    project.WorkflowUser = temStaff;
                }
            }
        }
        public List<ProjectInfo> GetProjects(int state)
        {
            var retList = Context.ProjectInfos
                .Include(p => p.Customer)
                .Include(p=>p.Reviewer)
                .Include(p => p.WorkflowUser)
                .Where(s => s.CaseState == state).ToList();

            replaceDataforCycleSerialze(retList);

            return retList;
        }

        public List<ProjectInfo> GetAll()
        {
            var retList = Context.ProjectInfos
                .Include(p => p.Customer)
                .Include(p => p.Reviewer)
                .Include(p => p.WorkflowUser)
                .ToList();

            replaceDataforCycleSerialze(retList);

            return retList;
        }

        

        public bool SetFinished(string caseNo)
        {
            var obj = Context.ProjectInfos.FirstOrDefault(s=>s.CaseNo == caseNo );

            if(obj != null)
            {
                try
                {
                    obj.CaseState = 4;
                    Context.SaveChanges();
                    return true;
                }
                catch(Exception ex)
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        public List<ProjectContentRecord> GetMyProjects()
        {
            var retList = Context.ProjectContentRecords
                .Include(p => p.CalMonth)
                .Include(p => p.Reviewer)
                .Include(p => p.Project).ThenInclude(p => p.Customer)
                .Include(p => p.ProjectWorkContents)
                .Where(p => p.Staff.Name == User.Identity.Name).ToList();

            NewMethod(retList);

            return retList;
        }

        private static void NewMethod(List<ProjectContentRecord> retList)
        {
            foreach (var pcRecord in retList)
            {
                if (pcRecord.CalMonth != null)
                {
                    pcRecord.CalMonth = new CalMonth()
                    {
                        Id = pcRecord.CalMonth.Id,
                        Year = pcRecord.CalMonth.Year,
                        Month = pcRecord.CalMonth.Month,
                        PerformanceItems = null

                    };


                }

                if (pcRecord.Reviewer != null)
                {
                    var temStaff = new Staff()
                    {
                        Name = pcRecord.Reviewer.Name,
                        Id = pcRecord.Reviewer.Id,
                    };

                    pcRecord.Reviewer = temStaff;
                }

                if (pcRecord.Project != null)
                {
                    ProjectInfo temProj = new ProjectInfo()
                    {
                        CaseNo = pcRecord.Project.CaseNo,
                        CaseName = pcRecord.Project.CaseName,
                        Customer = new Customer()
                        {
                            Name = (pcRecord.Project.Customer == null) ? "" : pcRecord.Project.Customer.Name,
                            Id = (pcRecord.Project.Customer == null) ? 0 : pcRecord.Project.Customer.Id,
                        }
                    };
                }

                if (pcRecord.ProjectWorkContents != null)
                {
                    foreach (var pwContent in pcRecord.ProjectWorkContents)
                    {
                        pwContent.ContentRecord = null;
                    }
                }
            }
        }

        public ProjectContents getProjectWorkContent(int Id)
        {
            var retObj = Context.ProjectContentRecords
                .Include(p => p.CalMonth)
                .Include(p => p.Reviewer)
                .Include(p => p.Project).ThenInclude(p=>p.Customer)
                .Include(p => p.ProjectWorkContents)
                .FirstOrDefault(p=>p.Id == Id);

            if(retObj != null)
            {
                ProjectContents ret = new ProjectContents();

                ret.ProjectContentRecord = retObj;

                ret.ProjectWorkContents = new List<ViewProjectWorkContent>();
                foreach(var wContent in retObj.ProjectWorkContents)
                {
                    ViewProjectWorkContent tem = new ViewProjectWorkContent();
                    tem.modifyState = ModifyState.UnChanged;
                    tem.Id = wContent.Id;
                    tem.Content = wContent.Content;
                    tem.ActualPerformance = wContent.ActualPerformance;
                    tem.ContentRecordId = wContent.ContentRecordId;
                    tem.FinalPerformance  = wContent.FinalPerformance;
                    tem.TakeTime = wContent.TakeTime;
                    tem.TimeSpan = wContent.TimeSpan;
                    tem.WorkDate = wContent.WorkDate;

                    ret.ProjectWorkContents.Add(tem);
                }

                ret.ProjectContentRecord.ProjectWorkContents = null;

                return ret;
            }

            return null;

        }

        private void _SaveProjectWorkContent(spDbContext dbContext,ProjectContents saveObj)
        {
            if (saveObj.ProjectContentRecord.Id == 0)
            {
                if (string.IsNullOrEmpty(saveObj.ProjectContentRecord.ProjectNo))
                {
                    throw new ApplicationException("没有选择专案！");
                }
                else
                {
                    saveObj.ProjectContentRecord.Project = null;
                }

                var currentUser = Context.Staffs.FirstOrDefault(s => s.Name == User.Identity.Name);
                saveObj.ProjectContentRecord.StaffId = currentUser.Id;

                var temObj = Context.ProjectContentRecords.FirstOrDefault(p => 
                                        p.StaffId == currentUser.Id && 
                                        p.ProjectNo == saveObj.ProjectContentRecord.ProjectNo && 
                                        p.CalMonthId== saveObj.ProjectContentRecord.CalMonthId );

                if(temObj != null)
                {
                    throw new ApplicationException($"本月已提交{temObj.ProjectNo}工作内容！");
                }

                Context.ProjectContentRecords.Add(saveObj.ProjectContentRecord);
                Context.SaveChanges();
            }
            else
            {
                var temObj = Context.ProjectContentRecords.FirstOrDefault(p => p.Id == saveObj.ProjectContentRecord.Id);
                temObj.CaseCoefficient = saveObj.ProjectContentRecord.CaseCoefficient;
                temObj.Point = saveObj.ProjectContentRecord.Point;
                temObj.ReviewerId = saveObj.ProjectContentRecord.ReviewerId;
                //temObj.StaffId = saveObj.ProjectContentRecord.StaffId;
                temObj.State = saveObj.ProjectContentRecord.State;
                temObj.PointS = saveObj.ProjectContentRecord.PointS;
                temObj.PointA = saveObj.ProjectContentRecord.PointA;
                temObj.PointB = saveObj.ProjectContentRecord.PointB;
                temObj.PointC = saveObj.ProjectContentRecord.PointC;
                temObj.PointD = saveObj.ProjectContentRecord.PointD;
                dbContext.SaveChanges();
                saveObj.ProjectContentRecord = temObj;
            }

            foreach (var temContent in saveObj.ProjectWorkContents)
            {
                switch (temContent.modifyState)
                {
                    case ModifyState.Deleted:
                        dbContext.Database.ExecuteSqlRaw($"Delete from ProjectWorkContent where id={temContent.Id}");

                        break;
                    case ModifyState.Modified:
                        var modifyContent = Context.ProjectWorkContents.FirstOrDefault(p => p.Id == temContent.Id);
                        if (modifyContent != null)
                        {
                            modifyContent.Content = temContent.Content;
                            modifyContent.ActualPerformance = temContent.ActualPerformance;
                            modifyContent.DifficultFactor = temContent.DifficultFactor;
                            modifyContent.FinalPerformance = temContent.FinalPerformance;
                            modifyContent.TakeTime = temContent.TakeTime;
                            modifyContent.TimeSpan = temContent.TimeSpan;
                            modifyContent.WorkDate = temContent.WorkDate;
                        }
                        break;
                    case ModifyState.New:
                        var newContent = new ProjectWorkContent();
                        newContent.Content = temContent.Content;
                        newContent.ActualPerformance = temContent.ActualPerformance;
                        newContent.DifficultFactor = temContent.DifficultFactor;
                        newContent.FinalPerformance = temContent.FinalPerformance;
                        newContent.TakeTime = temContent.TakeTime;
                        newContent.TimeSpan = temContent.TimeSpan;
                        newContent.WorkDate = temContent.WorkDate;
                        newContent.ContentRecordId = saveObj.ProjectContentRecord.Id;

                        Context.ProjectWorkContents.Add(newContent);
                        break;
                }
                dbContext.SaveChanges();
            }
        }

        public ApiSaveResponse SaveProjectWorkContent(ProjectContents saveObj)
        {
            ApiSaveResponse ret = new ApiSaveResponse();
            ret.Success = true;

            using (var t = Context.Database.BeginTransaction())
            {
                try
                {
                    _SaveProjectWorkContent(Context, saveObj);
                    
                    t.Commit();
                }
                catch(Exception ex)
                {
                    t.Rollback();
                    ret.Success = false;
                    ret.ErrorMessage = ex.Message;
                }
            }

            return ret;
        }

        public ApiSaveResponse ReviewProjectWorkContent(List<ProjectContents> saveObjs)
        {
            ApiSaveResponse ret = new ApiSaveResponse();
            ret.Success = true;
            var Reviewer = Context.Staffs.FirstOrDefault(p=>p.Name == User.Identity.Name);

            

            using (var t = Context.Database.BeginTransaction())
            {
                try
                {
                    foreach (var saveObj in saveObjs)
                    {
                        if (Reviewer.Id != saveObj.ProjectContentRecord.ReviewerId )
                        {
                            ret.Success = false;
                            ret.ErrorMessage = "只有指定审核人员才能操作！";
                        }
                        
                        saveObj.ProjectContentRecord.ReviewerId = Reviewer.Id;
                        

                        saveObj.ProjectContentRecord.State = 2;

                        _SaveProjectWorkContent(Context, saveObj);

                        if(saveObj.ProjectContentRecord.Project == null)
                        {
                            saveObj.ProjectContentRecord.Project = Context.ProjectInfos.Include(p=>p.Customer)
                                .FirstOrDefault(p=>p.CaseNo == saveObj.ProjectContentRecord.ProjectNo);
                        }

                        Dictionary<string, double> finanlJXDic = new Dictionary<string, double>();
                        if (saveObj.ProjectContentRecord.PointS.HasValue)
                        {
                            finanlJXDic.Add("S", saveObj.ProjectContentRecord.PointS.Value);
                        }

                        if (saveObj.ProjectContentRecord.PointA.HasValue)
                        {
                            finanlJXDic.Add("A", saveObj.ProjectContentRecord.PointA.Value);
                        }

                        if (saveObj.ProjectContentRecord.PointB.HasValue)
                        {
                            finanlJXDic.Add("B", saveObj.ProjectContentRecord.PointB.Value);
                        }

                        if (saveObj.ProjectContentRecord.PointC.HasValue)
                        {
                            finanlJXDic.Add("C", saveObj.ProjectContentRecord.PointC.Value);
                        }

                        if (saveObj.ProjectContentRecord.PointD.HasValue)
                        {
                            finanlJXDic.Add("D", saveObj.ProjectContentRecord.PointD.Value);
                        }

                        if (finanlJXDic.Count == 0)
                        {
                            throw new ApplicationException("请填写最终绩效！");
                        }

                        if (saveObj.ProjectContentRecord.State == 2)
                        {
                            if (finanlJXDic.Count > 0)
                            {
                                var retItems = Context.PerformanceItems.Include(p => p.ItemStaffs).Where(p =>
                                          p.CaseNo == saveObj.ProjectContentRecord.ProjectNo &&
                                          p.ItemStaffs.Where(s => s.DoPersonId == saveObj.ProjectContentRecord.StaffId).Count() > 0 &&
                                          p.CalMonthId == saveObj.ProjectContentRecord.CalMonthId).ToList();

                                foreach (var temItem in retItems)
                                {
                                    Context.ItemStaffs.RemoveRange(temItem.ItemStaffs);
                                    Context.PerformanceItems.Remove(temItem);
                                    Context.SaveChanges();
                                }
                            }

                            foreach (string strKey in finanlJXDic.Keys)
                            {
                                PerformanceItem item = Context.PerformanceItems.FirstOrDefault(p =>
                                    p.CaseNo == saveObj.ProjectContentRecord.ProjectNo &&
                                    p.ItemStaffs.Where(s => s.DoPersonId == saveObj.ProjectContentRecord.StaffId).Count() > 0 &&
                                    p.CaseCoefficient == strKey &&
                                    p.CalMonthId == saveObj.ProjectContentRecord.CalMonthId);

                                if(item == null)
                                {
                                    item = new PerformanceItem();
                                    item.DoItem = "";
                                }

                                item.CalMonthId = saveObj.ProjectContentRecord.CalMonthId.Value;
                                item.CaseCoefficient = strKey;
                                item.CaseName = saveObj.ProjectContentRecord.Project.CaseName;
                                item.CaseNo = saveObj.ProjectContentRecord.ProjectNo;

                                item.Type = "专案";
                                item.CustomerId = saveObj.ProjectContentRecord.Project.CustomerId;
                                item.BasePoint = finanlJXDic[strKey];

                                if (item.Id == 0)
                                {
                                    Context.PerformanceItems.Add(item);
                                    Context.SaveChanges();

                                    ItemStaff itemStaff = new ItemStaff();
                                    itemStaff.DoPersonId = saveObj.ProjectContentRecord.StaffId;
                                    itemStaff.ItemId = item.Id;
                                    itemStaff.PerformancePoint = finanlJXDic[strKey]; 
                                    Context.ItemStaffs.Add(itemStaff);
                                    Context.SaveChanges();
                                }
                                else
                                {
                                    item.BasePoint = finanlJXDic[strKey];
                                    item.CaseCoefficient = strKey;
                                    Context.SaveChanges();
                                }

                                new PerformanceItemController(Context, new Services.FileTaskCacheService()).CalItemJX(item.Id);
                            }
                        }
                        
                    }

                    t.Commit();
                }
                catch (Exception ex)
                {
                    t.Rollback();
                    ret.Success = false;
                    ret.ErrorMessage = ex.Message;
                }
            }

            return ret;
        }

        public ApiSaveResponse SubmitToReview(int Id, int reviewerId)
        {
            ApiSaveResponse ret = new ApiSaveResponse();
            ret.Success = true;
            using (var t = Context.Database.BeginTransaction())
            {
                try
                {
                    var temObj = Context.ProjectContentRecords.FirstOrDefault(p=>p.Id == Id);
                    

                    if(temObj != null)
                    {
                        temObj.State = 1;

                        var temStaff = Context.Staffs.FirstOrDefault(s=>s.Id == reviewerId);

                        if(temStaff == null)
                        {
                            ret.Success = false;
                            ret.ErrorMessage = "指定审核人不存在！";
                            return ret;
                        }

                        var calMonth = Context.CalMonths.FirstOrDefault(f=>f.Status ==0);

                        if(calMonth == null)
                        {
                            ret.Success = false;
                            ret.ErrorMessage = "当前没有正在处理的绩效核算月份！";
                            return ret;
                        }

                        temObj.ReviewerId = reviewerId;
                        temObj.CalMonthId = calMonth.Id;
                        Context.SaveChanges();
                        t.Commit();

                        #region 邮件通知
                        string strSubject = $"{User.Identity.Name}{calMonth.Month}月份专案工作内容";
                        string strBody = $"<html><body>{temStaff.Name},您好！<br/></br/>&nbsp;&nbsp;&nbsp;&nbsp;<div>{User.Identity.Name}提交了专案{temObj.ProjectNo} {calMonth.Year}年{calMonth.Month}月工作内容，请在尽快确认完成！</div></body></html>";
                        string strTo = temStaff.Mail;

                        _ = QuartzUtil.AddMailJob(strSubject, strBody, temStaff.Name, strTo);
                        #endregion
                    }
                    else
                    {
                        ret.Success = false;
                        ret.ErrorMessage = "指定项目工作内容Id不存在！";
                        return ret;
                    }
                }
                catch (Exception ex)
                {
                    t.Rollback();
                    ret.Success = false;
                    ret.ErrorMessage = ex.Message;
                }
            }

            return ret;
        }

        public List<ProjectInfo> GetWaitingReviewProject()
        {
            var user = Context.Staffs.FirstOrDefault(s=>s.Name == User.Identity.Name);

            var retList = Context.ProjectContentRecords
                .Include(p=>p.Project).ThenInclude(p=>p.Customer)
                .Where(p => p.State == 1 && p.CalMonth.Status == 0 && p.ReviewerId == user.Id).Select(p=>p.Project).Distinct().ToList();

            return retList;
        }

        public List<ProjectContents> GetProjectCanReviewWorkContent(string projectNo, int Year, int month)
        {
            var pcrList  = Context.ProjectContentRecords
                .Include(p => p.CalMonth)
                .Include(p => p.Reviewer)
                .Include(p => p.Staff)
                .Include(p => p.Project).ThenInclude(p => p.Customer)
                .Include(p => p.ProjectWorkContents)
                .Where(p => p.ProjectNo == projectNo && p.CalMonth.Year == Year && p.CalMonth.Month == month && p.State >0).ToList();
            


            List<ProjectContents> retList = new List<ProjectContents>();
            foreach (var retObj in pcrList)
            {
                ProjectContents ret = new ProjectContents();

                ret.ProjectContentRecord = retObj;
                ret.ProjectWorkContents = new List<ViewProjectWorkContent>();

                foreach (var wContent in retObj.ProjectWorkContents)
                {
                    ViewProjectWorkContent tem = new ViewProjectWorkContent();
                    tem.modifyState = ModifyState.UnChanged;
                    tem.Id = wContent.Id;
                    tem.Content = wContent.Content;
                    tem.ActualPerformance = wContent.ActualPerformance;
                    tem.ContentRecordId = wContent.ContentRecordId;
                    tem.FinalPerformance = wContent.FinalPerformance;
                    tem.TakeTime = wContent.TakeTime;
                    tem.TimeSpan = wContent.TimeSpan;
                    tem.WorkDate = wContent.WorkDate;

                    ret.ProjectWorkContents.Add(tem);
                }

                ret.ProjectContentRecord.ProjectWorkContents = null;

                retList.Add(ret);
            }

            return retList;
        }
        public List<ProjectContents> GetProjectWorkContentRecord(string projectNo,int Year,int month,int? state)
        {
            var pcrList = new List<ProjectContentRecord>();
            if (!state.HasValue)
            {
                pcrList = Context.ProjectContentRecords
                .Include(p => p.CalMonth)
                .Include(p => p.Reviewer)
                .Include(p=>p.Staff)
                .Include(p => p.Project).ThenInclude(p => p.Customer)
                .Include(p => p.ProjectWorkContents)
                .Where(p => p.ProjectNo == projectNo && p.CalMonth.Year == Year && p.CalMonth.Month == month).ToList();
            }
            else
            {
                pcrList = Context.ProjectContentRecords
                .Include(p => p.CalMonth)
                .Include(p => p.Reviewer)
                .Include(p => p.Staff)
                .Include(p => p.Project).ThenInclude(p => p.Customer)
                .Include(p => p.ProjectWorkContents)
                .Where(p => p.ProjectNo == projectNo && p.CalMonth.Year == Year && p.CalMonth.Month == month && p.State == state.Value).ToList();
            }
                

            List<ProjectContents> retList = new List<ProjectContents>();
            foreach(var retObj in pcrList)
            {
                ProjectContents ret = new ProjectContents();

                ret.ProjectContentRecord = retObj;
                ret.ProjectWorkContents = new List<ViewProjectWorkContent>();

                foreach (var wContent in retObj.ProjectWorkContents)
                {
                    ViewProjectWorkContent tem = new ViewProjectWorkContent();
                    tem.modifyState = ModifyState.UnChanged;
                    tem.Id = wContent.Id;
                    tem.Content = wContent.Content;
                    tem.ActualPerformance = wContent.ActualPerformance;
                    tem.ContentRecordId = wContent.ContentRecordId;
                    tem.FinalPerformance = wContent.FinalPerformance;
                    tem.TakeTime = wContent.TakeTime;
                    tem.TimeSpan = wContent.TimeSpan;
                    tem.WorkDate = wContent.WorkDate;

                    ret.ProjectWorkContents.Add(tem);
                }

                ret.ProjectContentRecord.ProjectWorkContents = null;

                retList.Add(ret);
            }

            return retList;
        }

        public List<ProjectContents> GetProjectHisttory(string projectNo)
        {
            var pcrList = Context.ProjectContentRecords
                .Include(p => p.CalMonth)
                .Include(p => p.Reviewer)
                .Include(p => p.Staff)
                .Include(p => p.Project).ThenInclude(p => p.Customer)
                .Include(p => p.ProjectWorkContents)
                .Where(p => p.ProjectNo == projectNo && p.State == 2)
                .OrderByDescending(p=>p.SubmitTime)
                .ToList();
            

            List<ProjectContents> retList = new List<ProjectContents>();
            foreach (var retObj in pcrList)
            {
                ProjectContents ret = new ProjectContents();

                ret.ProjectContentRecord = retObj;
                ret.ProjectWorkContents = new List<ViewProjectWorkContent>();

                foreach (var wContent in retObj.ProjectWorkContents)
                {
                    ViewProjectWorkContent tem = new ViewProjectWorkContent();
                    tem.modifyState = ModifyState.UnChanged;
                    tem.Id = wContent.Id;
                    tem.Content = wContent.Content;
                    tem.ActualPerformance = wContent.ActualPerformance;
                    tem.ContentRecordId = wContent.ContentRecordId;
                    tem.FinalPerformance = wContent.FinalPerformance;
                    tem.TakeTime = wContent.TakeTime;
                    tem.TimeSpan = wContent.TimeSpan;
                    tem.WorkDate = wContent.WorkDate;

                    ret.ProjectWorkContents.Add(tem);
                }

                ret.ProjectContentRecord.ProjectWorkContents = null;

                retList.Add(ret);
            }

            return retList;
        }
    }
}
