using Infrastructure;
using Infrastructure.Extensions;
using Newtonsoft.Json;
using OpenAuth.App.Config;
using OpenAuth.Repository.Domain;
using SqlSugar;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OpenAuth.App
{
    public class WFEngine : IWFEngine
    {
        ISqlSugarClient client;
        //private RepositoryFactory dbFactory { get; set; }
        /// <summary>
        /// 流程配置信息
        /// </summary>
        private WFEngineConfig _config { get; set; }
        /// <summary>
        /// 流程模板
        /// </summary>
        private WorkFlow.WFScheme _wfScheme { get; set; }
        /// <summary>
        /// 流程单元对应字典
        /// </summary>
        private Dictionary<string, WFUnit> _dicUnit { get; set; }
        /// <summary>
        /// 开始节点
        /// </summary>
        private WFUnit _startNode { get; set; }
        /// <summary>
        /// 线条集合
        /// </summary>
        private List<WFUnit> _lines { get; set; }
        #region 构造函数
        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="config">流程参数</param>
        public WFEngine(WFEngineConfig config, ISqlSugarClient sqlSugarClient)
        {
            // 初始化模板数据
            _config = config;
            _wfScheme = ToObject<WorkFlow.WFScheme>(_config.Params.Scheme);
            //_wfScheme = Newtonsoft.Json.JsonConvert.DeserializeObject<WorkFlow.WFScheme>(_config.Params.Scheme);
            //_wfScheme = ExtensionsJson.ToObject<WorkFlow.WFScheme>(_config.Params.Scheme);

            _dicUnit = new Dictionary<string, WFUnit>();
            _lines = new List<WFUnit>();

            foreach (var unit in _wfScheme.WfData)
            {
                if (!_dicUnit.ContainsKey(unit.Id))
                {
                    _dicUnit.Add(unit.Id, unit);
                }
                else
                {
                    continue;
                }

                if (unit.Type == NodeTypeEnum.startEvent.GetDescription())
                {
                    _startNode = unit;
                }
                else if (unit.Type == NodeTypeEnum.myline.GetDescription())
                {
                    _lines.Add(unit);
                }
            }
            client = sqlSugarClient;
            //dbFactory = new RepositoryFactory();
        }
        #endregion

        public T ToObject<T>(string Json)
        {
            return (T)((Json == null) ? ((object)default(T)) : ((object)JsonConvert.DeserializeObject<T>(Json)));
        }
        /// <summary>
        /// 流程运行参数
        /// </summary>
        public WFEngineConfig Config => _config;
        /// <summary>
        /// 开始节点
        /// </summary>
        public WFUnit StartNode => _startNode;

        /// <summary>
        /// 流程发起用户
        /// </summary>
        public WFUserInfo CreateUser => _config.Params.CreateUser;
        /// <summary>
        /// 流程发起用户
        /// </summary>
        public WFUserInfo CurrentUser => _config.Params.CurrentUser;

        /// <summary>
        /// 流程配置信息
        /// </summary>
        public WorkFlow.WFScheme WFScheme => _wfScheme;

        /// <summary>
        /// 获取流程单元信息
        /// </summary>
        /// <param name="id">id</param>
        /// <returns>流程单元信息</returns>
        public WFUnit GetNode(string id)
        {
            if (_dicUnit.ContainsKey(id))
            {
                return _dicUnit[id];
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 获取下一节点集合
        /// </summary>
        /// <param name="startId">开始节点</param>
        /// <param name="code">执行动作编码</param>
        /// <returns></returns>
        public List<WFUnit> GetNextUnits(string startId, string code = "")
        {
            List<WFUnit> nextUnits = new List<WFUnit>();

            // 找到与当前节点相连的线条
            foreach (var line in _lines)
            {
                if (line.From == startId)
                {
                    // 获取连接到开始节点的线条
                    bool isOk = false;
                    if (string.IsNullOrEmpty(line.LineConditions))
                    {
                        isOk = true;
                    }
                    else if (!string.IsNullOrEmpty(code))
                    {
                        var codeList = line.LineConditions.Split(',');
                        foreach (string _code in codeList)
                        {
                            if (_code == code)
                            {
                                isOk = true;
                                break;
                            }
                        }
                    }
                    else
                    { //没有执行码就是全部执行
                        isOk = true;
                    }


                    // 获取到流入节点
                    if (isOk)
                    {
                        if (_dicUnit.ContainsKey(line.To) && nextUnits.Find(t => t.Id == line.To) == null)
                        {
                            nextUnits.Add(_dicUnit[line.To]);
                        }
                    }
                }
            }
            return nextUnits;
        }
        /// <summary>
        /// 获取下一节点集合
        /// </summary>
        /// <param name="startId">开始节点</param>
        /// <param name="codeList">条件编码</param>
        /// <returns></returns>
        public List<WFUnit> GetNextUnits(string startId, List<string> codeList)
        {
            List<WFUnit> nextUnits = new List<WFUnit>();

            // 找到与当前节点相连的线条
            foreach (var line in _lines)
            {
                if (line.From == startId)
                {
                    // 获取连接到开始节点的线条
                    bool isOk = false;
                    if (codeList.Count > 0 && !string.IsNullOrEmpty(line.LineConditions))
                    {
                        var codeList2 = line.LineConditions.Split(',');
                        foreach (string _code in codeList2)
                        {
                            if (codeList.FindIndex(t => t == _code) != -1)
                            {
                                isOk = true;
                                break;
                            }
                        }
                    }

                    // 获取到流入节点
                    if (isOk)
                    {
                        if (_dicUnit.ContainsKey(line.To) && nextUnits.Find(t => t.Id == line.To) == null)
                        {
                            nextUnits.Add(_dicUnit[line.To]);
                        }
                    }
                }
            }
            return nextUnits;
        }

        /// <summary>
        /// 获取下一节点集合（流转条件为空的情况）
        /// </summary>
        /// <param name="startId">开始节点</param>
        /// <returns></returns>
        public List<WFUnit> GetNextUnitsNoSet(string startId)
        {
            List<WFUnit> nextUnits = new List<WFUnit>();

            // 找到与当前节点相连的线条
            foreach (var line in _lines)
            {
                if (line.From == startId)
                {
                    // 获取到流入节点
                    if (string.IsNullOrEmpty(line.LineConditions))
                    {
                        if (_dicUnit.ContainsKey(line.To) && nextUnits.Find(t => t.Id == line.To) == null)
                        {
                            nextUnits.Add(_dicUnit[line.To]);
                        }
                    }
                }
            }
            return nextUnits;
        }
        /// <summary>
        /// 获取上一单元ID列表
        /// </summary>
        /// <param name="myUnitId">当前节点Id</param>
        /// <returns></returns>
        public List<string> GetPreUnitIds(string myUnitId)
        {
            List<string> list = new List<string>();
            // 找到与当前节点相连的线条
            foreach (var line in _lines)
            {
                if (line.To == myUnitId && list.Find(t => t == line.From) == null)
                {
                    list.Add(line.From);
                }
            }
            return list;
        }
        /// <summary>
        /// 获取任务
        /// </summary>
        /// <param name="startId">开始节点</param>
        /// <param name="code">执行动作编码</param>
        /// <param name="toUnitId">下一个指定节点</param>
        /// <returns></returns>
        public async Task<List<WorkFlow.WFTask>> GetTask(string startId, string code = "", string toUnitId = "")
        {
            bool isIsReject = code == "disagree";
            var nextUnits = GetNextUnits(startId, code);

            if (!string.IsNullOrEmpty(toUnitId))
            {
                nextUnits = nextUnits.FindAll(t => t.Type == "bpmn:ScriptTask");// 只保留脚本节点
                nextUnits.Add(GetNode(toUnitId));
            }

            // 如果无法获取下一个审核任务且是驳回操作,就返回到之前流转过来的任务(除去通过驳回流转过来的)（需要过滤掉脚本节点）
            if (nextUnits.FindAll(t => t.Type != "bpmn:ScriptTask").Count == 0 && isIsReject)
            {
                // 获取当前节点的
                var prevUnitId = await Config.GetPrevUnitId(Config.Params.ProcessId, startId);
                if (!string.IsNullOrEmpty(prevUnitId))
                {
                    nextUnits.Add(GetNode(prevUnitId));
                }
            }

            var list = await GetTask(nextUnits, isIsReject, startId);
            foreach (var item in list)
            {
                item.PrevUnitId = startId;
            }
            return list;
        }



        /// <summary>
        /// 获取任务
        /// </summary>
        /// <param name="nextUnits">下一个节点集合</param>
        /// <param name="isReject">是否驳回</param>
        /// <param name="startId">开始节点</param>
        /// <returns></returns>
        public async Task<List<WorkFlow.WFTask>> GetTask(List<WFUnit> nextUnits, bool isReject, string startId)
        {
            WFUnit startUnit = _dicUnit[startId];

            if (startUnit.Type == NodeTypeEnum.startEvent.GetDescription() && string.IsNullOrEmpty(startUnit.Name))
            {
                startUnit.Name = "开始节点";
            }

            List<WorkFlow.WFTask> taskList = new List<WorkFlow.WFTask>();
            foreach (var unit in nextUnits)
            {
                switch (unit.Type)
                {
                    //case "startEvent":// 开始节点
                    case "bpmn:StartEvent":// 开始节点
                        taskList.Add(GetStartTask(unit, isReject, startId, startUnit.Name));
                        break;
                    //case "gatewayAnd":
                    case "bpmn:ParallelGateway":
                        // 并行网关会等待所有分支汇入才往下执行，所有出口分支都会被执行
                        // 判断是否所有分支都被执行了
                        // 1.或去此节点所有上节点
                        // 2.生成一个等待任务
                        // 3.获取所有该节点当前等待任务
                        // 4.判断是否完成获取下一节点
                        var preIdList = GetPreUnitIds(unit.Id);
                        if (preIdList.Count <= 1)
                        {
                            taskList.AddRange(await GetTask(unit.Id));
                        }
                        else
                        {
                            var awaitTaskList = await Config.GetAwaitTaskList(Config.Params.ProcessId, unit.Id);
                            var awaitTaskList2 = awaitTaskList.FindAll(t => t.PrevUnitId != startId); // 排除当前等待任务的所有等待任务
                            if (awaitTaskList2.Count + 1 >= preIdList.Count)
                            {
                                // 如果所有支路都被执行了就生成一个取消所有等待任务的命令
                                taskList.Add(GetDeleteAwaitTask(unit, isReject, startId, startUnit.Name));
                                taskList.AddRange(await GetTask(unit.Id));
                            }
                            else
                            {
                                taskList.Add(GetAwaitTask(unit, isReject, startId, startUnit.Name));
                            }
                        }
                        break;
                    //case "gatewayXor":
                    case "bpmn:ExclusiveGateway":
                        //  排他网关不会等待所有分支汇入才往下执行，只要有分支汇入就会往下执行，出口分支只会执行一条（条件为true，如果多条出口分支条件为true也执行一条）
                        // 1.获取当前节点的true条件，如果成立条件为0，就执行人默认没有条件的线条
                        // 2.获取下一个节点
                        var conditionCodes = await GetConditionIds(unit.Conditions);
                        var nextUnits2 = GetNextUnits(unit.Id, conditionCodes);
                        if (nextUnits2.Count == 0)
                        {
                            nextUnits2 = GetNextUnitsNoSet(unit.Id);
                        }
                        if (nextUnits2.Count == 0)
                        {
                            throw new Exception(string.Format("无法获取下一节点【{0}】", unit.Id));
                        }
                        else
                        {
                            var nextUnits3 = new List<WFUnit>();
                            nextUnits3.Add(nextUnits2[0]);
                            taskList.AddRange(await GetTask(nextUnits3, isReject, unit.Id));
                        }
                        break;
                    //case "gatewayInclusive":
                    case "bpmn:InclusiveGateway":
                        // 包容网关会等待所有分支汇入才往下执行，出口分支能执行多条（条件为true）
                        bool isNext = false;
                        var preIdList2 = GetPreUnitIds(unit.Id);
                        if (preIdList2.Count <= 1)
                        {
                            isNext = true;
                        }
                        else
                        {

                            var awaitTaskList = await Config.GetAwaitTaskList(Config.Params.ProcessId, unit.Id);
                            var awaitTaskList2 = awaitTaskList.FindAll(t => t.PrevUnitId != startId); // 排除当前等待任务的所有等待任务
                            if (awaitTaskList2.Count + 1 >= preIdList2.Count)
                            {
                                // 如果所有支路都被执行了就生成一个取消所有等待任务的命令
                                taskList.Add(GetDeleteAwaitTask(unit, isReject, startId, startUnit.Name));
                                isNext = true;
                            }
                            else
                            {
                                taskList.Add(GetAwaitTask(unit, isReject, startId, startUnit.Name));
                            }
                        }

                        if (isNext)
                        {
                            var conditionCodes2 = await GetConditionIds(unit.Conditions);
                            var nextUnits3 = GetNextUnits(unit.Id, conditionCodes2);
                            nextUnits3.AddRange(GetNextUnitsNoSet(unit.Id));
                            taskList.AddRange(await GetTask(nextUnits3, isReject, unit.Id));
                        }
                        break;
                    //case "userTask":// 审批节点
                    case "bpmn:Task":// 审批节点
                        // 1.获取节点上一次的请求人
                        var preAuditUsers = await Config.GetPrevTaskUserList(Config.Params.ProcessId, unit.Id);
                        if (preAuditUsers.FindIndex(t => t.State == 1) != -1)
                        {
                            // 如果此节点被激活不需要审核
                            break;
                        }


                        var auditUsers = new List<WFUserInfo>();
                        if (preAuditUsers.Count == 0)
                        {
                            // 表示此节点未被处理过
                            // 获取审核人
                            if (Config.Params.NextUsers != null && Config.Params.NextUsers.ContainsKey(unit.Id))
                            {
                                var auditUserList = new List<WFAuditor>();
                                var strAuditUser = Config.Params.NextUsers[unit.Id];
                                var strAuditUserList = strAuditUser.Split(",");
                                foreach (var id in strAuditUserList)
                                {
                                    auditUserList.Add(new WFAuditor()
                                    {
                                        Type = "3",
                                        Id = id
                                    });
                                }

                                auditUsers = await Config.GetUserList(auditUserList, CreateUser, Config.Params.ProcessId, _startNode);
                            }
                            else
                            {
                                auditUsers = await Config.GetUserList(unit.AuditUsers, CreateUser, Config.Params.ProcessId, _startNode);
                            }

                            // 添加传阅任务，节点第一次执行的时候触发
                            var lookUsers = await Config.GetUserList(unit.LookUsers, CreateUser, Config.Params.ProcessId, _startNode);
                            taskList.AddRange(GetLookUserTaskList(unit, lookUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
                        }
                        else
                        {
                            // 添加一条任务用于更新之前任务状态(将之前的任务设置成不是最近的一次任务)
                            taskList.Add(GetUpdateTask(unit));
                        }

                        // 表示找不到审核人
                        if (preAuditUsers.Count == 0 && auditUsers.Count == 0)
                        {
                            switch (unit.NoAuditor)
                            {
                                case "1":
                                    taskList.AddRange(GetUserTaskList(unit, await Config.GetSystemUserList(), isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
                                    break;
                                case "2":
                                    // 流转到下一个节点
                                    taskList.Add(GetSkipTask(unit, isReject, startId, startUnit.Name));
                                    taskList.AddRange(await GetTask(unit.Id));
                                    break;
                                case "3":
                                    throw new Exception(string.Format("【{0}{1}】找不到审核人，无法提交", unit.Name, unit.Id));
                            }
                        }

                        // 1.需要先判断是否是会签
                        if (unit.IsCountersign)
                        {
                            // 之前有人处理过
                            if (preAuditUsers.Count > 0)
                            {
                                // 驳回处理，重新开启审核
                                if (isReject)
                                {
                                    taskList.AddRange(GetCountersignTask(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType));
                                }
                                else
                                // 1.判断之前的会签策略是否通过
                                if (await Config.IsCountersignAgree(Config.Params.ProcessId, unit.Id))
                                {
                                    // 判断自动同意规则，会签状态下只有3有效
                                    if (unit.AutoAgree.IndexOf("3") != -1)
                                    {
                                        taskList.AddRange(await GetTask(unit.Id));// 自动审核，流转到下一节点
                                    }
                                    else
                                    {
                                        taskList.AddRange(GetCountersignTask(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType));
                                    }
                                }
                                else
                                {
                                    taskList.AddRange(GetCountersignTask(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType, unit.CountersignAgian));
                                }
                            }
                            // 第一次处理
                            else
                            {
                                taskList.AddRange(GetCountersignTask(unit, auditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString(), unit.CountersignType));
                            }
                        }
                        else
                        {
                            // 之前有人处理过
                            if (preAuditUsers.Count > 0)
                            {
                                if (IsAtuoAgree(preAuditUsers, unit.AutoAgree.Split(','), isReject))
                                {
                                    taskList.AddRange(await GetTask(unit.Id, "agree"));
                                }
                                else
                                {
                                    // 判断是否有完成任务的人
                                    if (preAuditUsers.FindIndex(t => t.State == 3) != -1)
                                    {
                                        taskList.AddRange(GetUserTaskList(unit, preAuditUsers.FindAll(t => t.State == 3), isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
                                    }
                                    else
                                    {
                                        taskList.AddRange(GetUserTaskList(unit, preAuditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
                                    }
                                }
                            }
                            else
                            {
                                if (IsAtuoAgree(auditUsers, unit.AutoAgree.Split(','), isReject))
                                {
                                    taskList.Add(GetAutoSkipTask(unit, isReject, startId, startUnit.Name));// 作为日志记录
                                    taskList.AddRange(await GetTask(unit.Id, "agree"));
                                }
                                else
                                {
                                    taskList.AddRange(GetUserTaskList(unit, auditUsers, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
                                }
                            }
                        }
                        break;
                    case "bpmn:ScriptTask":// 脚本节点
                        taskList.Add(GetScriptTaskList(unit, isReject, startId, startUnit.Name, Guid.NewGuid().ToString()));
                        taskList.AddRange(await GetTask(unit.Id));
                        break;
                    //case "subprocess":// 暂时不支持
                    case "bpmn:SubProcess":
                        taskList.Add(GetSubprocessTask(unit, startId, startUnit.Name));
                        break;
                    //case "endEvent":// 结束节点
                    case "bpmn:EndEvent":// 结束节点
                        taskList.Add(GetEndTask(unit, startId, startUnit.Name));
                        break;
                }
            }

            return taskList;
        }


        #region 私有方法
        /// <summary>
        /// 获取开始任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="IsReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetStartTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Name = "重新创建",
                Token = Guid.NewGuid().ToString(),
                Type = 4,
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
                IsReject = IsReject,
                MessageType = unit.MessageType,
                User = _config.Params.CreateUser
            };
            return task;
        }

        private WorkFlow.WFTask GetEndTask(WFUnit unit, string preUnitId, string preUnitName)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Name = "流程结束",
                Token = Guid.NewGuid().ToString(),
                Type = 100,
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
            };
            return task;
        }
        /// <summary>
        /// 获取一个等待任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="IsReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetAwaitTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Name = "等待其它支路完成",
                Type = 21,
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
                IsReject = IsReject
            };

            return task;
        }

        /// <summary>
        /// 获取一个更新任务
        /// </summary>
        /// <param name="unit"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetUpdateTask(WFUnit unit)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Type = 26,
            };

            return task;
        }

        /// <summary>
        /// 获取一个找不到审核人直接跳过任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="IsReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetSkipTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Name = "当前任务找不到审核人直接跳过",
                Type = 23,
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
                IsReject = IsReject
            };

            return task;
        }

        /// <summary>
        /// 获取一个找不到审核人直接跳过任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="IsReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetAutoSkipTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Name = "自动审核规则跳过",
                Type = 24,
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
                IsReject = IsReject
            };

            return task;
        }


        /// <summary>
        /// 获取一个取消等待任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="IsReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetDeleteAwaitTask(WFUnit unit, bool IsReject, string preUnitId, string preUnitName)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Name = "取消等待任务",
                Type = 22,
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
                IsReject = IsReject
            };

            return task;
        }
        /// <summary>
        /// 获取审批任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="userList"></param>
        /// <param name="isReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private List<WorkFlow.WFTask> GetUserTaskList(WFUnit unit, List<WFUserInfo> userList, bool isReject, string preUnitId, string preUnitName, string token)
        {
            List<WorkFlow.WFTask> list = new List<WorkFlow.WFTask>();
            int type = 1;
            if (unit!=null&&unit.IsSingleTask)
            {
                type = 7;
            }
            foreach (var user in userList)
            {
                WorkFlow.WFTask task = new WorkFlow.WFTask()
                {
                    UnitId = unit.Id,
                    Name = unit.Name,
                    Type = type,
                    PrevUnitId = preUnitId,
                    PrevUnitName = preUnitName,
                    IsReject = isReject,
                    Token = token,
                    MessageType = unit.MessageType,

                    // 超时设置
                    IsOvertimeMessage = unit.IsOvertimeMessage,
                    OvertimeMessageStart = unit.OvertimeMessageStart,
                    OvertimeMessageInterval = unit.OvertimeMessageInterval,
                    OvertimeGo = unit.OvertimeGo,
                    OvertimeMessageType = unit.OvertimeMessageType,

                    IsBatchAudit = unit.IsBatchAudit,
                    // 处理人
                    User = user

                };
                if (string.IsNullOrEmpty(task.Name))
                {
                    task.Name = "审核处理";
                }

                list.Add(task);
            }


            return list;
        }


        /// <summary>
        /// 获取传阅任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="userList"></param>
        /// <param name="isReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private List<WorkFlow.WFTask> GetLookUserTaskList(WFUnit unit, List<WFUserInfo> userList, bool isReject, string preUnitId, string preUnitName, string token)
        {
            List<WorkFlow.WFTask> list = new List<WorkFlow.WFTask>();
            foreach (var user in userList)
            {
                WorkFlow.WFTask task = new WorkFlow.WFTask()
                {
                    UnitId = unit.Id,
                    Name = unit.Name,
                    Type = 2,
                    PrevUnitId = preUnitId,
                    PrevUnitName = preUnitName,
                    IsReject = isReject,
                    Token = token,
                    MessageType = unit.MessageType,

                    // 处理人
                    User = user

                };
                if (string.IsNullOrEmpty(task.Name))
                {
                    task.Name = "查看";
                }

                list.Add(task);
            }


            return list;
        }

        /// <summary>
        /// 获取会签审批任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="userList"></param>
        /// <param name="isReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <param name="token"></param>
        /// <param name="countersignType">审核方式 1.并行 2.串行</param>
        /// <param name="countersignAgian">再次审核 1.已同意不需要审核 2.已同意需要审核</param>
        /// <returns></returns>
        private List<WorkFlow.WFTask> GetCountersignTask(WFUnit unit, List<WFUserInfo> userList, bool isReject, string preUnitId, string preUnitName, string token, string countersignType, string countersignAgian = "2")
        {
            List<WorkFlow.WFTask> list = new List<WorkFlow.WFTask>();
            int num = 1;
            foreach (var user in userList)
            {
                if (countersignAgian == "1" && user.IsAgree)
                {
                    continue;
                }

                user.IsAwait = countersignType == "1" ? false : true;
                user.Sort = num;
                if (num == 1)
                {
                    user.IsAwait = false;
                }
                WorkFlow.WFTask task = new WorkFlow.WFTask()
                {
                    UnitId = unit.Id,
                    Name = unit.Name,
                    Type = 5,
                    PrevUnitId = preUnitId,
                    PrevUnitName = preUnitName,
                    IsReject = isReject,
                    Token = token,
                    MessageType = unit.MessageType,

                    // 超时设置
                    IsOvertimeMessage = unit.IsOvertimeMessage,
                    OvertimeMessageStart = unit.OvertimeMessageStart,
                    OvertimeMessageInterval = unit.OvertimeMessageInterval,
                    OvertimeGo = unit.OvertimeGo,
                    OvertimeMessageType = unit.OvertimeMessageType,

                    IsBatchAudit = unit.IsBatchAudit,
                    // 处理人
                    User = user,


                };
                if (string.IsNullOrEmpty(task.Name))
                {
                    task.Name = "审核处理";
                }

                list.Add(task);

                num++;
            }


            return list;
        }

        /// <summary>
        /// 获取脚本执行任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="isReject"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetScriptTaskList(WFUnit unit, bool isReject, string preUnitId, string preUnitName, string token)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                UnitId = unit.Id,
                Name = unit.Name,
                Type = 10,
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
                IsReject = isReject,
                Token = token,

                ExecuteType = unit.ExecuteType,
                SqlDb = unit.SqlDb,
                SqlStr = unit.SqlStr,
                SqlStrRevoke = unit.SqlStrRevoke,
                ApiUrl = unit.ApiUrl,
                ApiUrlRevoke = unit.ApiUrlRevoke,
                Ioc = unit.Ioc,
                IocRevoke = unit.IocRevoke,


            };
            if (string.IsNullOrEmpty(task.Name))
            {
                task.Name = "脚本执行";
            }


            return task;
        }


        /// <summary>
        /// 获取成立的条件ID
        /// </summary>
        /// <param name="conditions">条件列表</param>
        /// <returns></returns>
        private async Task<List<string>> GetConditionIds(List<WFCondition> conditions)
        {
            List<string> list = new List<string>();
            foreach (var condition in conditions)
            {
                //获取数据id
                var process = await client.Queryable<WFProcess>().FirstAsync(a => a.Id == _config.Params.ProcessId);
                WFInstanceInfo instanceInfo = null;
                if (process != null)
                {
                  //  instanceInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<WFInstanceInfo>(process.InstanceInfo);
                  instanceInfo = process.InstanceInfo;
                }

                if (condition.Type == "1")// 字段比较
                {
                    string sql = string.Format("select \"{0}\" from \"{1}\" where \"{2}\" = @processId ", condition.Cfield, condition.Table, condition.Rfield, condition.Rfield);
                    //var dt = await dbFactory.BaseRepository(condition.DbCode).FindTable(sql, new { processId = _config.Params.ProcessId });
                    var pars = client.Ado.GetParameters(new { processId = instanceInfo.pkeyValue });
                    var dt = await client.Ado.GetDataTableAsync(sql, pars);
                    if (dt.Rows.Count > 0)
                    {
                        var value = dt.Rows[0][condition.Cfield.ToLower()].ToString();

                        switch (condition.CompareType)
                        {
                            case "1":
                                if (value == condition.Value)
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "2":
                                if (value != condition.Value)
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "3":
                                if (Convert.ToDecimal(value) > Convert.ToDecimal(condition.Value))
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "4":
                                if (Convert.ToDecimal(value) >= Convert.ToDecimal(condition.Value))
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "5":
                                if (Convert.ToDecimal(value) < Convert.ToDecimal(condition.Value))
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "6":
                                if (Convert.ToDecimal(value) <= Convert.ToDecimal(condition.Value))
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "7":
                                if (value.IndexOf(condition.Value) != -1)
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "8":
                                if (value.IndexOf(condition.Value) == -1)
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "9":
                                if (condition.Value.IndexOf(value) != -1)
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                            case "10":
                                if (condition.Value.IndexOf(value) == -1)
                                {
                                    list.Add(condition.Code);
                                }
                                break;
                        }
                    }

                }
                else
                {// sql语句
                    //var dt = await dbFactory.BaseRepository(condition.DbCode).FindTable(condition.Sql, new { processId = _config.Params.ProcessId, userId = CreateUser.Id, userAccount = CreateUser.Account, companyId = CreateUser.CompanyId, departmentId = CreateUser.DepartmentId });
                    //var pars = client.Ado.GetParameters(new { processId = _config.Params.ProcessId, userId = CreateUser.Id, userAccount = CreateUser.Account, companyId = CreateUser.CompanyId, departmentId = CreateUser.DepartmentId });
                                        var pars = client.Ado.GetParameters(new { processId = instanceInfo.pkeyValue, userId = CreateUser.Id, userAccount = CreateUser.Account, companyId = CreateUser.CompanyId, departmentId = CreateUser.DepartmentId });
                    var dt = await client.Ado.GetDataTableAsync(condition.Sql, pars);

                    if (dt.Rows.Count > 0)
                    {
                        list.Add(condition.Code);
                    }
                }
            }

            return list;
        }
        /// <summary>
        /// 判断是否自动同意
        /// </summary>
        /// <param name="auditUsers">审核处理人</param>
        /// <param name="atuoAgrees">自动同意策略1.处理人就是提交人 2.处理人和上一步的处理人相同 3.处理人审批过</param>
        /// <param name="isReject">是否是驳回</param>
        /// <returns></returns>
        private bool IsAtuoAgree(List<WFUserInfo> auditUsers, string[] atuoAgrees, bool isReject)
        {
            if (isReject)
            {
                return false;
            }

            bool res = false;
            if (auditUsers.Count == 0 || atuoAgrees.Length == 0)
            {
                return res;
            }

            foreach (var item in atuoAgrees)
            {
                switch (item)
                {
                    case "1":
                        if (auditUsers.FindIndex(t => t.Id == CreateUser.Id) != -1)
                        {
                            res = true;
                        }
                        break;
                    case "2":
                        if (auditUsers.FindIndex(t => t.Id == CurrentUser.Id) != -1)
                        {
                            res = true;
                        }
                        break;
                    case "3":
                        if (auditUsers.FindIndex(t => t.IsAgree) != -1 && !isReject)
                        {
                            res = true;
                        }
                        break;
                }
            }
            return res;
        }


        /// <summary>
        /// 获取子流程任务
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="preUnitId"></param>
        /// <param name="preUnitName"></param>
        /// <returns></returns>
        private WorkFlow.WFTask GetSubprocessTask(WFUnit unit, string preUnitId, string preUnitName)
        {
            WorkFlow.WFTask task = new WorkFlow.WFTask()
            {
                Type = 3,
                UnitId = unit.Id,
                Name = "子流程",
                Token = Guid.NewGuid().ToString(),
                PrevUnitId = preUnitId,
                PrevUnitName = preUnitName,
                ChildSchemeInfoId = unit.WfschemeId,
                User = _config.Params.CreateUser
            };
            return task;
        }
        #endregion
    }
}
