using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GxPress.Common.Exceptions;
using GxPress.Common.Tools;
using GxPress.Entity.WorkProcess;
using GxPress.Entity.WorkProcessDto;


namespace GxPress.Service.Implement
{
    public partial class ProcessService
    {
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<Process> AddAsync(ProcessDto request)
        {
            request.IconUrl = StringUtils.RemoveDomain(request.IconUrl);
            //1.保存基本信息
            var group = await _processGroupRepository.GetAsync(request.GroupId);
            if (group == null) throw new BusinessException("流程分组不存在");

            var process = _mapper.Map<Entity.WorkProcess.Process>(request);

            process.IsDisabled = false;//创建的时候默认启用
            process.Id = await _processRepository.InsertAsync(process);

            //2.保存发起限制
            foreach (var limit in request.RequestLimits)
            {
                await _processRequestLimitRepository.InsertAsync(new ProcessRequestLimit
                {
                    ProcessId = process.Id,
                    DepartmentId = limit.DepartmentId,
                    RoleId = limit.RoleId,
                    UserId = limit.UserId
                });
            }

            var fieldDict = new Dictionary<int, int>();

            //3.保存表单定义
            if (request.FormFields != null)
            {
                foreach (var field in request.FormFields)
                {
                    //保存字段
                    var fieldId = await _processFieldRepository.InsertAsync(new ProcessField
                    {
                        ProcessId = process.Id,
                        Label = field.Label,
                        Placeholder = field.Placeholder,
                        Required = field.Required,
                        Sort = field.Sort,
                        Type = field.Type,
                        Unit = field.Unit,
                        Options = StringUtils.ObjectCollectionToString(field.Options)
                    });
                    //保存选项信息

                    fieldDict.Add(field.Id, fieldId);
                }
            }

            //4.保存节点定义
            if (request.ProcessNodes != null)
            {
                foreach (var node in request.ProcessNodes)
                {
                    await AddNodeAsync(node, 0, process.Id, fieldDict);
                }
            }

            return process;
        }

        /// <summary>
        /// 插入流程节点树
        /// </summary>
        /// <param name="node"></param>
        /// <param name="parentId"></param>
        /// <param name="processId"></param>
        /// <param name="fieldDict"></param>
        /// <returns></returns>
        private async Task AddNodeAsync(ProcessNodeDto node, int parentId, int processId, Dictionary<int, int> fieldDict)
        {
            //插入节点
            var readOnlyFields = new List<int>();
            if (node.ReadOnlyFields != null)
            {
                foreach (var readOnlyField in node.ReadOnlyFields)
                {
                    if (fieldDict.ContainsKey(readOnlyField))
                    {
                        readOnlyFields.Add(fieldDict[readOnlyField]);
                    }
                }
            }
            var hiddenFields = new List<int>();
            if (node.HiddenFields != null)
            {
                foreach (var hiddenField in node.HiddenFields)
                {
                    if (fieldDict.ContainsKey(hiddenField))
                    {
                        hiddenFields.Add(fieldDict[hiddenField]);
                    }
                }
            }

            var nodeId = await _processNodeRepository.InsertAsync(new Entity.WorkProcess.ProcessNode
            {
                Name = node.Name,
                ParentId = parentId,//调用方法是传入的开始节点父节点id为
                ProcessId = processId,
                Type = node.Type,
                ReadOnlyFields = string.Join(',', readOnlyFields),
                HiddenFields = string.Join(',', hiddenFields),
                AllowMeeting = node.AllowMeeting,
                ApprovalType = node.ApprovalType,
                DefaultApprovalUserId = node.DefaultApprovalUserId,
                CaseLevel = node.CaseLevel
            });

            //设置抄送人
            foreach (var cc in node.CarbonCopies)
            {
                await _ruleCarbonCopyRepository.InsertAsync(new RuleCarbonCopy
                {
                    NodeId = nodeId,
                    UserId = cc.UserId,
                    RoleId = cc.RoleId,
                    DepartmentId = cc.DepartmentId
                });
            }

            //根据节点类型插入扩展信息
            //添加审批人设置
            if (node.ApproverChecks != null)
            {
                foreach (var approverChecks in node.ApproverChecks)
                {
                    await _ruleApproverCheckRepository.InsertAsync(new RuleApproverCheck
                    {
                        NodeId = nodeId,
                        UserId = approverChecks.UserId,
                        RoleId = approverChecks.RoleId,
                        DepartmentId = approverChecks.DepartmentId
                    });
                }
            }

            if (node.Conditions != null)
            {
                foreach (var condition in node.Conditions)
                {
                    if (!fieldDict.ContainsKey(condition.FieldId)) continue;

                    await _ruleConditionRepository.InsertAsync(new RuleCondition
                    {
                        NodeId = nodeId,
                        FieldId = fieldDict[condition.FieldId],
                        Operator = condition.Operator,
                        StringValue = condition.StringValue,
                        StringValues = StringUtils.ObjectCollectionToString(condition.StringValues),
                        IntValue = condition.IntValue,
                        Sort = condition.Sort
                    });


                }
            }

            //是否有下级节点,递归插入下级节点
            if (node.Children.Any())
            {
                foreach (var child in node.Children)
                {
                    await AddNodeAsync(child, nodeId, processId, fieldDict);
                }
            }
        }
    }
}