using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Datory;
using GxPress.Common.Tools;
using GxPress.Entity;
using GxPress.Entity.WorkFlowDto;
using GxPress.Entity.WorkProcessDto;
using GxPress.EnumConst;
using GxPress.Result.App.Flow;

namespace GxPress.Service.Implement
{
    public partial class FlowService
    {
        public async Task<FlowDto> GetAsync(int flowId)
        {
            var flow = await _flowRepository.GetAsync(flowId);
            if (flow == null) return null;
            var fieldValues = await _flowFieldValueRepository.GetListAsync(flowId);
            var fields = new List<FlowField>();
            foreach (var flowFieldValue in fieldValues)
            {
                fields.Add(new FlowField
                {
                    Id = flowFieldValue.FieldId,
                    Type = flowFieldValue.FieldType,
                    Value = GetFieldValue(flowFieldValue)
                });
            }

            var dto = new FlowDto
            {
                Id = flowId,
                ProcessId = flow.ProcessId,
                UserId = flow.UserId,
                State = flow.State,
                CreatedDate = flow.CreatedDate,
                Guid = flow.Guid,
                ProcessNodeId = flow.ProcessNodeId,
                Fields = fields
            };
            //获取审核和抄送人
            var flowToDos = await _flowTodoRepository.GetAllAsync(Q.Where(nameof(Entity.WorkFlow.FlowTodo.FlowId), flowId));
            if (flowToDos.Count() > 0)
            {
                dto.ApproverCheckUserIds = flowToDos.Where(n => n.Type == nameof(TodoTypeConst.ApproverCheck)).Select(n => n.UserId).ToList();
                dto.CarbonCopyUserIds = flowToDos.Where(n => n.Type == nameof(TodoTypeConst.CarbonCopy)).Select(n => n.UserId).ToList();
            }
            return dto;
        }

        public async Task<(string Title, List<string> Summaries)> GetFlowTitleAndSummaryAsync(User user, int processId, int flowId)
        {
            var process = await _processRepository.GetAsync(processId);

            if (process != null)
            {
                var fieldList = await _processFieldRepository.GetListAsync(processId);
                var valueList = await _flowFieldValueRepository.GetListAsync(flowId);
                var summaries = new List<string>();

                if (fieldList != null)
                {
                    foreach (var processField in fieldList)
                    {
                        var value = valueList?.FirstOrDefault(v => v.FieldId == processField.Id);
                        if (value != null)
                        {
                            summaries.Add($"{processField.Label}：{GetFieldValue(value)}");
                        }
                    }
                }
                return (GetFlowName(user, process), summaries);
            }

            return (GetFlowName(user, process), new List<string>());
        }

        public async Task<FlowResult> GetFlowResult(int flowId, int userId = 0)
        {
            var flowDto = await GetAsync(flowId);
            var user = await _userRepository.GetAsync(flowDto.UserId);
            var avatarUrl = await _userRepository.GetAvatarUrlAsync(flowDto.UserId);
            var process = await _processRepository.GetAsync(flowDto.ProcessId);
            if (process == null)
                throw new GxPress.Common.Exceptions.BusinessException("工作流不存在");
            var processFields = await _processFieldRepository.GetListAsync(flowDto.ProcessId);
            var valueList = await _flowFieldValueRepository.GetListAsync(flowId);
            var formFields = new List<FormField>();
            if (processFields != null)
            {
                foreach (var field in processFields)
                {
                    var flowFieldValue = valueList.FirstOrDefault(x => x.FieldId == field.Id);
                    formFields.Add(new FormField
                    {
                        Id = field.Id,
                        Label = field.Label,
                        Placeholder = field.Placeholder,
                        Required = field.Required,
                        Sort = field.Sort,
                        Type = field.Type,
                        Unit = field.Unit,
                        Options = StringUtils.StringCollectionToStringList(field.Options),
                        Value = GetFieldValue(flowFieldValue)
                    });
                }
            }

            var nodes = new List<NodeResult>
            {
                new NodeResult
                {
                    AvatarUrl = avatarUrl,
                    Name = user.Name,
                    Action = NodeStateConstUtils.GetText(NodeStateConst.Start),
                    CreatedDate = flowDto.CreatedDate
                }
            };

            var todoList = await _flowTodoRepository.GetListByFlowIdAsync(flowId);
            var carbonCopies = new List<string>();
            foreach (var flowTodo in todoList)
            {
                if (flowTodo.Type == nameof(TodoTypeConst.ApproverCheck))
                {
                    nodes.Add(new NodeResult
                    {
                        AvatarUrl = await _userRepository.GetAvatarUrlAsync(flowTodo.UserId),
                        Name = await _userRepository.GetNameAsync(flowTodo.UserId),
                        Action = GetTodoAction(flowTodo),
                        CreatedDate = flowTodo.LastModifiedDate,
                        Message = flowTodo.Message
                    });
                }
                else if (flowTodo.Type == nameof(TodoTypeConst.CarbonCopy))
                {
                    var nodeUserName = await _userRepository.GetNameAsync(flowTodo.UserId);
                    carbonCopies.Add(nodeUserName);
                }
            }

            // var checkMessages = new List<MessageResult>();
            // var messages = await _flowMessageRepository.GetListByFlowIdAsync(flowId, nameof(TodoTypeConst.ApproverCheck));
            // foreach (var message in messages)
            // {
            //     checkMessages.Add(new MessageResult
            //     {
            //         AvatarUrl = await _userRepository.GetAvatarUrlAsync(message.UserId),
            //         Name = await _userRepository.GetNameAsync(message.UserId),
            //         Message = message.Message,
            //         CreatedDate = message.CreatedDate
            //     });
            // }
            //获取系统配置抄送人和审核人
            var processNodeDtos = await GetNodesAsync(flowDto, await _processService.GetNodesAsync(flowDto.ProcessId, 0));
            //系统抄送人
            var carbonCopyUserIds = new List<int>();
            //系统审核人
            var approverCheckUserIds = new List<int>();
            foreach (var processNodeDto in processNodeDtos)
            {
                //抄送人
                if (processNodeDto.Type == nameof(ProcessNodeTypeConst.Start))
                {
                    carbonCopyUserIds.AddRange(await GetListUserAsync(processNodeDto));
                }
                //插入审核人 
                if (processNodeDto.Type == nameof(ProcessNodeTypeConst.Approver))
                {
                    approverCheckUserIds.AddRange(await GetListUserAsync(processNodeDto));
                    //break;
                }
                //抄送人
                if (processNodeDto.Type == nameof(ProcessNodeTypeConst.End))
                {
                    carbonCopyUserIds.AddRange(await GetListUserAsync(processNodeDto));
                    break;
                }
            }

            var flowResult = new FlowResult
            {
                ProcessId = process.Id,
                AvatarUrl = avatarUrl,
                UserName = user.Name,
                Name = GetFlowName(user, process),
                FlowState = flowDto.State,
                No = flowDto.No,
                DepartmentName = await _departmentRepository.GetNameAsync(user.DepartmentId),
                CreatedDate = flowDto.CreatedDate,
                FormFields = formFields,
                Nodes = nodes,
                CarbonCopies = string.Join(",", carbonCopies),
                UserId = flowDto.UserId
                // CheckMessages = checkMessages
            };
            //流程名称
            flowResult.ProcessName = process.Name;
            //抄送人
            flowResult.CarbonCopyUsers = await _userRepository.GeFlowUsers(carbonCopyUserIds, flowId, nameof(TodoTypeConst.CarbonCopy));
            //审核人
            flowResult.ApproverCheckUsers = await _userRepository.GeFlowUsers(approverCheckUserIds, flowId, nameof(TodoTypeConst.ApproverCheck));
            if (userId > 0)
            {
                //获取副流程
                var flowToDo = await _flowTodoRepository.GetAsync(Q.Where(nameof(Entity.WorkFlow.FlowTodo.UserId), userId).Where(nameof(Entity.WorkFlow.FlowTodo.FlowId), flowId).Where(nameof(Entity.WorkFlow.FlowTodo.Type), nameof(TodoTypeConst.ApproverCheck)).OrderByDesc(nameof(Entity.WorkFlow.FlowTodo.CreatedDate)));
                if (flowToDo != null)
                {
                    if (flowToDo.IsDone && flowToDo.IsChecked)
                        flowResult.State = FlowState.Checked;
                    else if (flowToDo.IsDone && !flowToDo.IsChecked)
                    {
                        if (flowToDo.DoneType == 1)
                            flowResult.State = FlowState.Meeting;
                        else if (flowToDo.DoneType == 2)
                            flowResult.State = FlowState.Wait;
                        else
                            flowResult.State = FlowState.Denied;
                    }
                    else if (flowToDo.IsDone && !flowToDo.IsChecked)
                        flowResult.State = FlowState.Denied;
                    else
                    {
                        flowResult.State = FlowState.Checking;
                    }
                }
                else
                {
                    flowResult.State = FlowState.Checked;
                }
            }
            //获取会议上传的文件流
            var flowAttachments = await flowAttachmentRepository.GetAllAsync(Q.Where(nameof(Entity.WorkFlow.FlowAttachment.TypeId), 1).Where(nameof(Entity.WorkFlow.FlowAttachment.FlowId), flowId).OrderByDesc(nameof(Entity.WorkFlow.FlowAttachment.CreatedDate)));
            flowResult.FlowAttachments = flowAttachments.ToList();
            return flowResult;
        }
    }
}