using System;
using System.Collections.Generic;
using System.Linq;
using Model;
using System.Data;
namespace BLL
{
    public class SGManPowerService
    {
        /// 
        /// 检查并发送人力资源预警
        /// 
        public static List CheckAndSendPersonWarning(string userId)
        {
            var responeData = new Model.ResponeData();
            // 合并两个集合
            var allItems = new List();
            var projects = Funs.DB.Base_Project.Where(p => p.ProjectState == BLL.Const.ProjectState_1).ToList();
            foreach (var project in projects)
            {
                // 检查管理人员到期未到岗情况
                var items1 = CheckManagerNotArrived(project.ProjectId);
                // 检查作业人员人力偏差情况
                var items2 = CheckWorkerDeviation(project.ProjectId);
                if (items1 != null)
                {
                    allItems.AddRange(items1);
                }
                if (items2 != null)
                {
                    allItems.AddRange(items2);
                }
            }
            if (!string.IsNullOrEmpty(userId))
            {
                //过滤出指定用户的数据
                allItems = allItems.Where(x => x.UserId == userId).ToList();
            }
            return allItems;
        }
        /// 
        /// 检查管理人员到期未到岗情况(超过一周发出预警)
        /// 
        /// 项目ID
        private static IEnumerable CheckManagerNotArrived(string projectId)
        {
            //获取计划的最新版本
            var version = "1";
            var sgMan = Funs.DB.JDGL_SGManPower.Where(x => x.ProjectId == projectId).OrderByDescending(x => x.Version)
                .FirstOrDefault();
            if (sgMan != null)
            {
                version = sgMan.Version;
            }
            // 先获取计划表超过一周的管理岗位有哪些
            var dataList = (from x in Funs.DB.JDGL_SGManPower
                join p in Funs.DB.Base_WorkPost on x.WorkPostId equals p.WorkPostId into pp
                from y in pp.DefaultIfEmpty()
                where x.ProjectId == projectId && (y.PostType == "4" || y.PostType == "1") &&
                      x.PlanDate <= DateTime.Now.AddDays(-7) && x.Version == version
                select x).ToList();
            var lItems = new List();
            //循环检查实际考勤中的人数
            foreach (var data in dataList)
            {
                //根据人员计划表获取计划中的管理人员数
                int num = getInOutRecordNum(data);
                if (data.Quantity > num)
                {
                    lItems = SendManagerWarning(data.UnitId, projectId, data.WorkPostId, data.UnitWorkId, data.PlanDate,
                        data.Quantity, num);
                }
            }
            return lItems;
        }
        //获取实际考勤人员数
        private static int getInOutRecordNum(JDGL_SGManPower sgManPower)
        {
            string strSql = @"
                SELECT e.UnitId, e.PostId, e.RecordDate, p.WorkAreaId as UnitWorkId
                FROM T_d_EmployInOutRecord e INNER JOIN SitePerson_Person p ON e.IDCardNo = p.IdentityCard AND e.ProjectId = p.ProjectId
                WHERE e.PostId IS NOT NULL AND e.PostId != '' 
                AND e.ProjectId = @ProjectId 
                AND e.RecordDate = @RecordDate 
                AND e.UnitId = @UnitId 
                AND e.PostId = @PostId";
            var parameters = new List
            {
                new System.Data.SqlClient.SqlParameter("@ProjectId", sgManPower.ProjectId),
                new System.Data.SqlClient.SqlParameter("@RecordDate", sgManPower.PlanDate),
                new System.Data.SqlClient.SqlParameter("@UnitId", sgManPower.UnitId),
                new System.Data.SqlClient.SqlParameter("@PostId", sgManPower.WorkPostId),
            };
            // 执行查询获取分组数据
            var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray());
            // 创建一个新的DataTable来存储处理后的数据
            DataTable processedDt = dt.Clone();
            foreach (System.Data.DataRow row in dt.Rows)
            {
                string ids = row["UnitWorkId"] != DBNull.Value ? row["UnitWorkId"].ToString() : string.Empty;
                if (!string.IsNullOrEmpty(ids))
                {
                    string[] unitWorkIdArray = ids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string unitWorkId in unitWorkIdArray)
                    {
                        // 往processedDt里面添加数据,每个UnitWorkId一行
                        DataRow newRow = processedDt.NewRow();
                        newRow["UnitId"] = row["UnitId"];
                        newRow["PostId"] = row["PostId"];
                        newRow["RecordDate"] = row["RecordDate"];
                        newRow["UnitWorkId"] = unitWorkId.Trim();
                        processedDt.Rows.Add(newRow);
                    }
                }
                else
                {
                    DataRow newRow = processedDt.NewRow();
                    newRow["UnitId"] = row["UnitId"];
                    newRow["PostId"] = row["PostId"];
                    newRow["RecordDate"] = row["RecordDate"];
                    newRow["UnitWorkId"] = string.Empty;
                    processedDt.Rows.Add(newRow);
                }
            }
            // 确定要用于后续处理的数据源
            IEnumerable dataSource = processedDt.AsEnumerable();
            if (string.IsNullOrEmpty(sgManPower.UnitWorkId))
            {
                dataSource = dataSource.Where(x => x["UnitWorkId"] == null);
            }
            else
            {
                dataSource = dataSource.Where(x =>
                    x["UnitWorkId"] != DBNull.Value && x["UnitWorkId"].ToString() == sgManPower.UnitWorkId);
            }
            return dataSource.Count();
        }
        /// 
        /// 发送管理人员预警
        /// 
        /// 项目ID
        /// 单位id
        private static List SendManagerWarning(string unitId, string projectId, string workPostId,
            string unitWorkId, DateTime? planDate, int? quantity, int num)
        {
            // 发送预警信息
            var toDoItems = new List();
            var unitWorks = (from x in Funs.DB.WBS_UnitWork
                where x.UnitWorkId == unitWorkId
                select new { x.UnitWorkId, x.UnitWorkName }).FirstOrDefault();
            var projectUnits = (from x in Funs.DB.Project_ProjectUnit
                join y in Funs.DB.Base_Unit on x.UnitId equals y.UnitId
                where x.UnitId == unitId
                select new { x.UnitId, y.UnitName, x.UnitType }).FirstOrDefault();
            if (projectUnits != null)
            {
                List toUserIds = new List();
                // 施工单位人员推送至施工单位项目经理和总包单位施工经理
                if (projectUnits.UnitType == Const.ProjectUnitType_2) // 施工分包单位
                {
                    // 获取施工单位项目经理
                    var constructionManagers = (from x in Funs.DB.Project_ProjectUser
                        where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true &&
                              x.RoleId.Contains(Const.ProjectManager)
                        select x).ToList();
                    if (constructionManagers.Count > 0)
                    {
                        foreach (var projectUser in constructionManagers)
                        {
                            toUserIds.Add(projectUser.UserId);
                        }
                    }
                    // 获取总包单位施工经理
                    var generalContractorUnit = Funs.DB.Project_ProjectUnit.FirstOrDefault(pu =>
                        pu.ProjectId == projectId && pu.UnitType == Const.ProjectUnitType_1); // 总包单位
                    if (generalContractorUnit != null)
                    {
                        var constructionManagerGCs = (from x in Funs.DB.Project_ProjectUser
                            where x.ProjectId == projectId && x.UnitId == generalContractorUnit.UnitId &&
                                  x.IsPost == true && x.RoleId.Contains(Const.ConstructionManager)
                            select x).ToList();
                        if (constructionManagerGCs.Count > 0)
                        {
                            foreach (var projectUser in constructionManagerGCs)
                            {
                                toUserIds.Add(projectUser.UserId);
                            }
                        }
                    }
                }
                // 总包单位人员推送到总包单位施工经理和项目经理
                else if (projectUnits.UnitType == Const.ProjectUnitType_1) // 总包单位
                {
                    // 获取总包单位施工经理
                    var constructionManagers = (from x in Funs.DB.Project_ProjectUser
                        where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true &&
                              x.RoleId.Contains(Const.ConstructionManager)
                        select x).ToList();
                    if (constructionManagers.Count() > 0)
                    {
                        foreach (var projectUser in constructionManagers)
                        {
                            toUserIds.Add(projectUser.UserId);
                        }
                    }
                    // 获取总包单位项目经理
                    var projectManagers = (from x in Funs.DB.Project_ProjectUser
                        where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true &&
                              x.RoleId.Contains(Const.ProjectManager)
                        select x).ToList();
                    if (projectManagers.Count() > 0)
                    {
                        foreach (var projectUser in projectManagers)
                        {
                            toUserIds.Add(projectUser.UserId);
                        }
                    }
                }
                string warningContent = string.Empty;
                if (unitWorks != null)
                {
                    warningContent =
                        $"{projectUnits.UnitName}单位{unitWorks.UnitWorkName}装置计划{string.Format("{0:yyyy-MM-dd}", planDate)}投入人力{quantity}人,实际考勤为{num}人。";
                }
                else
                {
                    warningContent =
                        $"{projectUnits.UnitName}单位计划{string.Format("{0:yyyy-MM-dd}", planDate)}投入人力{quantity}人,实际考勤为{num}人。";
                }
                string urlParams = "JDGL/SGManPower/SGWarningDetails.aspx?projectId=" + projectId;
                // 添加单位参数(如果已选择)
                if (!string.IsNullOrEmpty(unitId))
                {
                    urlParams += "&unitId=" + unitId;
                }
                // 添加装置参数(如果已选择)
                if (!string.IsNullOrEmpty(unitWorkId))
                {
                    urlParams += "&unitWorkId=" + unitWorkId;
                }
                // 添加岗位参数(如果已选择)
                if (!string.IsNullOrEmpty(workPostId))
                {
                    urlParams += "&workPostId=" + workPostId;
                }
                // 添加时间参数
                if (planDate.HasValue)
                {
                    urlParams += "&planDate=" + string.Format("{0:yyyy-MM-dd}", planDate);
                }
                // 添加岗位参数(如果已选择)
                if (quantity.HasValue)
                {
                    urlParams += "&quantity=" + quantity.Value;
                }
                // 添加岗位参数(如果已选择)
                if (num >= 0)
                {
                    urlParams += "&num=" + num;
                }
                else
                {
                    urlParams += "&num=0";
                }
                foreach (var userId in toUserIds)
                {
                    Model.ToDoItem toDoItem = new Model.ToDoItem();
                    toDoItem.DataId = SQLHelper.GetNewID(typeof(Model.ToDoItem));
                    toDoItem.MenuId = "";
                    toDoItem.MenuName = "管理人员到岗预警";
                    toDoItem.ProjectCode = "";
                    toDoItem.Content = warningContent;
                    toDoItem.UserId = userId;
                    toDoItem.UserName = UserService.GetUserNameByUserId(userId);
                    toDoItem.DataTime = DateTime.Now;
                    toDoItem.DataTimeStr = DateTime.Now.ToString("yyyy-MM-dd");
                    toDoItem.PCUrl = urlParams;
                    toDoItems.Add(toDoItem);
                }
            }
            return toDoItems;
        }
        // /// 
        // /// 检查作业人员人力偏差情况(一周内累计偏差值超过计划的10%)
        // /// 
        // /// 项目ID
        private static IEnumerable CheckWorkerDeviation(string projectId)
        {
            //获取计划的最新版本
            var version = "1";
            var sgMan = Funs.DB.JDGL_SGManPower.Where(x => x.ProjectId == projectId).OrderByDescending(x => x.Version)
                .FirstOrDefault();
            if (sgMan != null)
            {
                version = sgMan.Version;
            }
            //当前时间
            var endDate = DateTime.Now;
            //当前时间前7天
            var startDate = DateTime.Now.AddDays(-7);
            // 先获取计划表一周的作业岗位有哪些
            var dataList = (from x in Funs.DB.JDGL_SGManPower
                join p in Funs.DB.Base_WorkPost on x.WorkPostId equals p.WorkPostId into pp
                from y in pp.DefaultIfEmpty()
                where x.ProjectId == projectId && (y.PostType == "2" || y.PostType == "3") &&
                      x.PlanDate >= startDate && x.PlanDate <= endDate && x.Version == version
                group x by new
                {
                    x.UnitId,
                    x.UnitWorkId,
                    x.WorkPostId
                }
                into g
                select new
                {
                    UnitId = g.Key.UnitId,
                    UnitWorkId = g.Key.UnitWorkId,
                    WorkPostId = g.Key.WorkPostId,
                    QuantitySum = g.Sum(x => x.Quantity)
                }).ToList();
            var lItems = new List();
            //循环检查实际考勤中的人数
            foreach (var data in dataList)
            {
                //根据人员计划表获取计划中的作业人员数
                int num = getInOutRecordNum1(data.UnitId, data.UnitWorkId, data.WorkPostId, projectId);
                // 计算偏差百分比
                if (data.QuantitySum != 0)
                {
                    double deviationPercentage = Math.Abs((double)((data.QuantitySum - num) / data.QuantitySum));
                    // 如果偏差超过10%,发出预警
                    if (deviationPercentage > 0.1)
                    {
                        lItems = SendWorkerDeviationWarning(data.UnitId, projectId, data.WorkPostId, data.UnitWorkId,
                            startDate, endDate, data.QuantitySum, num);
                    }
                }
            }
            return lItems;
        }
        //获取实际考勤人员数
        private static int getInOutRecordNum1(string unitId, string unitWorkId, string workPostId, string projectId)
        {
            string strSql = @"
                SELECT e.UnitId, e.PostId, e.RecordDate, p.WorkAreaId as UnitWorkId
                FROM T_d_EmployInOutRecord e INNER JOIN SitePerson_Person p ON e.IDCardNo = p.IdentityCard AND e.ProjectId = p.ProjectId
                WHERE e.PostId IS NOT NULL AND e.PostId != '' 
                AND e.ProjectId = @ProjectId 
                AND e.UnitId = @UnitId 
                AND e.PostId = @PostId
                AND e.RecordDate >= @StartDate 
                AND e.RecordDate <= @EndDate";
            var parameters = new List
            {
                new System.Data.SqlClient.SqlParameter("@ProjectId", projectId),
                new System.Data.SqlClient.SqlParameter("@UnitId", unitId),
                new System.Data.SqlClient.SqlParameter("@PostId", workPostId),
                new System.Data.SqlClient.SqlParameter("@StartDate", DateTime.Now.AddDays(-7)),
                new System.Data.SqlClient.SqlParameter("@EndDate", DateTime.Now),
            };
            // 执行查询获取分组数据
            var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray());
            // 创建一个新的DataTable来存储处理后的数据
            DataTable processedDt = dt.Clone();
            foreach (System.Data.DataRow row in dt.Rows)
            {
                string ids = row["UnitWorkId"] != DBNull.Value ? row["UnitWorkId"].ToString() : string.Empty;
                if (!string.IsNullOrEmpty(ids))
                {
                    string[] unitWorkIdArray = ids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string id in unitWorkIdArray)
                    {
                        // 往processedDt里面添加数据,每个UnitWorkId一行
                        DataRow newRow = processedDt.NewRow();
                        newRow["UnitId"] = row["UnitId"];
                        newRow["PostId"] = row["PostId"];
                        newRow["RecordDate"] = row["RecordDate"];
                        newRow["UnitWorkId"] = id.Trim();
                        processedDt.Rows.Add(newRow);
                    }
                }
                else
                {
                    DataRow newRow = processedDt.NewRow();
                    newRow["UnitId"] = row["UnitId"];
                    newRow["PostId"] = row["PostId"];
                    newRow["RecordDate"] = row["RecordDate"];
                    newRow["UnitWorkId"] = string.Empty;
                    processedDt.Rows.Add(newRow);
                }
            }
            // 确定要用于后续处理的数据源
            IEnumerable dataSource = processedDt.AsEnumerable();
            if (string.IsNullOrEmpty(unitWorkId))
            {
                dataSource = dataSource.Where(x => x["UnitWorkId"] == null);
            }
            else
            {
                dataSource = dataSource.Where(x =>
                    x["UnitWorkId"] != DBNull.Value && x["UnitWorkId"].ToString() == unitWorkId);
            }
            return dataSource.Count();
        }
        /// 
        /// 发送作业人员偏差预警
        /// 
        /// 项目ID
        /// 单位ID
        /// 计划总人数
        /// 实际总人数
        /// 偏差百分比
        private static List SendWorkerDeviationWarning(string unitId, string projectId, string workPostId,
            string unitWorkId,
            DateTime? startDate, DateTime? endDate, int? quantity, int num)
        {
            // 发送预警信息
            var toDoItems = new List();
            List toUserIds = new List();
            var unitWorks = (from x in Funs.DB.WBS_UnitWork
                where x.UnitWorkId == unitWorkId
                select new { x.UnitWorkId, x.UnitWorkName }).FirstOrDefault();
            var projectUnits = (from x in Funs.DB.Project_ProjectUnit
                join y in Funs.DB.Base_Unit on x.UnitId equals y.UnitId
                where x.UnitId == unitId
                select new { x.UnitId, y.UnitName, x.UnitType }).FirstOrDefault();
            // 获取施工单位项目经理
            var constructionManagers = (from x in Funs.DB.Project_ProjectUser
                where x.ProjectId == projectId && x.UnitId == unitId && x.IsPost == true &&
                      x.RoleId.Contains(Const.ProjectManager)
                select x).ToList();
            if (constructionManagers.Count > 0)
            {
                foreach (var projectUser in constructionManagers)
                {
                    toUserIds.Add(projectUser.UserId);
                }
            }
            // 获取总包单位施工经理
            var generalContractorUnit = Funs.DB.Project_ProjectUnit.FirstOrDefault(pu =>
                pu.ProjectId == projectId && pu.UnitType == Const.ProjectUnitType_1); // 总包单位
            if (generalContractorUnit != null)
            {
                var constructionManagerGCs = (from x in Funs.DB.Project_ProjectUser
                    where x.ProjectId == projectId && x.UnitId == generalContractorUnit.UnitId &&
                          x.IsPost == true && x.RoleId.Contains(Const.ConstructionManager)
                    select x).ToList();
                if (constructionManagerGCs.Count > 0)
                {
                    foreach (var projectUser in constructionManagerGCs)
                    {
                        toUserIds.Add(projectUser.UserId);
                    }
                }
            }
            // 构建预警信息内容
            string warningContent = string.Empty;
            if (unitWorks != null)
            {
                warningContent =
                    $"{projectUnits.UnitName}单位{unitWorks.UnitWorkName}装置计划投入人力{quantity}人,实际考勤为{num}人。";
            }
            else
            {
                warningContent = $"{projectUnits.UnitName}单位计划投入人力{quantity}人,实际考勤为{num}人。";
            }
            string urlParams = "JDGL/SGManPower/SGWarningDetails.aspx?projectId=" + projectId;
            // 添加单位参数(如果已选择)
            if (!string.IsNullOrEmpty(unitId))
            {
                urlParams += "&unitId=" + unitId;
            }
            // 添加装置参数(如果已选择)
            if (!string.IsNullOrEmpty(unitWorkId))
            {
                urlParams += "&unitWorkId=" + unitWorkId;
            }
            // 添加岗位参数(如果已选择)
            if (!string.IsNullOrEmpty(workPostId))
            {
                urlParams += "&workPostId=" + workPostId;
            }
            // 添加时间参数
            if (startDate.HasValue && endDate.HasValue)
            {
                urlParams += "&planDate=" + string.Format("{0:yyyy-MM-dd}", startDate) + "~" +
                             string.Format("{0:yyyy-MM-dd}", endDate);
            }
            // 添加岗位参数(如果已选择)
            if (quantity.HasValue)
            {
                urlParams += "&quantity=" + quantity.Value;
            }
            // 添加岗位参数(如果已选择)
            if (num >= 0)
            {
                urlParams += "&num=" + num;
            }
            else
            {
                urlParams += "&num=0";
            }
            // 发送预警信息
            foreach (var userId in toUserIds)
            {
                Model.ToDoItem toDoItem = new Model.ToDoItem();
                toDoItem.DataId = SQLHelper.GetNewID(typeof(Model.ToDoItem));
                toDoItem.MenuId = "";
                toDoItem.MenuName = "人力资源偏差预警";
                toDoItem.ProjectCode = "";
                toDoItem.Content = warningContent;
                toDoItem.UserId = userId;
                toDoItem.UserName = UserService.GetUserNameByUserId(userId);
                toDoItem.DataTime = DateTime.Now;
                toDoItem.DataTimeStr = DateTime.Now.ToString("yyyy-MM-dd");
                toDoItem.PCUrl = urlParams;
                toDoItems.Add(toDoItem);
            }
            return toDoItems;
        }
    }
}