using System.Linq;
using System.Threading.Tasks;
using Datory;
using GxPress.Common.Tools;
using GxPress.Entity.WorkFlow;
using GxPress.Entity.WorkFlowDto;
using GxPress.EnumConst;
using GxPress.Request.Notice;

namespace GxPress.Service.Implement
{
    public partial class FlowService
    {
        /// <summary>
        /// 添加工作流
        /// </summary>
        /// <param name="flow"></param>
        /// <returns></returns>
        public async Task<int> AddAsync(FlowDto flow)
        {
            //获取用户
            var user = await _userRepository.GetAsync(flow.UserId);
            //获取
            var process = await _processRepository.GetAsync(flow.ProcessId);
            flow.Id = await _flowRepository.InsertAsync(new Entity.WorkFlow.Flow
            {
                State = FlowState.Checking,
                ProcessId = flow.ProcessId,
                UserId = flow.UserId,
                IsRead = true
            });
            await _noticeService.AddNoticeFlowAsync(new NoticeInRequest
            {
                NoticeType = NoticeTypeConst.Send,
                Title = $"{user.Name}的{process.Name}流程",
                UserId = flow.UserId,
                SoureId = flow.Id,
                TypeValue = AllTypeConst.MySubmitted.GetHashCode(),
                SendUserId = user.Id,
                SendUserName = user.Name
            });
            foreach (var flowField in flow.Fields)
            {
                await _flowFieldValueRepository.InsertAsync(new FlowFieldValue
                {
                    ProcessId = flow.ProcessId,
                    FlowId = flow.Id,
                    FieldId = flowField.Id,
                    UserId = flow.UserId,
                    FieldType = flowField.Type,
                    StringValue = flowField.Value,
                    StringValues = flowField.Value,
                    IntValue = StringUtils.ToInt(flowField.Value)
                });
            }
            //添加审核人
            if (flow.ApproverCheckUserIds != null)
            {
                for (int i = 0; i < flow.ApproverCheckUserIds.Count(); i++)
                {
                    var todo = new FlowTodo
                    {
                        ProcessId = flow.ProcessId,
                        FlowId = flow.Id,
                        UserId = flow.ApproverCheckUserIds[i],
                        Type = nameof(TodoTypeConst.ApproverCheck),
                        IsDone = false,
                        IsOperate = i == 0,
                    };
                    var flowTodoId = await _flowTodoRepository.InsertAsync(todo);
                    //添加工作收件箱
                    if (todo.IsOperate)
                        await _noticeService.AddNoticeFlowAsync(new NoticeInRequest
                        {
                            NoticeType = NoticeTypeConst.Send,
                            Title = $"{user.Name}的{process.Name}流程",
                            UserId = todo.UserId,
                            SoureId = flow.Id,
                            SonId = flowTodoId,
                            TypeValue = AllTypeConst.MyChecked.GetHashCode(),
                            SendUserId = user.Id,
                            SendUserName = user.Name
                        });
                }
            }
            if (flow.CarbonCopyUserIds != null)
            {
                foreach (var userId in flow.CarbonCopyUserIds)
                {
                    var todo = new FlowTodo
                    {
                        ProcessId = flow.ProcessId,
                        FlowId = flow.Id,
                        UserId = userId,
                        Type = nameof(TodoTypeConst.CarbonCopy),
                        IsDone = false,
                        IsOperate = false
                    };
                    var flowTodoId = await _flowTodoRepository.InsertAsync(todo);
                    await _noticeService.AddNoticeFlowAsync(new NoticeInRequest
                    {
                        NoticeType = NoticeTypeConst.Send,
                        Title = $"{user.Name}的{process.Name}流程",
                        UserId = todo.UserId,
                        SoureId = flow.Id,
                        SonId = flowTodoId,
                        TypeValue = AllTypeConst.MyCc.GetHashCode(),
                        SendUserId = user.Id,
                        SendUserName = user.Name
                    });
                }
            }
            var nodes = await _processService.GetAllAsync(flow.ProcessId);

            foreach (var processNodeDto in nodes.Where(n => n.ParentId == 0))
            {
                if (processNodeDto.Type == nameof(ProcessNodeTypeConst.Start))
                {
                    await NodeExecuteAsync(flow, processNodeDto);
                }
                //插入审核人 
                if (processNodeDto.Type == nameof(ProcessNodeTypeConst.Approver) && processNodeDto.ParentId == 0)
                {
                    await NodeExecuteAsync(flow, processNodeDto);
                    //break;
                }
                if (processNodeDto.Type == nameof(ProcessNodeTypeConst.Switch))
                {
                    //工作流条件
                    await NodeExecuteSwitchAsync(flow, processNodeDto);
                }
                if (processNodeDto.Type == nameof(ProcessNodeTypeConst.End))
                {
                    await NodeExecuteAsync(flow, processNodeDto);
                    break;
                }
            }

            //创建工作流
            foreach (var item in flow.flowAttachments)
            {
                item.FlowId = flow.Id;
                item.TypeId = 1;
            }
            await flowAttachmentRepository.InsertsAsync(flow.flowAttachments);
            return flow.Id;
        }

        public async Task<int> ReAddAsync(int flowId)
        {
            var flow = await GetAsync(flowId);
            if (flow == null) return 0;

            flow.Id = await _flowRepository.InsertAsync(new Entity.WorkFlow.Flow
            {
                ProcessId = flow.ProcessId,
                State = FlowState.Checking,
                UserId = flow.UserId
            });
            //获取上一个的文件
            var flowAttachments = (await flowAttachmentRepository.GetAllAsync(flowId)).ToList();
            foreach (var item in flowAttachments)
            {
                item.FlowId = flow.Id;
                item.TypeId = 1;
            }
            await flowAttachmentRepository.InsertsAsync(flowAttachments);
            if (flow.Fields != null)
            {
                foreach (var flowField in flow.Fields)
                {
                    await _flowFieldValueRepository.InsertAsync(new FlowFieldValue
                    {
                        ProcessId = flow.ProcessId,
                        FlowId = flow.Id,
                        FieldId = flowField.Id,
                        UserId = flow.UserId,
                        FieldType = flowField.Type,
                        StringValue = flowField.Value,
                        StringValues = flowField.Value,
                        IntValue = StringUtils.ToInt(flowField.Value)
                    });
                }
            }
            for (int i = 0; i < flow.ApproverCheckUserIds.Count(); i++)
            {
                var todo = new FlowTodo
                {
                    ProcessId = flow.ProcessId,
                    FlowId = flow.Id,
                    UserId = flow.ApproverCheckUserIds[i],
                    Type = nameof(TodoTypeConst.ApproverCheck),
                    IsDone = false,
                    IsOperate = i == 0,
                };
                await _flowTodoRepository.InsertAsync(todo);
            }
            if (flow.ApproverCheckUserIds != null)
            {
                foreach (var userId in flow.ApproverCheckUserIds)
                {
                    var todo = new FlowTodo
                    {
                        ProcessId = flow.ProcessId,
                        FlowId = flow.Id,
                        UserId = userId,
                        Type = nameof(TodoTypeConst.CarbonCopy),
                        IsDone = false
                    };
                    await _flowTodoRepository.InsertAsync(todo);
                }
            }
            var nodes = await GetNodesAsync(flow, await _processService.GetNodesAsync(flow.ProcessId, 0));
            if (nodes != null)
            {
                foreach (var processNodeDto in nodes)
                {
                    if (processNodeDto.Type == nameof(ProcessNodeTypeConst.Start) ||
                        processNodeDto.Type == nameof(ProcessNodeTypeConst.End))
                    {
                        await NodeExecuteAsync(flow, processNodeDto);
                    }
                    else if (processNodeDto.Type == nameof(ProcessNodeTypeConst.Approver))
                    {
                        await NodeExecuteAsync(flow, processNodeDto);
                    }
                }
            }
            await DeleteAsync(flow.Id);
            return flow.Id;
        }
        /// <summary>
        /// 上会待定
        /// </summary>
        /// <param name="flowId"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<bool> ActionsWait(int flowId, int userId)
        {
            var flow = await GetAsync(flowId);
            if (flow == null) return false;
            var flowTode = await _flowTodoRepository.GetAsync(Q.Where(nameof(Entity.WorkFlow.FlowTodo.FlowId), flowId).Where(nameof(Entity.WorkFlow.FlowTodo.UserId), userId));
            if (flowTode == null)
                return false;
            flowTode.IsDone = true;
            flowTode.DoneType = 2;
            flowTode.IsChecked = false;
            return await _flowTodoRepository.UpdateAsync(flowTode);
        }
    }
}