using DeviceRepair.DataAccess.Data;
using DeviceRepair.Models;
using DeviceRepair.Models.Enum;
using DeviceRepair.Models.Plan.View;
using DeviceRepair.Utils;
using NLog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
using System.Text;

namespace DeviceRepair.DataAccess.PLAN
{
    public class PlanDa : BaseDa
    {
        private static readonly Logger log = LogManager.GetCurrentClassLogger();
        public PlanDa(IDictionary<string, string> apiParams) : base(apiParams)
        {

        }

        #region PM
        /// <summary>
        /// 获取PM的保养计划
        /// </summary>
        /// <returns></returns>
        public DataSet Get_PM_PLAN_Datas()
        {
            DataSet dsDatas = new DataSet("Datas");
            try
            {
                string EquipmentID = ApiParameters["EquipmentID"];
                int Year = DateTime.Today.Year;
                int.TryParse(ApiParameters["Year"], out Year);
                int CurrentMonth = DateTime.Now.Month;

                var exp = Expressionable.Create<View_PM_PLAN>()
                        .And(x => x.MaintenanceYear == Year).
                        AndIF(!EquipmentID.IsNull(), x => x.DisplayEquipmentID == SqlFunc.Trim(EquipmentID)).ToExpression();//拼接表达式

                List<View_PM_PLAN> Datas = devMain.Queryable<View_PM_PLAN>().With(SqlWith.NoLock).Where(exp).ToList();

                int[] planIds = Datas.Select(x => x.AutoID).ToArray();
                Dictionary<int, MaintenanceRecordInfo> recordDict = devMain.Queryable<MaintenanceRecordInfo>().With(SqlWith.NoLock)
                  .Where(x => SqlFunc.ContainsArray(planIds, x.PlanPrimaryID)).ToList().ToDictionary(x => x.PlanPrimaryID, x => x);

                List<AnnualMaintenancePlan> lst = new List<AnnualMaintenancePlan>();
                Type type = typeof(AnnualMaintenancePlan);
                foreach (View_PM_PLAN data in Datas)
                {
                    AnnualMaintenancePlan item = null;
                    if (!lst.Any(x => x.EquipmentID == data.EquipmentID && x.MaintenanceYear == data.MaintenanceYear))
                    {
                        DateTime PMMonth;
                        item = new AnnualMaintenancePlan
                        {
                            EquipmentID = data.EquipmentID,
                            DisplayEquipmentID = data.DisplayEquipmentID,
                            EquipmentName = data.EquipmentName,
                            VersionCode = data.VersionCode,
                            MaintenanceYear = data.MaintenanceYear,
                            CreatUser = data.CreatUser,
                            CreatDate = data.CreatDate,
                            ChangeUser = data.ChangeUser,
                            ChangeDate = data.ChangeDate,
                            ChangeUserName = "",
                            Remarks = data.Remarks
                        };

                        if (DateTime.TryParse(data.PMStartMonth, out PMMonth))
                        {
                            item.PMStartMonth = PMMonth.ToString("yyyy-MM");
                        }

                        lst.Add(item);
                    }

                    item = lst.FirstOrDefault(x => x.EquipmentID == data.EquipmentID && x.MaintenanceYear == data.MaintenanceYear);
                    if (item == null)
                        continue;
                    EnumMonth month = (EnumMonth)(data.MaintenanceMonth);
                    PropertyInfo prop = type.GetProperty(month + "");
                    prop.SetValue(item, data.MaintenanceType);

                    EnumPlanCompleteStatus status = EnumPlanCompleteStatus.None;
                    if (string.IsNullOrWhiteSpace(data.MaintenanceType))
                        status = EnumPlanCompleteStatus.None;
                    else if (recordDict.ContainsKey(data.AutoID))
                        status = EnumPlanCompleteStatus.Complete;
                    else
                    {
                        if (data.MaintenanceMonth == CurrentMonth)
                        {
                            status = EnumPlanCompleteStatus.Current;
                        }
                        else if (data.MaintenanceMonth > CurrentMonth)
                        {
                            status = EnumPlanCompleteStatus.Future;
                        }
                        else if (data.MaintenanceMonth < CurrentMonth)
                        {
                            status = EnumPlanCompleteStatus.TimeOut;
                        }
                    }

                    prop = type.GetProperty(month + "Status");
                    prop.SetValue(item, status);
                }

                DataTable table = lst.OrderByDescending(x => x.ChangeDate).OrderByDescending(x => x.ChangeDate).ToList().ToDataTable();
                dsDatas.Tables.Add(table);

                return dsDatas;
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取当月保养
        /// </summary>
        /// <returns></returns>
        public DataSet Get_PM_PLAN_CurrentMonth()
        {
            DataSet dsDatas = new DataSet("Datas");
            try
            {
                List<View_CurrentMonthPlanTips> Datas = devMain.Queryable<View_CurrentMonthPlanTips>().ToList();
                DataTable table = Datas.ToDataTable();
                dsDatas.Tables.Add(table);
                return dsDatas;
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取单条PM计划任务进度
        /// </summary>
        /// <param name="dsDatas"></param>
        /// <returns></returns>
        public APIResponseData PM_PLAN_Single(out DataSet dsDatas)
        {
            dsDatas = new DataSet("Datas");

            try
            {
                if (!ApiParameters.ContainsKey("Year"))
                {
                    throw new ArgumentException("传入的计划年不能为空！");
                }

                int EquipmentAutoID = base.GetParamInt("EquipmentID", "设备编号");

                int Year = base.GetParamInt("Year", "计划年");

                string Belong = base.GetParamString("Belong", "计划类型");
                if (Belong.ToUpper() != "AM" && Belong.ToUpper() != "PM")
                    throw new ArgumentException("传入的计划类型值不正确！");

                if (Belong.ToUpper() == "AM")
                {
                    List<AnnualMaintenancePlan> Datas = devMain.Queryable<View_AnnualMaintenance_AMPlan>().Where(x => x.MaintenanceYear == Year && x.EquipmentID == EquipmentAutoID)
                    .Select(x => new AnnualMaintenancePlan
                    {
                        EquipmentID = x.EquipmentID,
                        DisplayEquipmentID = x.DisplayEquipmentID,
                        EquipmentName = x.EquipmentName,
                        VersionCode = x.VersionCode,
                        MaintenanceYear = x.MaintenanceYear,
                        Jan = x.Jan,
                        Feb = x.Feb,
                        Mar = x.Mar,
                        Apr = x.Apr,
                        May = x.May,
                        Jun = x.Jun,
                        Jul = x.Jul,
                        Aug = x.Aug,
                        Sep = x.Sep,
                        Oct = x.Oct,
                        Nov = x.Nov,
                        Dec = x.Dec,
                        PMStartMonth = x.PMStartMonth,
                        CreatUser = x.CreatUser,
                        CreatUserName = x.CreatUserName,
                        CreatDate = x.CreatDate,
                        ChangeUser = x.ChangeUser,
                        ChangeUserName = x.ChangeUserName,
                        ChangeDate = x.ChangeDate,
                        Remarks = x.Remarks
                    }).ToList();
                    if (Datas == null)
                    {
                        throw new ArgumentException("传入的数据不正确，获取计划信息失败！");
                    }

                    DataTable table = Datas.ToDataTable();
                    dsDatas.Tables.Add(table);
                }
                else if (Belong.ToUpper() == "PM")
                {
                    List<AnnualMaintenancePlan> Datas = devMain.Queryable<View_AnnualMaintenancePlan>().Where(x => x.MaintenanceYear == Year && x.EquipmentID == EquipmentAutoID)
                    .Select(x => new AnnualMaintenancePlan
                    {
                        EquipmentID = x.EquipmentID,
                        DisplayEquipmentID = x.DisplayEquipmentID,
                        EquipmentName = x.EquipmentName,
                        VersionCode = x.VersionCode,
                        MaintenanceYear = x.MaintenanceYear,
                        Jan = x.Jan,
                        Feb = x.Feb,
                        Mar = x.Mar,
                        Apr = x.Apr,
                        May = x.May,
                        Jun = x.Jun,
                        Jul = x.Jul,
                        Aug = x.Aug,
                        Sep = x.Sep,
                        Oct = x.Oct,
                        Nov = x.Nov,
                        Dec = x.Dec,
                        PMStartMonth = x.PMStartMonth,
                        CreatUser = x.CreatUser,
                        CreatUserName = x.CreatUserName,
                        CreatDate = x.CreatDate,
                        ChangeUser = x.ChangeUser,
                        ChangeUserName = x.ChangeUserName,
                        ChangeDate = x.ChangeDate,
                        Remarks = x.Remarks
                    }).ToList();
                    if (Datas == null)
                    {
                        throw new ArgumentException("传入的数据不正确，获取计划信息失败！");
                    }

                    DataTable table = Datas.ToDataTable();
                    dsDatas.Tables.Add(table);
                }

                return new APIResponseData { Code = 1, Message = "操作成功！" };
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取PM的保养计划导出数据
        /// </summary>
        /// <param name="dsDatas"></param>
        /// <returns></returns>
        public APIResponseData Get_PM_PLAN_Xlsx(out DataSet dsDatas)
        {
            dsDatas = new DataSet("Datas");

            try
            {
                int Year = DateTime.Today.Year;
                int.TryParse(ApiParameters["Year"], out Year);

                List<View_YearsMaintenancePlansExport> lst = devMain.Queryable<View_YearsMaintenancePlansExport>()
                   .With(SqlWith.NoLock).Where(x => x.MaintenanceYear == Year)?.ToList();

                DataTable table = lst.ToDataTable();
                dsDatas.Tables.Add(table);
                return new APIResponseData { Code = 1, Message = "操作成功！" };
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }
        #endregion

        #region AM

        /// <summary>
        /// 获取PM的保养计划
        /// </summary>
        /// <returns></returns>
        public DataSet Get_AM_PLAN_Datas()
        {
            try
            {
                string EquipmentID = ApiParameters["EquipmentID"];
                int Year = DateTime.Today.Year;
                int.TryParse(ApiParameters["Year"], out Year);
                int CurrentMonth = DateTime.Now.Month;

                DataTable table = devMain.Ado.UseStoredProcedure().GetDataTable("Proc_AnnualEquipmentMaintenanceProgram", new { Year = Year, Keyword = EquipmentID });
                return table.DataSet;
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取PM的保养计划导出数据
        /// </summary>
        /// <param name="dsDatas"></param>
        /// <returns></returns>
        public APIResponseData Get_AM_PLAN_Xlsx(out DataSet dsDatas)
        {
            dsDatas = new DataSet("Datas");

            try
            {
                int Year = DateTime.Today.Year;
                int.TryParse(ApiParameters["Year"], out Year);

                List<View_AMYearsMaintenancePlansExport> lst = devMain.Queryable<View_AMYearsMaintenancePlansExport>()
                   .With(SqlWith.NoLock).Where(x => x.MaintenanceYear == Year)?.ToList();

                DataTable table = lst.ToDataTable();
                dsDatas.Tables.Add(table);
                return new APIResponseData { Code = 1, Message = "操作成功！" };
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        public DataSet AM_PLAN_Scheduler()
        {
            try
            {
                if (!ApiParameters.ContainsKey("PlanAutoID"))
                {
                    throw new ArgumentException("传入的计划编号不能为空！");
                }

                int PlanAutoID = 0;
                if (!int.TryParse(ApiParameters["PlanAutoID"], out PlanAutoID))
                {
                    throw new ArgumentException("传入的计划编号格式不正确！");
                }

                string sql = @"SELECT MaintenanceDay,
       IIF(COUNT(Banci) = SUM(IsComplete), 1, 0) AS IsComplete
FROM dbo.func_GetDailyPlanProccScheduleDetail(@PlanAutoID)
GROUP BY MaintenanceDay;";

                return devMain.Ado.GetDataTable(sql, new { PlanAutoID }).DataSet;
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }


        #endregion

        /// <summary>
        /// 获取设备在年度的全部保养信息
        /// </summary>
        /// <param name="EquipmentAutoID"></param>
        /// <param name="Year"></param>
        /// <returns></returns>
        public DataSet GetDeviceInformationPlans()
        {
            DataSet dsDatas = new DataSet("Datas");
            try
            {
                int EquipmentAutoID = base.GetParamInt("EquipmentID", "设备编号");
                int Year = base.GetParamInt("Year", "计划年");
                string Belong = base.GetParamString("Belong", "计划类型");

                if (Belong.ToUpper() != "AM" && Belong.ToUpper() != "PM")
                    throw new ArgumentException("传入的计划类型值不正确！");

                // 获取设备计划信息
                DeviceInformationInfo Dev = devMain.Queryable<DeviceInformationInfo>().First(x => x.AutoID == EquipmentAutoID);

                if (Dev == null)
                    throw new Exception($"编号为：{EquipmentAutoID} 的设备不存在！");

                // 获取计划信息
                List<DriveMaintencePlanInfo> plans = devMain.Queryable<DriveMaintencePlanInfo>().Where(x => x.PlanStatus == "A" && x.Belong == Belong && x.EquipmentID == EquipmentAutoID && x.MaintenanceYear == Year && SqlFunc.HasValue(x.MaintenanceType)).ToList();
                if ((plans?.Count ?? 0) == 0)
                    throw new Exception($"编号为：{Dev.EquipmentID} 的设备计划为空！");

                int[] pIds = plans.Select(x => x.AutoID).ToArray();

                // 获取保养的记录信息
                List<MaintenanceRecordInfo> records = devMain.Queryable<MaintenanceRecordInfo>().Where(x => x.EquipmentPrimaryID == EquipmentAutoID && SqlFunc.ContainsArray(pIds, x.PlanPrimaryID)).ToList();

                if (Dev.MaintenanceFormVersion != 0 || Dev.MaintenanceAMFormVersion != 0)
                {
                    //devs.CurrentFormCode = devMain.Queryable<MaintenanceFormVersionInfo>().First(x => x.AutoID == Dev.MaintenanceFormVersion)?.VersionCode;
                    DataTable Form = devMain.Ado.GetDataTable(@"SELECT 
                        MAX(CASE WHEN AutoID = @PM_FORM THEN VersionCode ELSE '' END ) AS PM_FormCode,
                        MAX(CASE WHEN AutoID = @AM_FORM THEN VersionCode ELSE '' END ) AS AM_FormCode
                        FROM dbo.MaintenanceFormVersion WHERE AutoID = @PM_FORM OR AutoID = @AM_FORM", new { PM_FORM = Dev.MaintenanceFormVersion, AM_FORM = Dev.MaintenanceAMFormVersion });
                    if (Form != null && Form.Rows.Count > 0)
                    {
                        dsDatas.Clear();
                        dsDatas = Form.DataSet;
                    }
                }

                DataTable devDT = Dev.toDataTable();
                DataTable planDT = ListToDataTable(plans);
                DataTable Records = ListToDataTable(records);
                dsDatas.Tables.Add(devDT);
                dsDatas.Tables.Add(planDT);
                dsDatas.Tables.Add(Records);
                return dsDatas;
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取当前计划是否存的保养记录
        /// </summary>
        /// <returns></returns>
        public DataSet Get_PlanRecordProgress()
        {
            DataSet dsDatas = new DataSet("Datas");

            try
            {
                int EquipmentAutoID = base.GetParamInt("EquipmentID", "设备编号");
                int Year = base.GetParamInt("Year", "计划年");
                string Belong = base.GetParamString("Belong", "计划类型");

                if (Belong.ToUpper() != "AM" && Belong.ToUpper() != "PM")
                    throw new ArgumentException("传入的计划类型值不正确！");

                List<PlanProgress> Datas = devMain.Queryable<DriveMaintencePlanInfo, MaintenanceRecordInfo>((t1, t2) => new object[] { JoinType.Inner, t1.AutoID == t2.PlanPrimaryID && t1.MaintenanceType == t2.PlanType })
                .Where((t1, t2) => t1.Belong == Belong && t2.EquipmentPrimaryID == EquipmentAutoID && t2.MYear == Year)
                .Select((t1, t2) => new PlanProgress
                {
                    PlanAutoID = t1.AutoID,
                    PlanMonth = t1.MaintenanceMonth,
                    PlanType = t1.MaintenanceType,
                    PlanYear = t1.MaintenanceYear,
                    RecordAutoID = t2.AutoID
                }).ToList();

                if (Datas != null && Datas.Count > 0)
                    dsDatas.Tables.Add(ListToDataTable(Datas));
                return dsDatas;
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 删除PM保养计划
        /// </summary>
        /// <param name="Year"></param>
        /// <param name="EquipmentAutoID"></param>
        /// <returns></returns>
        public APIResponseData Delete_PM_PLAN()
        {
            try
            {
                int EquipmentAutoID = base.GetParamInt("EquipmentID", "设备编号");
                int Year = base.GetParamInt("Year", "计划年");
                string Belong = base.GetParamString("Belong", "计划类型");

                if (Belong.ToUpper() != "AM" && Belong.ToUpper() != "PM")
                    throw new ArgumentException("传入的计划类型值不正确！");

                List<DriveMaintencePlanInfo> Datas = devMain.Queryable<DriveMaintencePlanInfo>()
                    .Where(x => x.MaintenanceYear == Year && x.EquipmentID == EquipmentAutoID && x.Belong == Belong).ToList();

                if ((Datas?.Count ?? 0) == 0)
                {
                    throw new ArgumentException("传入的数据不正确，获取计划信息失败！");
                }

                int[] PlanIds = Datas.Select(x => x.AutoID).ToArray();

                /* 判断是否存在已保养数据 */
                if (devMain.Queryable<MaintenanceRecordInfo>().Any(x => PlanIds.Contains(x.PlanPrimaryID)))
                    return new APIResponseData { Code = -1, Message = "当前计划下存在已保养数据,无法删除！" };

                Datas.AsParallel().ForEach(x => { x.PlanStatus = "G"; });

                devMain.BeginTran();
                if (devMain.Updateable(Datas).ExecuteCommand() == Datas.Count)
                {
                    devMain.CommitTran();
                    return new APIResponseData { Code = 1, Message = "操作成功！" };
                }
                else
                {
                    devMain.RollbackTran();
                    return new APIResponseData { Code = -1, Message = "操作失败！" };
                }
            }
            catch (SqlException sqlEx)
            {
                devMain.RollbackTran();
                throw sqlEx;
            }
            catch (Exception ex)
            {
                devMain.RollbackTran();
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取计划任务进度
        /// </summary>
        /// <param name="dsDatas"></param>
        /// <returns></returns>
        public APIResponseData Get_PM_PLAN_ProgressInfo(out DataSet dsDatas)
        {
            dsDatas = new DataSet("Datas");

            try
            {
                int EquipmentAutoID = base.GetParamInt("EquipmentID", "设备编号");
                int Year = base.GetParamInt("Year", "计划年");

                List<View_PM_Plan_ProgressInfo> Datas = devMain.Queryable<View_PM_Plan_ProgressInfo>().Where(x => x.PlanYear == Year && x.EquipmentID == EquipmentAutoID).ToList();
                if ((Datas?.Count ?? 0) == 0)
                {
                    throw new ArgumentException("传入的数据不正确，获取计划信息失败！");
                }

                DataTable table = Datas.ToDataTable();
                dsDatas.Tables.Add(table);
                return new APIResponseData { Code = 1, Message = "操作成功！" };
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取计划任务进度
        /// </summary>
        /// <param name="dsDatas"></param>
        /// <returns></returns>
        public APIResponseData Get_AM_PLAN_ProgressInfo(out DataSet dsDatas)
        {
            dsDatas = new DataSet("Datas");

            try
            {
                int EquipmentAutoID = base.GetParamInt("EquipmentID", "设备编号");
                int Year = base.GetParamInt("Year", "计划年");

                List<View_PM_Plan_ProgressInfo> Datas = devMain.SqlQueryable<View_PM_Plan_ProgressInfo>("SELECT * FROM View_AM_Plan_Progress").Where(x => x.PlanYear == Year && x.EquipmentID == EquipmentAutoID).ToList();
                if ((Datas?.Count ?? 0) == 0)
                {
                    throw new ArgumentException("传入的数据不正确，获取计划信息失败！");
                }

                DataTable table = Datas.ToDataTable();
                dsDatas.Tables.Add(table);
                return new APIResponseData { Code = 1, Message = "操作成功！" };
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 新增或编辑
        /// </summary>
        /// <param name="lst"></param>
        /// <returns></returns>
        public APIResponseData Insert_OR_Edit_PM_PLAN(List<DriveMaintencePlanInfo> lst)
        {
            APIResponseData apiResponseData = new APIResponseData { Code = -1, Message = $"新增失败或当前数据无更改，请重试！" };

            try
            {
                if (!ApiParameters.ContainsKey("OPERATORAUTOID"))
                {
                    throw new ArgumentException("非法的操作,当前操作人参数不正确！");
                }

                if (!ApiParameters.ContainsKey("Belong"))
                {
                    throw new ArgumentException("传入的计划类型不能为空！");
                }
                string Belong = ApiParameters["Belong"]?.Trim();
                if (Belong.ToUpper() != "AM" && Belong.ToUpper() != "PM")
                    throw new ArgumentException("传入的计划类型值不正确！");

                int OperationID = Convert.ToInt32(ApiParameters["OPERATORAUTOID"] + "");

                DateTime CurrentTime = DateTime.Now;
                if (lst == null || lst.Count == 0)
                    throw new Exception("插入的数据集合,不能为空！");

                // 操作对象
                Dictionary<EnumOperationType, List<DriveMaintencePlanInfo>> OperationList = new Dictionary<EnumOperationType, List<DriveMaintencePlanInfo>>();
                OperationList.Add(EnumOperationType.Add, new List<DriveMaintencePlanInfo>());
                OperationList.Add(EnumOperationType.Change, new List<DriveMaintencePlanInfo>());

                devMain.BeginTran();
                int Year = lst[0].MaintenanceYear;
                int[] equipmentIds = lst.Select(x => x.EquipmentID).Distinct().ToArray();

                // 设备编号校验
                Dictionary<int, DeviceInformationInfo> devs =
                    DeviceAccess.Instance.CurrentDb.AsQueryable().With(SqlWith.NoLock).Where(x => SqlFunc.ContainsArray(equipmentIds, x.AutoID)).ToList().ToDictionary(x => x.AutoID, x => x);

                System.Text.StringBuilder builder = new StringBuilder();
                foreach (int id in equipmentIds)
                {
                    if (!devs.ContainsKey(id))
                    {
                        builder.AppendLine($"设备编号：{id} ,不存在于系统中！");
                    }
                }

                if (builder.Length > 0)
                    throw new Exception(builder.ToString());

                // 计划校验
                List<DriveMaintencePlanInfo> Plans = devMain.Queryable<DriveMaintencePlanInfo>()
                    .With(SqlWith.NoLock).Where(x => SqlFunc.ContainsArray(equipmentIds, x.EquipmentID) && x.MaintenanceYear == Year && x.Belong == Belong && x.PlanStatus == "A").ToList();
                int[] planIds = Plans.Select(x => x.AutoID).Distinct().ToArray();

                // 已保养数据不允许修改
                List<MaintenanceRecordInfo> Records = devMain.Queryable<MaintenanceRecordInfo>().Where(x => SqlFunc.ContainsArray(planIds, x.PlanPrimaryID)).ToList();
                foreach (MaintenanceRecordInfo item in Records)
                {
                    DriveMaintencePlanInfo t = Plans.FirstOrDefault(x => x.AutoID == item.PlanPrimaryID);
                    if (t != null)
                    {
                        DriveMaintencePlanInfo tt = lst.FirstOrDefault(x => x.MaintenanceMonth == t.MaintenanceMonth && x.EquipmentID == t.EquipmentID);
                        if (tt != null)
                        {
                            // 计划已保养，但本次操作未修改此条保养的数据，正常执行
                            if (tt.MaintenanceType == t.MaintenanceType)
                            {
                                lst.RemoveAll(x => x.MaintenanceType == t.MaintenanceType && x.MaintenanceMonth == t.MaintenanceMonth && x.EquipmentID == t.EquipmentID);
                            }
                            else
                            {
                                // 计划已保养且本次欲修改此数据，退出保养
                                builder.AppendLine($"设备编号：{devs[t.EquipmentID].EquipmentID} 在{t.MaintenanceMonth}月的计划，存在已保养的数据，无法更改！");
                            }
                        }
                    }
                }

                if (builder.Length > 0)
                    throw new Exception(builder.ToString());

                // 修改的计划
                List<int> DelPlanIds = new List<int>();
                foreach (DriveMaintencePlanInfo item in Plans)
                {
                    // 取数据库计划信息，对应当前传入的计划
                    DriveMaintencePlanInfo t = lst.FirstOrDefault(x => x.MaintenanceMonth == item.MaintenanceMonth && x.EquipmentID == item.EquipmentID);

                    if (t != null && ((t.MaintenanceType != item.MaintenanceType) || t.PMStartMonth != item.PMStartMonth || t.Remarks != item.Remarks))
                    {
                        // 修改的数据
                        item.ChangeDate = CurrentTime;
                        item.ChangeUser = OperationID;
                        item.MaintenanceType = t.MaintenanceType;
                        item.PMStartMonth = t.PMStartMonth;
                        item.Remarks = t.Remarks;
                        OperationList[EnumOperationType.Change].Add(item);
                    }
                    else
                    {
                        OperationList[EnumOperationType.Change].Add(item);
                    }
                }

                // 新增的计划
                int[] EditEquipmentIds = OperationList[EnumOperationType.Change].Select(x => x.EquipmentID).Distinct().ToArray();
                List<DriveMaintencePlanInfo> InPlans = lst.Where(x => x.MaintenanceYear == Year && !EditEquipmentIds.Contains(x.EquipmentID)).ToList();
                foreach (DriveMaintencePlanInfo item in InPlans)
                {
                    item.PlanStatus = "A";
                    item.CreatDate = CurrentTime;
                    item.CreatUser = OperationID;
                    item.ChangeDate = null;
                    item.ChangeUser = 0;

                    OperationList[EnumOperationType.Add].Add(item);
                }


                // 存在新增项
                List<DriveMaintencePlanInfo> FulfillmentLst = new List<DriveMaintencePlanInfo>();
                FulfillmentLst.AddRange(OperationList[EnumOperationType.Add]);
                FulfillmentLst.AddRange(OperationList[EnumOperationType.Change]);


                if (devMain.Saveable(FulfillmentLst).ExecuteCommand() == FulfillmentLst.Count)
                {
                    devMain.CommitTran();
                    apiResponseData.Code = 1;
                    apiResponseData.Data = lst.Count;

                    List<PlanlogInfo> logs = new List<PlanlogInfo>();

                    foreach (KeyValuePair<EnumOperationType, List<DriveMaintencePlanInfo>> item in OperationList)
                    {
                        foreach (DriveMaintencePlanInfo data in item.Value)
                        {
                            DeviceInformationInfo dev = null;
                            if (devs.ContainsKey(data.EquipmentID))
                                dev = devs[data.EquipmentID];
                            else
                                throw new Exception($"没有查询到设备表主键编号为【{data.EquipmentID}】的数据！");

                            logs.Add(new PlanlogInfo
                            {
                                EquipmentAutoID = data.EquipmentID,
                                EquipmentID = dev.EquipmentID,
                                PlanMonth = data.MaintenanceMonth,
                                PlanYear = data.MaintenanceYear,
                                PlanType = data.MaintenanceType,
                                OperationUser = OperationID,
                                OperationUserName = ApiParameters["OPERATORNAME"],
                                OperationComputer = ApiParameters["CLIENTNAME"],
                                OperationIP = ApiParameters["CLIENTIP"],
                                OperationDate = CurrentTime,
                                OperationType = EnumOperationType.Add == item.Key ? "新增" : "修改"
                            });
                        }
                    }

                    devLog.Insertable(logs).ExecuteCommand();
                }
                else
                {
                    devMain.RollbackTran();
                    apiResponseData.Code = -1;
                }

                return apiResponseData;
            }
            catch (SqlException sqlEx)
            {
                devMain.RollbackTran();
                throw sqlEx;
            }
            catch (Exception ex)
            {
                devMain.RollbackTran();
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 获取单数据
        /// </summary>
        /// <param name="dsDatas"></param>
        /// <returns></returns>
        public APIResponseData Get_PLAN_Single(out DataSet dsDatas)
        {
            dsDatas = new DataSet("Datas");

            try
            {
                if (!ApiParameters.ContainsKey("AutoID"))
                {
                    throw new ArgumentException("传入的计划编号不能为空！");
                }

                int AutoID = 0;
                if (!int.TryParse(ApiParameters["AutoID"], out AutoID))
                {
                    throw new ArgumentException("传入的计划编号格式不正确！");
                }

                List<DriveMaintencePlanInfo> Datas = devMain.Queryable<DriveMaintencePlanInfo>().Where(x => x.AutoID == AutoID).ToList();
                if ((Datas?.Count ?? 0) == 0)
                {
                    throw new ArgumentException("传入的数据不正确，获取计划信息失败！");
                }

                DataTable table = Datas.ToDataTable();
                dsDatas.Tables.Add(table);

                return new APIResponseData { Code = 1, Message = "操作成功！" };
            }
            catch (SqlException sqlEx)
            {
                throw sqlEx;
            }
            catch (Exception ex)
            {
                log.Error(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 判断当前开工设备是否存在未完成的保养计划
        /// </summary>
        /// <param name="EquipmentID"></param>
        /// <returns></returns>
        public APIResponseData Get_EquipmentPlanIsComplete(string EquipmentID, int Banci)
        {
            try
            {
                if (EquipmentID.IsNull())
                {
                    throw new ArgumentNullException("输入的设备编号参数不能为空！");
                }

                if (!devMain.Queryable<DeviceInformationInfo>().Any(x => x.EquipmentID == EquipmentID))
                {
                    throw new ArgumentNullException("输入的设备编号错误或不存在！");
                }

                int Operation = base.GetParamInt("OPERATORAUTOID", "操作员");
                var parEquipmentDisplayID = new SugarParameter("@EquipmentDisplayID", EquipmentID);
                var parBanci = new SugarParameter("@Banci", Banci);
                var parCreateBy = new SugarParameter("@CreateBy", Operation);
                var parCreateClient = new SugarParameter("@CreateClient", ApiParameters["CLIENTIP"]);
                var parMsg = new SugarParameter("@Msg", null, true);

                devMain.Ado.UseStoredProcedure().ExecuteCommand("proc_EquipmentPlanIsComplete", parEquipmentDisplayID, parBanci, parCreateBy, parCreateClient, parMsg);

                return new APIResponseData { Code = 1, Message = parMsg.Value + "" };
            }
            catch (Exception ex)
            {
                return new APIResponseData { Code = -1, Message = ex.Message };
            }
        }

    }
}
