using Hotline.FlowEngine.Definitions;
using Hotline.FlowEngine.Workflows;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.FlowEngine;
using Hotline.Share.Enums.FlowEngine;
using XF.Domain.Entities;
using XF.Domain.Exceptions;

namespace Hotline.FlowEngine;

public class FlowAssignInfo
{
    /// <summary>
    /// 流程指派类型
    /// </summary>
    public EFlowAssignType FlowAssignType { get; set; }

    /// <summary>
    /// 办理对象
    /// </summary>
    public FlowStepHandler Handler { get; set; }

    /// <summary>
    /// 办理对象（UserIds/OrgCodes）
    /// </summary>
    public List<HandlerGroupItem> HandlerObjects { get; set; } = new();

    /// <summary>
    /// 创建mode对象实例，自动生成一个groupId
    /// </summary>
    public static FlowAssignInfo Create(EFlowAssignType flowAssignType, List<Kv> handlers, bool isStartCountersign = false)
    {
        if (handlers == null || !handlers.Any())
            return new();
        List<HandlerGroupItem> handlerObjects;
        if (isStartCountersign)
        {
            //会签
            handlerObjects = handlers.Select(d => new HandlerGroupItem
            {
                Key = d.Key,
                Value = d.Value,
                GroupId = Guid.NewGuid().ToString(),
            }).ToList();
        }
        else
        {
            //或签
            var groupId = Guid.NewGuid().ToString();
            handlerObjects = handlers.Select(d => new HandlerGroupItem
            {
                Key = d.Key,
                Value = d.Value,
                GroupId = groupId
            }).ToList();
        }

        return new FlowAssignInfo
        {
            FlowAssignType = flowAssignType,
            HandlerObjects = handlerObjects,
        };
    }

    /// <summary>
    /// 办理人/办理部门（UserIds/OrgCodes）
    /// </summary>
    /// <returns></returns>
    public List<string> GetHandlerIds() =>
        HandlerObjects.Select(d => d.Key).ToList();

    public List<Kv> GetHandlers() =>
        HandlerObjects.Select(d => new Kv(d.Key, d.Value))
            .Distinct()
            .ToList();

    public static EFlowAssignType GetAssignType(EHandlerType handlerType, bool hasSelectedHandlers) =>
        handlerType switch
        {
            EHandlerType.Role => hasSelectedHandlers ? EFlowAssignType.User : EFlowAssignType.Role,
            EHandlerType.OrgLevel => EFlowAssignType.Org,
            EHandlerType.OrgType => EFlowAssignType.Org,
            EHandlerType.AssignedUser => EFlowAssignType.User,
            EHandlerType.AssignedOrg => EFlowAssignType.Org,
            _ => throw new ArgumentOutOfRangeException(nameof(handlerType), handlerType, null)
        };
}