using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using MadRunFabric.Common;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using DistributionApi.IRepositories;
using Api.SignToken;
using System.Security.Claims;
using DistributionApi.Models.Input;
using MadRunFabric.Model;
using MongoDB.Bson;
using System.Threading;
using MadRunFabric.Model.MessageApi;
using Microsoft.Extensions.Configuration;

namespace DistributionApi.Controllers
{
    /// <summary>
    /// 配送计划 - 省三院
    /// </summary>
    [Authorize]
    [ApiVersion("6.0")]
    [Route("api/[controller]")]
    [Produces("application/json")]
    public class DistriWorkOrderPlanController : BaseController
    {
        private readonly ILogger<DistriWorkOrderPlanController> _logger;
        private readonly IConfiguration _configuration;
        private readonly ISys_User_AccountRepository _sys_user_accountRepository;
        private readonly ISignTokenService _signTokenService;
        private readonly IDistri_Workorder_PlanRepository _distri_workorder_planrepository;
        private readonly IDistri_Workorder_PlanTaskRepository _distri_workorder_plantaskrepository;
        private readonly IDistri_WorkorderRepository _distri_workorderrepository;
        private readonly IDistri_Workorder_ItemsRepository _distri_workorder_itemsrepository;
        private readonly IDistri_Workorder_EvaluateRepository _distri_workorder_evaluaterepository;
        private readonly IPro_Project_InfoRepository _pro_project_infoRepository;
        private readonly IHangfirePlan_DistributionRepository _hangfireplan_distributionrepository;
        private readonly IHangfireService _hangfireService;
        private readonly IWechatService _wechatservice;
        private readonly ISys_ClassGroupRepository _sys_classgrouprepository;
        private readonly ISys_ClassGroup_User_MapRepository _sys_classgroup_user_maprepository;
        private readonly ISys_User_AccountRepository _sys_user_accountrepository;
        private readonly ISys_Role_InfoRepository _sys_role_inforepository;
        private readonly IWo_Order_User_MapRepository _wo_order_user_maprepository;
        private readonly ISys_User_AccountRepository _distri_sys_user_accountrepository;
        public DistriWorkOrderPlanController(
           ILogger<DistriWorkOrderPlanController> logger,
            IConfiguration configuration,
            ISys_User_AccountRepository sys_user_accountRepository,
           ISignTokenService signTokenService,
           IDistri_Workorder_PlanRepository distri_workorder_planrepository,
           IDistri_Workorder_PlanTaskRepository distri_workorder_plantaskrepository,
           IDistri_WorkorderRepository distri_workorderrepository,
           IDistri_Workorder_ItemsRepository distri_workorder_itemsrepository,
           IDistri_Workorder_EvaluateRepository distri_workorder_evaluaterepository,
           IPro_Project_InfoRepository pro_project_infoRepository,
           IHangfirePlan_DistributionRepository hangfireplan_distributionrepository,
           IHangfireService hangfireService,
           IWechatService wechatservice,
           ISys_ClassGroupRepository sys_classgrouprepository,
           ISys_ClassGroup_User_MapRepository sys_classgroup_user_maprepository,
           ISys_User_AccountRepository sys_user_accountrepository,
           ISys_Role_InfoRepository sys_role_inforepository,
           IWo_Order_User_MapRepository wo_order_user_maprepository,
           ISys_User_AccountRepository distri_sys_user_accountrepository
           )
        {
            _logger = logger;
            _configuration = configuration;
            _sys_user_accountRepository = sys_user_accountRepository;
            _signTokenService = signTokenService;
            _distri_workorder_planrepository = distri_workorder_planrepository;
            _distri_workorder_plantaskrepository = distri_workorder_plantaskrepository;
            _distri_workorderrepository = distri_workorderrepository;
            _distri_workorder_itemsrepository = distri_workorder_itemsrepository;
            _distri_workorder_evaluaterepository = distri_workorder_evaluaterepository;
            _pro_project_infoRepository = pro_project_infoRepository;
            _hangfireplan_distributionrepository = hangfireplan_distributionrepository;
            _hangfireService = hangfireService;
            _wechatservice = wechatservice;
            _sys_classgrouprepository = sys_classgrouprepository;
            _sys_classgroup_user_maprepository = sys_classgroup_user_maprepository;
            _sys_user_accountrepository = sys_user_accountrepository;
            _sys_role_inforepository = sys_role_inforepository;
            _wo_order_user_maprepository = wo_order_user_maprepository;
            _distri_sys_user_accountrepository = distri_sys_user_accountrepository;
        }

        #region 计划管理

        /// <summary>
        /// 获取配送计划列表分页 by page
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="stime"></param>
        /// <param name="etime"></param>
        /// <param name="pageindex"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        [HttpGet("getlistbypage")]
        public async Task<IActionResult> GetListByPageAsync(string keyword, string projectid, int planstate = -1, int pageindex = 1, int pagesize = 10)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            //var userstr = _signTokenService.GetUserInfoAsync(usercode).Result;
            //var userinfo = userstr.ToJObject()["data"].ToString().ToObject<UserInfoModel>();
            
            var userinfos = _sys_user_accountRepository.GetUserInfo(usercode);
            var userinfo = JsonHelper.JsonToEntity<UserAccountInfoModel>(userinfos.ToJson());

            //获取数据
            int recordCount = 0;
            var result = _distri_workorder_planrepository.GetListsByPage(keyword, projectid, planstate, userinfo, pageindex, pagesize, out recordCount);
            var list = result.ToList();
            //获取所有 HangFirePlan 关系图
            var listHangFirePlan = await _hangfireplan_distributionrepository.GetAll();
            foreach (var item in list)
            {
                if (!string.IsNullOrWhiteSpace(item.hangfireid))
                {
                    var hfmo = listHangFirePlan.FirstOrDefault(x=>x.id == item.hangfireid);
                    if (hfmo != null)
                    {
                        item.plancycle = hfmo.plancycle;
                        item.planinterval = hfmo.planinterval;
                        item.plantimes = hfmo.plantimes;
                        item.extensiontime = hfmo.extensiontime;
                    }
                }
            }
            var obj = new
            {
                rows = list.ToList(),
                total = recordCount
            };
            return Success("获取成功", obj);
        }       

        /// <summary>
        /// 获取配送计划详情
        /// </summary>
        [HttpGet("getsingle")]
        public async Task<IActionResult> GetSingleAsync(string id)
        {
            if (string.IsNullOrEmpty(id))
                return Error("参数错误");
            var model = _distri_workorder_planrepository.GetDetails(id);
            if (model != null)
            {
                if (!string.IsNullOrWhiteSpace(model.hangfireid))
                {
                    var hfmo = await _hangfireplan_distributionrepository.GetSingle(model.hangfireid);
                    if (hfmo != null)
                    {
                        model.plancycle = hfmo.plancycle;
                        model.planinterval = hfmo.planinterval;
                        model.plantimes = hfmo.plantimes;
                        model.extensiontime = hfmo.extensiontime;
                    }
                }
                return Success("获取成功！", model);
            }
            return Success("获取成功", model);
        }

        /// <summary>
        /// 添加配送计划
        /// </summary>
        [HttpPost("add")]
        public async Task<IActionResult> AddAsync(DistriWorkOrderPlanInput input)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            string username = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name).Value;

            if (string.IsNullOrWhiteSpace(input.projectid))
                return Error("请选择项目");
            var pro = await _pro_project_infoRepository.GetSingle(input.projectid);
            if (pro != null && pro.isend == 1)
                return Error("该项目已暂停");

            #region 判断验证
            if (string.IsNullOrEmpty(input.projectid))
                return Error("请选择项目");
            if (string.IsNullOrEmpty(input.planname))
                return Error("请选择计划名称");
            if (input.goodslist == null || input.goodslist.Count <= 0)
                return Error("请选择物品种类");
            int goodsnum = input.goodslist.Sum(x => x.num);
            if (goodsnum <= 0)
                return Error("请填写物品数量");
            if (input.deliverylist == null || input.deliverylist.Count <= 0)
                return Error("请选择发货地址");
            #endregion

            var model = new Distri_Workorder_Plan();
            #region model 添加配送计划对象
            model.projectid = input.projectid;
            model.channel = input.channel;
            model.planname = input.planname;
            model.plancontent = input.plancontent;
            //model.planstate = input.planstate;
            model.startdate = input.startdate;
            model.enddate = input.enddate;
            model.createtby = usercode;
            model.goodslist = input.goodslist;
            model.deliverylist = input.deliverylist;
            model.deliveryname = input.deliveryname;
            model.deliverytel = input.deliverytel;
            #endregion
            bool b = await _distri_workorder_planrepository.Add(model);
            if (b)
            {
                #region 添加定时计划任务
                //保存计划任务 - 方法
                var planid = await addDistributionPlan(input, "");
                model.hangfireid = planid;
                await _distri_workorder_planrepository.UpdateOne(model);
                //_logger.LogError(null, "ceshi2:" + input.ToJson());
                //设置定时任务                
                var extensiontime = JsonHelper.ObjectToJson(input.extensiontime);
                SetTaskAsync(model.id, input.plancycle, input.planinterval, input.plantimes, extensiontime);
                #endregion
                //if (DateTime.Now.Date == input.startdate.Date)
                //{
                //    await AddHangfirePlanWorkorderAsync(model);
                //}
                return Success("保存成功");
            }
            else
                return Error("保存失败");
        }

        /// <summary>
        /// 修改配送计划
        /// </summary>
        [HttpPost("update")]
        public async Task<IActionResult> UpdateAsync(DistriWorkOrderPlanInput input)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            string username = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name).Value;

            if (string.IsNullOrWhiteSpace(input.projectid))
                return Error("请选择项目");
            var pro = await _pro_project_infoRepository.GetSingle(input.projectid);
            if (pro != null && pro.isend == 1)
                return Error("该项目已暂停");

            var model = await _distri_workorder_planrepository.GetSingle(p => p.id == input.id);
            if (model != null)
            {
                #region 判断验证
                if (string.IsNullOrEmpty(input.projectid))
                    return Error("请选择项目");
                if (string.IsNullOrEmpty(input.planname))
                    return Error("请选择计划名称");
                if (input.goodslist == null || input.goodslist.Count <= 0)
                    return Error("请选择物品种类");
                int goodsnum = input.goodslist.Sum(x => x.num);
                if (goodsnum <= 0)
                    return Error("请填写物品数量");
                if (input.deliverylist == null || input.deliverylist.Count <= 0)
                    return Error("请选择发货地址");
                #endregion

                #region model 添加配送计划对象
                model.projectid = input.projectid;
                model.channel = input.channel;
                model.planname = input.planname;
                model.plancontent = input.plancontent;
                model.planstate = input.planstate;
                model.startdate = input.startdate;
                model.enddate = input.enddate;
                model.createtby = usercode;
                model.goodslist = input.goodslist;
                model.deliverylist = input.deliverylist;
                model.deliveryname = input.deliveryname;
                model.deliverytel = input.deliverytel;
                #endregion

                bool b = await _distri_workorder_planrepository.UpdateOne(model);
                if (b)
                {
                    #region 添加定时计划任务
                    //保存计划任务 - 方法
                    var planid = await addDistributionPlan(input, "");
                    model.hangfireid = planid;
                    await _distri_workorder_planrepository.UpdateOne(model);
                    //设置定时任务                
                    var extensiontime = JsonHelper.ObjectToJson(input.extensiontime);
                    SetTaskAsync(model.id, input.plancycle, input.planinterval, input.plantimes, extensiontime);
                    //_logger.LogError(null, "ceshi2:" + input.ToJson());
                    #endregion
                    return Success("保存成功");
                }
                else
                    return Error("保存失败");
            }
            return Error("参数错误");
        }

        #region 不用的
        ///// <summary>
        ///// 完成计划 - 只是此计划完成，与循环无关
        ///// </summary>
        ///// <param name="id"></param>
        ///// <param name="channel"></param>
        ///// <returns></returns>
        //[HttpPost("finish")]
        //public async Task<IActionResult> UpdateFinishAsync(string id)
        //{
        //    string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
        //    if (string.IsNullOrEmpty(id))
        //        return Error("参数错误");
        //    var model = await _distri_workorder_planrepository.GetSingle(id);
        //    if (model == null)
        //        return Error("操作失败");
        //    if (model.planstate == (int)EnumDistriWorkOrderPlanstate.finish)
        //        return Error("操作失败，计划已完成");

        //    model.dealby = usercode;     //处理人
        //    model.dealtime = DateTime.Now;     //处理时间
        //    //配送计划状态:0创建计划，1已完成
        //    model.planstate = (int)EnumDistriWorkOrderPlanstate.finish;
        //    bool b = await _distri_workorder_planrepository.UpdateOne(model);
        //    if (b)
        //    {
        //        return Success("接单成功");
        //    }
        //    return Error("接单失败");
        //}
        #endregion

        /// <summary>
        /// 删除配送计划
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost("delete")]
        public async Task<IActionResult> RemoveAsync(string[] ids)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            //使用逻辑删除
            //物理删除的数据无法恢复
            var res = 0;
            if (ids == null && ids.Length <= 0)
                return Error("请选择要删除的记录");
            foreach (var item in ids)
            {
                var model_Plan = await _distri_workorder_planrepository.GetSingle(item);
                model_Plan.isdelete = 1;
                model_Plan.deleteby = usercode;
                model_Plan.deletetime = DateTime.Now;
                if (await _distri_workorder_planrepository.UpdateOne(model_Plan))
                {
                    #region 查询此计划是否有未执行的工单，若有一并删除
                    var list_Wo = await _distri_workorderrepository.Get(r => r.planid.Equals(item) && r.wostate == (int)EnumEquipmentRunningState.create);
                    if (list_Wo.Count() > 0)
                    {
                        foreach (var item_Dis in list_Wo)
                        {
                            item_Dis.isdelete = 1;
                            item_Dis.deleteby = usercode;
                            item_Dis.dealtime = DateTime.Now;
                            await _distri_workorderrepository.UpdateOne(item_Dis);
                        }
                    }
                    #endregion
                    RemoveTask(model_Plan.id);
                    res += 1;
                }
            }
            if (res == ids.Length)
                return Success("删除成功");
            else if (res > 0 && res < ids.Length)
                return Error("部分删除失败，请查看后重新操作");
            else
                return Error("删除失败，请查看后重新操作");
        }

        /// <summary>
        /// 启动计划
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost("start")]
        public async Task<IActionResult> StartAsync(string[] ids)
        {
            var res = 0;
            if (ids != null && ids.Length > 0)
            {
                try
                {
                    foreach (var item in ids)
                    {
                        var ml = await _distri_workorder_planrepository.GetSingle(item);
                        ml.planstate = 0;
                        if (await _distri_workorder_planrepository.UpdateOne(ml))
                        {
                            var hl = await _hangfireplan_distributionrepository.GetSingle(ml.hangfireid);
                            var extensiontime = JsonHelper.ObjectToJson(hl.extensiontime);
                            SetTaskAsync(item, hl.plancycle, hl.planinterval, hl.plantimes, extensiontime);
                            res += 1;
                        }
                    }
                    if (res == ids.Length)
                        return Success("操作成功");
                    else if (res > 0 && res < ids.Length)
                        return Error("部分操作失败，请查看后重新操作");
                    else
                        return Error("操作失败，请查看后重新操作");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "启动计划异常");
                    return Error("启动计划失败");
                }
            }
            else
                return Error("请选择要操作的记录");
        }

        /// <summary>
        /// 中止计划
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost("stop")]
        public async Task<IActionResult> StopAsync(string[] ids)
        {
            var res = 0;
            if (ids != null && ids.Length > 0)
            {
                try
                {
                    foreach (var item in ids)
                    {
                        var ml = await _distri_workorder_planrepository.GetSingle(item);
                        ml.planstate = 1;
                        if (await _distri_workorder_planrepository.UpdateOne(ml))
                        {
                            RemoveTask(ml.id);
                            res += 1;
                        }
                    }
                    if (res == ids.Length)
                        return Success("操作成功");
                    else if (res > 0 && res < ids.Length)
                        return Error("部分操作失败，请查看后重新操作");
                    else
                        return Error("操作失败，请查看后重新操作");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "中止计划异常");
                    return Error("中止计划失败");
                }
            }
            else
                return Error("请选择要操作的记录");
        }

        #endregion

        #region 方法 - 设置定时计划
        /// <summary>
        /// 设置定时任务
        /// </summary>
        /// <param name="id"></param>
        /// <param name="plancycle"></param>
        /// <param name="planinterval"></param>
        /// <param name="plantimes"></param>
        private void SetTaskAsync(string planid, int plancycle, int planinterval, int plantimes,string extensiontime)
        {
            _logger.LogDebug("DistriWorkOrderPlanController/SetTask start ");
            _hangfireService.AddDistriWorkOrderPlan(planid, plancycle, planinterval, plantimes, extensiontime);
        }

        /// <summary>
        /// 删除计划 - 到期删除
        /// </summary>
        /// <param name="id"></param>
        private void RemoveTask(string id)
        {
            _logger.LogDebug("DistriWorkOrderPlanController/RemoveTask remove");
            _hangfireService.RemoveDistriWorkOrderPlan(id);
        }
        #endregion

        #region 方法 - 保存计划任务定时
        /// <summary>
        /// 保存计划任务定时 - 方法
        /// </summary>
        /// <param name="input"></param>
        /// <param name="planid"></param>
        /// <returns></returns>
        private async Task<string> addDistributionPlan(DistriWorkOrderPlanInput input, string planid)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;

            var model = new HangfirePlan_Distribution();
            if (!string.IsNullOrWhiteSpace(planid))
            {
                model = await _hangfireplan_distributionrepository.GetSingle(planid);
            }
            else
            {
                model.id = ObjectId.GenerateNewId().ToString();
                model.wotype = (int)EnumDistributionWoType.distribution;

                model.createby = usercode;
                model.createtime = DateTime.Now;
                model.isdelete = 0;
                //bool b = await _hangfireplan_distributionepository.Add(model);
            }
            model.plantype = 1; //定时计划
            model.plancycle = input.plancycle;
            model.plantimes = input.plantimes;
            model.planinterval = input.planinterval;
            model.planstate = input.planstate;
            model.extensiontime = input.extensiontime;
            var b = false;
            if (string.IsNullOrWhiteSpace(planid))
                b = await _hangfireplan_distributionrepository.Add(model);
            else
                b = await _hangfireplan_distributionrepository.UpdateOne(model);

            if (b)
                return model.id;
            else
                return "";
        }

        #endregion

        #region 添加计划工单 - Hangfire循环定时 - 为Hangfire提供接口
        /// <summary>
        /// 添加计划工单 - Hangfire循环定时
        /// </summary>
        [AllowAnonymous]
        [HttpPost("addhangfire")]
        public async Task<IActionResult> AddHangfireAsync(string planid)
        {
            _logger.LogDebug("DistriWorkOrderPlanController/AddHangfireAsync  添加计划工单 start");
            if (string.IsNullOrWhiteSpace(planid))
            {
                _logger.LogError("AddHangfireAsync Error  计划不能为空");
                return Error("计划不能为空");
            }
            var b = false;
            //获取上一计划详情，作为生成模板
            var modelPlan = await _distri_workorder_planrepository.GetSingle(planid);
            if (modelPlan != null)
            {
                if (DateTime.Now.Date < modelPlan.startdate.Date)
                {
                    _logger.LogDebug("AddHangfireAsync Error 未到计划执行时间，计划名称：" + modelPlan.planname);
                    return Error("未到计划执行时间");
                }
                if (DateTime.Now.Date > modelPlan.enddate.Date)
                {
                    //删除计划 - 到期删除
                    RemoveTask(planid);
                    _logger.LogDebug("AddHangfireAsync Error 计划已结束，计划名称：" + modelPlan.planname);
                    return Error("计划已结束");
                }
                //Hangfire循环定时 - 方法
                b = await AddHangfirePlanWorkorderAsync(modelPlan);
            }
            if (b)
            {
                _logger.LogDebug("DistriWorkOrderPlanController/AddHangfireAsync  添加成功");
                return Success("添加成功");
            }
            else
            {
                _logger.LogError("DistriWorkOrderPlanController/AddHangfireAsync  添加失败");
                return Error("添加失败");
            }
        }

        /// <summary>
        /// 生成计划工单 - Hangfire循环定时 - 强制配送 - 方法
        /// </summary>
        /// <param name="planmodel"></param>
        /// <returns></returns>
        public async Task<bool> AddHangfirePlanWorkorderAsync(Distri_Workorder_Plan planmodel)
        {
            _logger.LogDebug("DistriWorkOrderPlanController/AddHangfirePlanWorkorderAsync Start  ");
            var model_Hangfire = await _hangfireplan_distributionrepository.GetSingle(planmodel.hangfireid);
            int res = 0; int count = 0;
            #region 自动分配计划工单至计划参与人 - 获取参与人（电梯岗/配送岗） - 与排班没有关系，选中计划添加参与人 - 注释目的：生成计划工单时不执行参与人，在计划执行时间段推送给参与人（接口saveautoassignhangfire中添加参与人）
            ////获取当前时间
            //DateTime nowDateTime = DateTime.Now;
            //string nowDate = nowDateTime.ToString("yyyy-MM-dd");
            ////当天 - 获取当天排班列表
            //var listClassUser = (await _sys_classgroup_user_maprepository.Get(x => x.date == nowDate && x.isdelete == 0 && x.isstatus == 1 && x.projectid == planmodel.projectid)).ToList();
            ////当天参与计划 - 排班人列表
            //var listClassUserByPlan = listClassUser.Where(x => x.distri_planList != null && x.distri_planList.Count > 0 && x.isjoin == true && x.distri_planList.Select(p => p.planid).Contains(planmodel.id));

            //List<string> listUserCode = new List<string>();
            //foreach (var item in listClassUserByPlan)
            //{
            //    listUserCode.Add(item.usercode);
            //}
            #endregion

            if (model_Hangfire != null)
            {
                #region 生成物品信息 - 主要是设置剩余数值
                List<DistributionGoodsListByTask> list_task = new List<DistributionGoodsListByTask>();
                foreach (var item_plan in planmodel.goodslist)
                {
                    var model_task = new DistributionGoodsListByTask();
                    model_task.goodsid = item_plan.goodsid;
                    model_task.goodsname = item_plan.goodsname;
                    model_task.typeid = item_plan.typeid;
                    model_task.isremind = item_plan.isremind;
                    model_task.remark = item_plan.remark;
                    model_task.num = item_plan.num;
                    model_task.usednum = 0;     //使用数量 - 主要是设置剩余数值
                    list_task.Add(model_task);
                }
                #endregion

                #region 不用
                //foreach (var item in model_Hangfire.extensiontime)
                //{
                //    //Thread.Sleep(500);
                //    var model = new Distri_Workorder_PlanTask();
                //    #region 基本信息
                //    model.channel = planmodel.channel;
                //    model.projectid = planmodel.projectid;
                //    model.planid = planmodel.id;
                //    model.wocode = UniqueData.Gener("", 2);     //计划工单编号 目前不用
                //    model.planwostate = (int)EnumDistriWorkOrderPlanWOstate.create;
                //    model.name = planmodel.planname;
                //    model.content = planmodel.plancontent;
                //    model.joinuserlist = new List<string>();  //计划工单参与人                   
                //    model.goodslist = list_task;
                //    model.deliverylist = planmodel.deliverylist;
                //    model.deliveryname = planmodel.deliveryname;
                //    model.deliverytel = planmodel.deliverytel;
                //    model.starttime = DateTime.Parse(DateTime.Now.AddDays(item.startdate - 1).ToString("yyyy-MM-dd") + " " + item.starttime.ToString("HH:mm"));
                //    model.endtime = DateTime.Parse(DateTime.Now.AddDays(item.enddate - 1).ToString("yyyy-MM-dd") + " " + item.endtime.ToString("HH:mm"));
                //    model.createtby = planmodel.createtby;
                //    model.createtime = DateTime.Now;
                //    model.isdelete = 0;
                //    #endregion
                //    //DateTime starttime = DateTime.Parse(DateTime.Now.AddDays(item.startdate - 1).ToString("yyyy-MM-dd") + " " + item.starttime.ToString("HH:mm"));
                //    //DateTime endtime = DateTime.Parse(DateTime.Now.AddDays(item.enddate - 1).ToString("yyyy-MM-dd") + " " + item.endtime.ToString("HH:mm"));
                //    //开始时间小于当前时间不创建工单
                //    //if (starttime <= DateTime.Now)    //临时注释
                //    //{ continue; }

                //    if (await _distri_workorder_plantaskrepository.Add(model))
                //    {
                //        res += 1;
                //    }
                //    count++;
                //}
                #endregion

                var timeMode = new ExtensionTimeModel();
                foreach (var item in model_Hangfire.extensiontime)
                {
                    string hourS = item.starttime.ToString("HH");
                    string hourNowS = DateTime.Now.ToString("HH");
                    if (hourNowS == hourS)
                    {
                        timeMode.startdate = item.startdate;
                        timeMode.starttime = item.starttime;
                        timeMode.enddate = item.enddate;
                        timeMode.endtime = item.endtime;
                    }
                    break;
                }

                //Thread.Sleep(500);
                var model = new Distri_Workorder_PlanTask();
                #region 基本信息
                model.channel = planmodel.channel;
                model.projectid = planmodel.projectid;
                model.planid = planmodel.id;
                model.wocode = UniqueData.Gener("", 2);     //计划工单编号 目前不用
                model.planwostate = (int)EnumDistriWorkOrderPlanWOstate.create;
                model.name = planmodel.planname;
                model.content = planmodel.plancontent;
                model.joinuserlist = new List<string>();  //计划工单参与人                   
                model.goodslist = list_task;
                model.deliverylist = planmodel.deliverylist;
                model.deliveryname = planmodel.deliveryname;
                model.deliverytel = planmodel.deliverytel;
                model.starttime = DateTime.Parse(DateTime.Now.AddDays(timeMode.startdate - 1).ToString("yyyy-MM-dd") + " " + timeMode.starttime.ToString("HH:mm"));
                model.endtime = DateTime.Parse(DateTime.Now.AddDays(timeMode.enddate - 1).ToString("yyyy-MM-dd") + " " + timeMode.endtime.ToString("HH:mm"));
                model.createtby = planmodel.createtby;
                model.createtime = DateTime.Now;
                model.isdelete = 0;
                #endregion
                DateTime starttime = DateTime.Parse(DateTime.Now.AddDays(timeMode.startdate - 1).ToString("yyyy-MM-dd") + " " + timeMode.starttime.ToString("HH:mm"));
                //DateTime endtime = DateTime.Parse(DateTime.Now.AddDays(item.enddate - 1).ToString("yyyy-MM-dd") + " " + item.endtime.ToString("HH:mm"));
                //开始时间小于当前时间不创建工单
                //if (starttime <= DateTime.Now)    //临时注释
                //{ continue; }

                if (await _distri_workorder_plantaskrepository.Add(model))
                {
                    _logger.LogError("AddHangfirePlanWorkorderAsync 定时生成计划工单成功，计划工单名称：" + planmodel.planname + "，计划工单内容：" + planmodel.plancontent);
                    return true;
                }
                else
                {
                    _logger.LogError("AddHangfirePlanWorkorderAsync 定时生成添加计划失败，计划工单名称：" + planmodel.planname + "，计划工单内容：" + planmodel.plancontent);
                    return false;
                }
            }
            else
            {
                _logger.LogError("AddHangfirePlanWorkorderAsync 定时生成添加计划失败！计划工单名称：" + planmodel.planname + "，计划工单内容：" + planmodel.plancontent);
                return false;
            }
        }

        /// <summary>
        /// 自动定时计划 - 自动分配 随机工单 计划工单
        /// </summary>
        [AllowAnonymous]
        [HttpPost("saveautoassignhangfire")]
        public async Task<IActionResult> AddAutoAssignHangfireAsync(int wotype)
        {
            _logger.LogDebug("DistriWorkOrderPlanController/AddAutoAssignHangfireAsync  ");
            if (wotype == (int)EnumDistributionWoType.autoassign)
            {
                DateTime dtnow = DateTime.Now;
                string nowDay = dtnow.ToString("yyyy-MM-dd");
                //1、配送岗 抢单时效  3分钟（某单子此时间内没人抢，系统强制分配）
                //抢单时效 - 分钟数
                int receive_Time = _distri_workorder_planrepository.GetLimitCount("ReceiveOrder_Time");
                //累积待配送量最大值
                int limit_Max = _distri_workorder_planrepository.GetLimitCount("Distribution_MaxNum");
                //待配送工单滞留时效 - 分钟数
                int stuck_Time = _distri_workorder_planrepository.GetLimitCount("StuckOrder_Time");

                DateTime dtnow_Out = dtnow.AddMinutes(-receive_Time);
                var list = (await _distri_workorderrepository.Get(x => x.wosorts == (int)EnumDistributionWoSorts.random && x.isdelete == 0)).ToList();
                //计划工单
                var list_PlanTask = await _distri_workorder_plantaskrepository.Get(x => x.isdelete == 0);

                //获取当天排班列表
                var listClassUser = (await _sys_classgroup_user_maprepository.Get(x => x.date == nowDay && x.isdelete == 0 && x.isstatus == 1)).ToList();

                //强制分配 - 添加接单人                
                //待分配工单
                var list_wo = list.Where(x => x.createtime < dtnow_Out && x.wostate == (int)EnumDistributionState.create);

                var list_num = list.Where(x => x.wostate == (int)EnumDistributionState.assign).ToList();
                //计划工单 - 开始
                var list_PlanTask_start = list_PlanTask.Where(x => x.planwostate <= (int)EnumDistriWorkOrderPlanWOstate.start && x.joinuserlist.Count>0).ToList();  //x.joinuserlist !=null && 

                //班别列表
                var listClass = (await _sys_classgrouprepository.Get(x => x.isdelete == 0)).ToList();

                #region 获取用户符合条件的用户
                //var listUser = (await _sys_user_accountrepository.Get(x => x.delete_flag == false && x.lock_flag == false)).ToList();
                List<string> listUserCode_ByPlan = new List<string>();
                List<string> listUserCode = new List<string>();
                foreach (var item in listClassUser)
                {
                    //获取条件 - 日期和班别code                           
                    var list_code = new List<string> { };   //班别code
                    var dayone = item.date;
                    var list_r = item.classgroupList.ToList();
                    foreach (var item_r in list_r)
                    {
                        if (item_r.roleList != null && item_r.roleList.Count > 0)
                        {
                            //角色 - 班别
                            var mode_r = item_r.roleList.FirstOrDefault(x => x.ischeck == true);    // && x.rolecode == rolecode  // && x.rolecode == "SSY_PSG"
                            if (mode_r != null)
                                list_code.Add(item_r.code);
                        }
                    }

                    if (list_code != null && list_code.Count > 0)
                    {
                        listClass = listClass.Where(x => list_code.Contains(x.code)).ToList();
                        var model_Class = listClass.FirstOrDefault(x => DateTime.Parse(nowDay + " " + x.starttime) <= dtnow && DateTime.Parse(nowDay + " " + x.endtime) >= dtnow);
                        if(model_Class!=null)
                        {
                            //判断人员下面是否有未完成的计划工单（如果没有，则分配随机工单）
                            var list_p = list_PlanTask_start.Where(x => x.joinuserlist.Contains(item.usercode)).ToList();
                            if (list_p.Count <= 0)
                            {
                                listUserCode_ByPlan.Add(item.usercode);
                            }
                            listUserCode.Add(item.usercode);    //随机工单
                        }
                        //foreach (var item_Class in listClass)
                        //{
                        //    //判断人员下面是否有未完成的计划工单（如果没有，则分配随机工单）
                        //    var list_p = list_PlanTask_start.Where(x => x.joinuserlist.Contains(item.usercode)).ToList();
                        //    if (list_p.Count <= 0)
                        //    {
                        //        listUserCode_ByPlan.Add(item.usercode);
                        //    }
                        //    listUserCode.Add(item.usercode);    //随机工单
                        //}                        

                    }
                }
                #endregion

                #region 1、待强制分配工单
                //缓存里临时 配送列表
                var list_num_assign = list_num;
                var listwo = list_wo;
                foreach (var item in listwo)
                {
                    //Thread.Sleep(500);
                    #region 获取待配送工单量最少用户
                    //var listUser = new List<string>();
                    int n = limit_Max;  //临时参数
                    var usercodeMin = "";

                    // 用户 和 工单数 list
                    var list_usernum = new List<UserAndNumList>();
                    foreach (var itemUser in listUserCode)
                    {
                        var model_usernum = new UserAndNumList();
                        int num = list_num_assign.Count(x => x.touser.Contains(itemUser));

                        model_usernum.num = num;
                        model_usernum.usercode = itemUser;
                        list_usernum.Add(model_usernum);
                        //if (n > num)
                        //{
                        //    n = num;    //最小值赋值
                        //    usercodeMin = itemUser;
                        //}
                    }
                    //获取单数最少的用户
                    var model_minusernum = list_usernum.OrderBy(x => x.num).FirstOrDefault();
                    if (model_minusernum != null)
                    {
                        n = model_minusernum.num;
                        usercodeMin = model_minusernum.usercode;
                    }
                    #endregion
                    var userinfo = (await _distri_sys_user_accountrepository.GetSingle(x => x.usercode == usercodeMin)); //x.delete_flag == false &&
                    if (n < limit_Max)
                    {
                        //2019-01-04 修改bug 多次配送同一个人
                        if (item.wostate == (int)EnumDistributionState.create && item.touser.Count <= 0)
                        {
                            #region 强制分配
                            item.touser = new List<string>() { usercodeMin };     //配送岗 - 转派人/抢单人
                            item.totype = (int)EnumDistributionTotype.assign;
                            //配送工单状态:0创建工单，1转派或者抢单（待取货）,2已取货（配送中）,3货物异常（异常），4已完结/待评价，5已取消，6挂起 ，9已评价 
                            item.wostate = (int)EnumDistributionState.assign;
                            item.assigtime = DateTime.Now;
                            bool b = await _distri_workorderrepository.UpdateOne(item);
                            #region 微信模板消息
                            if (item.channel == 4)
                            {
                                var model_Receiver = item.receiverlist.FirstOrDefault();
                                string content = "抢单人：" + usercodeMin + "-" + usercodeMin
                                    + "\n联系电话：" + (userinfo != null ? userinfo.mobile : "")
                                    + "\n收货地址：" + (model_Receiver != null ? model_Receiver.building_name : "") + (model_Receiver != null ? model_Receiver.floor_name : "") + " 科室：" + (model_Receiver != null ? model_Receiver.department_name : "")
                                    + "\n抢单时间：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                _logger.LogError("neirong: " + content);
                                SendWechatMsg(item.wocode, "配送员抢单成功！", "配送员已抢单成功，等待配送员取货", content, "", item.id, item.createtby);   //默认是查看工单详情 PSDD
                            }

                            //int islast = item.wostate == (int)EnumDistributionState.finish ? 1 : 0;    //是否最后一步 0否 1是
                            //AddItems(item.id, item.wocode, item.wostate, item.wostate_elevator, channel, islast, usercode, "", "配送岗" + username + "抢单：", usercode);
                            #endregion
                            _logger.LogDebug("DistriWorkOrderPlanController/AddAutoAssignHangfireAsync  自动定时计划 强制分配,分配人：" + item.touser.ToJson() + "工单：" + item.wocode);
                            #endregion
                            //添加对应待配送（已分配）
                            list_num_assign.Add(item);
                        }
                    }
                }
                #endregion

                #region 2、自动分配计划工单至计划参与人 - 获取参与人（电梯岗/配送岗） - 与排班没有关系，选中计划添加参与人
                //计划工单 - 新建
                var list_PlanTask_create = list_PlanTask.Where(x => x.planwostate == (int)EnumDistriWorkOrderPlanWOstate.create && x.joinuserlist.Count == 0 && x.joinuserlist.Count <= 0).ToList();    // && x.starttime <= dtnow && x.endtime >= dtnow
                foreach (var item_plan in list_PlanTask_create)
                {
                    List<string> listUserCode_Plan = new List<string>();
                    //当天 - 获取当天排班列表
                    listClassUser = listClassUser.Where(x => x.projectid == item_plan.projectid).ToList();

                    #region 1、提前计划排班 - PC端管理员，主管等昨天的提前计划排班
                    //当天参与计划 - 排班人列表
                    var listClassUserByPlan = listClassUser.Where(x => x.distri_planList != null && x.distri_planList.Count > 0 && x.isjoin == true && x.distri_planList.Select(p => p.planid).Contains(item_plan.planid));
                    foreach (var item in listClassUserByPlan)
                    {
                        listUserCode_Plan.Add(item.usercode);
                    }
                    item_plan.joinuserlist = listUserCode_Plan.Distinct().ToList();  //计划工单参与人
                    await _distri_workorder_plantaskrepository.UpdateOne(item_plan);
                    #endregion

                    #region 2、无人接的计划工单 - A、无提前计划排班；B、无人抢单，需要自动分配

                    #region 获取待配送工单量最少用户
                    int n = limit_Max;  //临时参数
                    var usercodeMin = "";

                    // 用户 和 工单数 list
                    var list_usernum = new List<UserAndNumList>();
                    foreach (var itemUser in listUserCode_ByPlan)
                    {
                        var model_usernum = new UserAndNumList();
                        int num = list_PlanTask_start.Count(x => x.joinuserlist.Contains(itemUser));

                        model_usernum.num = num;
                        model_usernum.usercode = itemUser;
                        list_usernum.Add(model_usernum);
                    }
                    //获取单数最少的用户
                    var model_minusernum = list_usernum.OrderBy(x => x.num).FirstOrDefault();
                    if (model_minusernum != null)
                    {
                        n = model_minusernum.num;
                        usercodeMin = model_minusernum.usercode;
                    }
                    #endregion
                    if (n < limit_Max)
                    {
                        item_plan.joinuserlist = new List<string>() { usercodeMin };  //计划工单参与人
                        await _distri_workorder_plantaskrepository.UpdateOne(item_plan);
                    }
                    #endregion

                    _logger.LogDebug("DistriWorkOrderPlanController/AddAutoAssignHangfireAsync  自动定时计划工单 强制分配参与人,参与人：" + item_plan.joinuserlist.ToJson() + "计划工单：" + item_plan.wocode);
                }
                #endregion

                //配送岗 待配送工单滞留时效 30分钟（超时就记一次超时违规记录，可以有违规申诉）
                #region 3、违规修改
                DateTime dtnow_Wait = dtnow.AddMinutes(-stuck_Time);
                var list_Wait = list.Where(x => x.assigtime < dtnow_Wait && x.isoffence == 0 && x.wostate == (int)EnumDistributionState.assign); //1、从指派/抢单时间算 2、待配送  x.wostate_elevator == (int)EnumDistributionState_elevator.delivery &&
                foreach (var item in list_Wait)
                {
                    item.isoffence = 1; //违规记录 - 待配送工单滞留时效
                    await _distri_workorderrepository.UpdateOne(item);
                    _logger.LogDebug("DistriWorkOrderPlanController/AddAutoAssignHangfireAsync  自动定时计划 违规处理,工单：" + item.wocode);
                }
                #endregion
                //_logger.LogDebug("DistriWorkOrderPlanController/AddAutoAssignHangfireAsync  自动定时计划创建成功");
                return Success("自动定时计划创建成功");
            }
            else
            {
                _logger.LogError("DistriWorkOrderPlanController/AddAutoAssignHangfireAsync  自动定时计划创建失败");
                return Error("自动定时计划创建失败");
            }
        }

        /// <summary>
        /// 用户 和 工单数 list
        /// </summary>
        public class UserAndNumList
        {
            /// <summary>
            /// 数量
            /// </summary>
            public int num { get; set; }
            /// <summary>
            /// 用户账号
            /// </summary>
            public string usercode { get; set; }
        }
        #endregion

        #region 设置定时计划
        #endregion

        #region 计划工单
        /// <summary>
        /// 获取计划工单列表分页 by page
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="stime"></param>
        /// <param name="etime"></param>
        /// <param name="pageindex"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        [HttpGet("getplantasklistbypage")]
        public IActionResult GetPlanTaskListByPageAsync(string keyword, string projectid, string stime, string etime, int datetype = -1, int planwostate = -1, int pageindex = 1, int pagesize = 10)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            //var userstr = _signTokenService.GetUserInfoAsync(usercode).Result;
            //var userinfo = userstr.ToJObject()["data"].ToString().ToObject<UserInfoModel>();
            
            var userinfos = _sys_user_accountRepository.GetUserInfo(usercode);
            var userinfo = JsonHelper.JsonToEntity<UserAccountInfoModel>(userinfos.ToJson());

            //获取当天、本周、本月、本年、累计时间
            if (datetype != -1)
            {
                GetStartEndTime(datetype, out stime, out etime);
            }
            //获取数据
            int recordCount = 0;
            var result = _distri_workorder_planrepository.GetPlanTaskListsByPage(keyword, projectid, stime, etime, planwostate, userinfo, pageindex, pagesize, out recordCount);
            var obj = new
            {
                rows = result.ToList(),
                total = recordCount
            };
            return Success("获取成功", obj);
        }

        /// <summary>
        /// 获取计划工单详情
        /// </summary>
        [HttpGet("getplanworkordersingle")]
        public async Task<IActionResult> GetPlanTaskSingleAsync(string id,string projectid, int channelcode = 0)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            if (string.IsNullOrEmpty(id))
                return Error("参数错误");
            var model = _distri_workorder_planrepository.GetPlanTaskDetails(id);
            if (model != null)
            {

                var userlist = (await _distri_sys_user_accountrepository.Get(x => x.delete_flag == false && x.type != 2)).ToList();
                //定时计划表
                var hangfireplan_List = (await _hangfireplan_distributionrepository.Get(x => x.plantype == (int)EnumDistributionPlanType.timing && x.isdelete == 0)).ToList();
                //计划表
                var plan_List = (await _distri_workorder_planrepository.Get(x => x.isdelete == 0 )).ToList();
                //分送工单表
                var wo_List = (await _distri_workorderrepository.Get(x => x.wosorts == (int)EnumDistributionWoSorts.plan && x.isdelete == 0 && x.plantaskid == model.id && (x.wostate == (int)EnumDistributionState.finish || x.wostate == (int)EnumDistributionState.evaluated))).ToList();

                #region 标记消息提醒工单（消息提醒，App推送）
                string goodsDetail = "";
                if (channelcode > 0)
                {
                    if (model.planwostate == (int)EnumDistriWorkOrderPlanWOstate.start)
                    {
                        //维修工单号
                        var listmap = await _wo_order_user_maprepository.Get(x => x.woid == model.id && x.wocode == model.wocode && x.channelcode == channelcode && x.readby == usercode);
                        var modelmap = listmap.FirstOrDefault();
                        goodsDetail = (model.goodslist != null && model.goodslist.Count > 0) ? " 配送计划工单物品:" + model.goodslist.Select(x => x.goodsname).ToJson() : "";
                        if (modelmap == null)
                        {
                            //添加是否已读关系表
                            modelmap = new Wo_Order_User_Map();
                            modelmap.woid = model.id;
                            modelmap.wocode = model.wocode;
                            modelmap.wostate = model.planwostate;
                            modelmap.readby = usercode;
                            modelmap.channelcode = channelcode;   //工单类型（枚举EnumOrderState） 维修工单 = 1, 保养工单 = 2, 运行工单 = 3, 超时工单 = 4, 配送工单 = 5, 计划工单 = 5
                            modelmap.isread = 1;
                            modelmap.isnotice = 1;
                            modelmap.readtime = DateTime.Now;
                            modelmap.note = (string.IsNullOrEmpty(model.content) ? "" : "计划工单内容:" + model.content) + goodsDetail; //保养内容
                                                                                                                                                 // modelmap.note = model.maintaincontent;
                            bool b = await _wo_order_user_maprepository.Add(modelmap);
                        }
                        else
                        {
                            modelmap.isread = 1;
                            modelmap.isnotice = 1;
                            modelmap.note = (string.IsNullOrEmpty(model.content) ? "" : "计划工单内容:" + model.content) + goodsDetail; //保养内容
                            bool b = await _wo_order_user_maprepository.UpdateOne(modelmap);
                        }
                    }
                }
                #endregion

                if (!string.IsNullOrEmpty(projectid))
                    userlist = userlist.Where(x => x.projectlist.Contains(projectid)).ToList();
                if (model.joinuserlist != null && model.joinuserlist.Count > 0)
                {
                    model.joinusertel = userlist.Where(y => model.joinuserlist.Contains(y.usercode)).Select(x => x.mobile).ToList();
                }
                if (!string.IsNullOrEmpty(model.planid) && hangfireplan_List != null && hangfireplan_List.Count > 0)
                {
                    if (plan_List != null && plan_List.Count > 0)
                    {
                        var model_Plan = plan_List.FirstOrDefault(x => x.id == model.planid);
                        if (model_Plan != null)
                        {
                            model.plantimes = hangfireplan_List.FirstOrDefault(x => x.id == model_Plan.hangfireid).plantimes;
                        }
                    }
                }
                var newlist = wo_List.Select(x => new
                {
                    id = x.id,
                    wocode = x.wocode,
                    receiverlist = x.receiverlist
                });
                var obj = new
                {
                    model = model,
                    items = wo_List
                };
                return Success("获取计划工单成功", obj);
            }
            return Error("获取失败");
        }

        /// <summary>
        /// 修改计划工单（修改且开始）
        /// </summary>
        [HttpPost("updateplantask")]
        public async Task<IActionResult> UpdatePlanTaskAsync(string taskid, List<DistributionGoodsListByTask> goodslist)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            string username = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name).Value;

            #region 判断验证
            if (string.IsNullOrEmpty(taskid))
                return Error("参数错误");
            if (goodslist == null || goodslist.Count <= 0)
                return Error("请选择物品种类");
            int goodsnum = goodslist.Sum(x => x.num);
            if (goodsnum <= 0)
                return Error("请填写物品数量");
            var model = await _distri_workorder_plantaskrepository.GetSingle(p => p.id == taskid);
            if (model == null)
                return Error("操作失败");
            if (model.joinuserlist == null || model.joinuserlist.Count <= 0)
                return Error("操作失败，参与人为空");
            if (model.planwostate >= (int)EnumDistriWorkOrderPlanWOstate.start)
                return Error("操作失败，计划工单已完成或已开始");
            var pro = await _pro_project_infoRepository.GetSingle(model.projectid);
            if (pro != null && pro.isend == 1)
                return Error("该项目已暂停");
            #endregion

            //计划工单状态:0创建计划工单，1开始，2已完成
            model.planwostate = (int)EnumDistriWorkOrderPlanWOstate.start;
            model.goodslist = goodslist;
            model.statetime = DateTime.Now; //开始时间

            bool b = await _distri_workorder_plantaskrepository.UpdateOne(model);
            if (b)
            {
                return Success("操作成功");
            }
            return Error("操作失败");
        }

        /// <summary>
        /// 抢单 - 计划工单
        /// </summary>
        /// <param name="id"></param>
        /// <param name="channel"></param>
        /// <returns></returns>
        [HttpPost("receiveplantask")]
        public async Task<IActionResult> UpdateReceiveTaskAsync(string id)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;

            #region 验证判断
            if (string.IsNullOrEmpty(id))
                return Error("参数错误");
            var model = await _distri_workorder_plantaskrepository.GetSingle(id);
            if (model == null)
                return Error("操作失败");
            if (model.planwostate >= (int)EnumDistriWorkOrderPlanWOstate.start)
                return Error("操作失败，计划工单已开始或已完成");
            if (model.joinuserlist != null && model.joinuserlist.Count > 0)
                return Error("操作失败，计划工单已有参与人或已抢单");
            //判断此用户下是否有计划任务，如果有不让抢单，没有让抢单
            var listWorkorder = (await _distri_workorder_plantaskrepository.Get(x => x.isdelete == 0 && x.joinuserlist.Contains(usercode) && x.planwostate < (int)EnumDistriWorkOrderPlanWOstate.finish)).ToList();
            if (listWorkorder != null && listWorkorder.Count > 0)
                return Error("您有" + listWorkorder.Count + "计划工单没有完成，不能进行抢单操作");
            #endregion

            model.joinuserlist = new List<string>() { usercode };     //参与人
            //计划工单状态:0创建计划工单，1开始，2已完成
            bool b = await _distri_workorder_plantaskrepository.UpdateOne(model);
            if (b)
                return Success("操作成功");
            return Error("操作失败");
        }

        /// <summary>
        /// 添加配合人 - 计划工单
        /// </summary>
        /// <param name="id"></param>
        /// <param name="channel"></param>
        /// <returns></returns>
        [HttpPost("addreceiveplantask")]
        public async Task<IActionResult> AddReceiveTaskAsync(string id,string user)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;

            #region 验证判断
            if (string.IsNullOrEmpty(id))
                return Error("参数错误");
            var model = await _distri_workorder_plantaskrepository.GetSingle(id);
            if (model == null)
                return Error("操作失败");
            if (model.planwostate >= (int)EnumDistriWorkOrderPlanWOstate.start)
                return Error("操作失败，计划工单已开始或已完成");
            if(string.IsNullOrEmpty(user))
                return Error("操作失败，添加配合人不能为空");
            if (model.joinuserlist.Contains(user))
                return Error("操作失败，" + user + "已存在，请不要重复添加");

            ////判断此用户下是否有计划任务，如果有不让抢单，没有让抢单
            //var listWorkorder = (await _distri_workorder_plantaskrepository.Get(x => x.isdelete == 0 && x.joinuserlist.Contains(user) && x.planwostate < (int)EnumDistriWorkOrderPlanWOstate.finish)).ToList();
            //if (listWorkorder != null && listWorkorder.Count > 0)
            //    return Error("您有计划工单没有完成，不能进行抢单操作");
            #endregion
            model.joinuserlist.Add(user);    //参与人
            //计划工单状态:0创建计划工单，1开始，2已完成
            bool b = await _distri_workorder_plantaskrepository.UpdateOne(model);
            if (b)
                return Success("操作成功");
            return Error("操作失败");
        }

        /// <summary>
        /// 删除计划工单
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost("deleteplantask")]
        public async Task<IActionResult> RemovePlanTaskAsync(string[] ids)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            //使用逻辑删除
            var res = 0;
            if (ids == null && ids.Length <= 0)
                return Error("请选择要删除的记录");
            foreach (var item in ids)
            {
                var model = await _distri_workorder_plantaskrepository.GetSingle(item);
                model.isdelete = 1;
                model.deleteby = usercode;
                model.deletetime = DateTime.Now;
                if (await _distri_workorder_plantaskrepository.UpdateOne(model))
                {
                    #region 查询此计划是否有未执行的工单，若有一并删除
                    var list_Wo = await _distri_workorderrepository.Get(r => r.plantaskid.Equals(item) && r.wostate == (int)EnumEquipmentRunningState.create);
                    if (list_Wo.Count() > 0)
                    {
                        foreach (var item_Dis in list_Wo)
                        {
                            item_Dis.isdelete = 1;
                            item_Dis.deleteby = usercode;
                            item_Dis.dealtime = DateTime.Now;
                            await _distri_workorderrepository.UpdateOne(item_Dis);
                        }
                    }
                    #endregion
                    res += 1;
                }
            }
            if (res == ids.Length)
                return Success("删除成功");
            else if (res > 0 && res < ids.Length)
                return Error("部分删除失败，请查看后重新操作");
            else
                return Error("删除失败，请查看后重新操作");
        }

        /// <summary>
        /// 开始 - 计划工单
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        [HttpPost("startplantask")]
        public async Task<IActionResult> StartAsync(string id)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;
            if (string.IsNullOrEmpty(id))
                return Error("参数错误");
            var model = await _distri_workorder_plantaskrepository.GetSingle(id);
            if (model == null)
                return Error("操作失败");
            if (model.joinuserlist!=null && model.joinuserlist.Count>0)
                return Error("操作失败，参与人为空");
            if (model.planwostate >= (int)EnumDistriWorkOrderPlanWOstate.start)
                return Error("操作失败，计划工单已完成或已开始");

            //计划工单状态:0创建计划工单，1开始，2已完成
            model.planwostate = (int)EnumDistriWorkOrderPlanWOstate.start;
            model.statetime = DateTime.Now; //开始时间
            bool b = await _distri_workorder_plantaskrepository.UpdateOne(model);
            if (b)
            {
                return Success("操作成功");
            }
            return Error("操作失败");
        }

        /// <summary>
        /// 完成 - 计划工单
        /// </summary>
        /// <param name="id"></param>
        /// <param name="channel"></param>
        /// <returns></returns>
        [HttpPost("finishplantask")]
        public async Task<IActionResult> UpdateFinishTaskAsync(string id)
        {
            string usercode = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Sid).Value;

            #region 验证判断
            if (string.IsNullOrEmpty(id))
                return Error("参数错误");
            var model = await _distri_workorder_plantaskrepository.GetSingle(id);
            if (model == null)
                return Error("操作失败");
            if (model.planwostate == (int)EnumDistriWorkOrderPlanWOstate.finish)
                return Error("操作失败，计划工单已完成");
            ////判断此用户下是否有计划任务，如果有不让抢单，没有让抢单
            //var listWorkorder = (await _distri_workorder_plantaskrepository.Get(x => x.isdelete == 0 && x.planwostate < (int)EnumDistriWorkOrderPlanWOstate.finish)).ToList();
            //if (listWorkorder != null && listWorkorder.Count > 0)
            //    return Error("您有计划工单没有完成，不能操作完成");
            #endregion

            foreach (var item in model.goodslist)
            {
                if (item.usednum < item.num)
                    return Error("操作错误，已配送物品" + item.goodsname + "数量：" + item.usednum + "小于计划工单物品" + item.goodsname + "数量：" + item.num + "，没有分送完物品，不能操作完成");               
            }

            model.dealby = usercode;     //处理人
            model.dealtime = DateTime.Now;     //处理时间
            //计划工单状态:0创建计划工单，1开始，2已完成
            model.planwostate = (int)EnumDistriWorkOrderPlanWOstate.finish;
            bool b = await _distri_workorder_plantaskrepository.UpdateOne(model);
            if (b)
            {
                return Success("操作成功");
            }
            return Error("操作失败");
        }
        #endregion

        /// <summary>
        /// 获取当天、本周、本月、本年、累计时间
        /// </summary>
        /// <param name="datetype"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        public void GetStartEndTime(int datetype, out string start, out string end)
        {
            start = string.Empty;
            end = string.Empty;

            var datenow = DateTime.Now;
            var datestart = datenow;
            var dateend = datenow;
            switch (datetype)
            {
                case 0://当天
                    break;
                case 1://本周
                    int n = (int)datenow.DayOfWeek == 0 ? 7 : (int)datenow.DayOfWeek;
                    datestart = datenow.AddDays(1 - n);//本周周一
                    dateend = datestart.AddDays(6);//本周周日
                    break;
                case 2://本月

                    datestart = datenow.AddDays(1 - datenow.Day);  //本月月初  
                    dateend = datestart.AddMonths(1).AddDays(-1);  //本月月末  
                    break;
                case 3://本年
                    datestart = new DateTime(datenow.Year, 1, 1);  //本年年初  
                    dateend = new DateTime(datenow.Year, 12, 31);  //本年年末  
                    break;
                case 4://全部
                    break;
                default:
                    break;
            }
            if (datetype != 4)
            {
                start = datestart.ToString("yyyy-MM-dd");
                end = dateend.ToString("yyyy-MM-dd");
            }
        }

        #region 微信方法
        /// <summary>
        /// 发送微信模板消息
        /// </summary>
        /// <param name="wocode">工单编号</param>
        /// <param name="title">标题</param>
        /// <param name="content">内容</param>
        /// <param name="url">链接地址</param>
        /// <param name="openid">接收方</param>
        /// <param name="templateid">模板id</param>
        private async void SendWechatMsg(string wocode, string title, string statename, string content, string menucode, string url, string openid, string templateid = "csH1KSQMz8nMnZhlcH7gpOo1aAIZZLiXecYlhGFzvuE")
        {
            if (string.IsNullOrEmpty(menucode))
                menucode = "PSDD";
            url = "menucode=" + menucode + "&id=" + url;
            var obj = new
            {
                first = new { value = title, color = "#173177" },
                keyword1 = new { value = statename },
                keyword2 = new { value = wocode },
                remark = new { value = content }
            };
            await _wechatservice.SendTemplateMsg(openid, url, obj.ToJson(), templateid);
        }

        ///// <summary>
        ///// 发送微信消息
        ///// </summary>
        ///// <param name="wocode">工单编号</param>
        ///// <param name="title">标题</param>
        ///// <param name="content">内容</param>
        ///// <param name="url">链接地址</param>
        ///// <param name="openid">接收方</param>
        //private async void SendWechatMessage(string wocode, string title, string content, string url, string openid)
        //{
        //    url = "menucode=CKXQ&id=" + url;
        //    content = content + "\n时间：" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        //    await _wechatservice.SendNewsMsg(openid, title, content, url);
        //}

        #endregion
    }
}