using Hotline.FlowEngine.Definitions;
using Hotline.Settings;
using Hotline.Share.Dtos.FlowEngine;
using Hotline.Share.Enums.FlowEngine;
using SqlSugar;
using XF.Domain.Entities;
using XF.Domain.Exceptions;
using XF.Domain.Extensions;
using XF.Domain.Repository;

namespace Hotline.FlowEngine.Workflows;

[SugarIndex("index_workflow_externalId", nameof(Workflow.ExternalId), OrderByType.Asc)]
public partial class Workflow : CreationEntity
{
    public string DefinitionId { get; set; }

    /// <summary>
    /// 流程类型
    /// </summary>
    public EFlowType FlowType { get; set; }

    /// <summary>
    /// 审核结果
    /// </summary>
    public EReviewResult ReviewResult { get; set; }

    #region 业务模块(冗余)

    public string? ModuleId { get; set; }

    public string? ModuleName { get; set; }

    public string? ModuleCode { get; set; }

    #endregion

    /// <summary>
    /// 流程标题
    /// </summary>
    [SugarColumn(ColumnDataType = "varchar(2000)")]
    public string Title { get; set; }

    /// <summary>
    /// end节点办理完成时间
    /// </summary>
    public DateTime? EndTime { get; set; }

    /// <summary>
    /// 流程状态
    /// </summary>
    public EWorkflowStatus Status { get; set; }

    #region 实际办理信息（节点，部门，意见）

    /// <summary>
    /// 实际办理节点code（会签状态此字段保存最外层会签发起节点code）
    /// </summary>
    public string? ActualHandleStepCode { get; set; }

    /// <summary>
    /// 实际办理节点名称（会签状态此字段保存最外层会签发起节点名称）
    /// </summary>
    public string? ActualHandleStepName { get; set; }

    /// <summary>
    /// 实际办理节点id
    /// </summary>
    public string? ActualHandleStepId { get; set; }

    /// <summary>
    /// 到达实际办理节点时间（stepBox创建时间）
    /// </summary>
    public DateTime? ActualHandleStepCreateTime { get; set; }

    /// <summary>
    /// 实际办理节点签收时间
    /// </summary>
    public DateTime? ActualHandleStepAcceptTime { get; set; }

    /// <summary>
    /// 实际办理时间
    /// </summary>
    public DateTime? ActualHandleTime { get; set; }

    /// <summary>
    /// 实际办理人id
    /// </summary>
    public string? ActualHandlerId { get; set; }

    /// <summary>
    /// 实际办理人名称
    /// </summary>
    public string? ActualHandlerName { get; set; }

    /// <summary>
    /// 实际办理部门名称
    /// </summary>
    public string? ActualHandleOrgName { get; set; }

    /// <summary>
    /// 实际办理部门编码
    /// </summary>
    public string? ActualHandleOrgCode { get; set; }

    /// <summary>
    /// 实际办理部门等级
    /// </summary>
    public int? ActualHandleOrgLevel { get; set; }

    /// <summary>
    /// 实际办理部门行政区划编码
    /// </summary>
    public string? ActualHandleOrgAreaCode { get; set; }

    /// <summary>
    /// 实际办理部门行政区划名称
    /// </summary>
    public string? ActualHandleOrgAreaName { get; set; }

    /// <summary>
    /// 实际办理意见（办理中...or 最终办理意见）
    /// </summary>
    [SugarColumn(ColumnDataType = "text")]
    public string ActualOpinion { get; set; } = "办理中...";

    ///// <summary>
    ///// 真实办理人姓名（手动填写）
    ///// </summary>
    //public string? RealHandlerName { get; set; }

    ///// <summary>
    ///// 真实办理人电话（手动填写）
    ///// </summary>
    //public string? RealHandlerPhone { get; set; }

    ///// <summary>
    ///// 沟通方式（手动填写）
    ///// </summary>
    //public ERealCommunicationMode? RealCommunicationMode { get; set; }

    ///// <summary>
    ///// 沟通时间（手动填写）
    ///// </summary>
    //public DateTime? RealCommunicationTime { get; set; }

    ///// <summary>
    ///// 沟通地点（手动填写）
    ///// </summary>
    //public string? RealCommunicationAddress { get; set; }

    ///// <summary>
    ///// 已与市民沟通
    ///// </summary>
    //public bool? RealIsContacted { get; set; }

    ///// <summary>
    ///// 已与市民现场沟通
    ///// </summary>
    //public bool? RealContactLocale { get; set; }
    #endregion

    #region 当前办理节点信息(指派时赋值)

    public string? CurrentStepId { get; set; }

    /// <summary>
    /// 当前办理节点code（非会签：当前被指派节点，会签：会签发起节点）
    /// </summary>
    public string? CurrentStepCode { get; set; }

    /// <summary>
    /// 当前节点名称
    /// </summary>
    public string? CurrentStepName { get; set; }

    /// <summary>
    /// 到达当前节点时间
    /// </summary>
    public DateTime? CurrentStepCreateTime { get; set; }

    /// <summary>
    /// 当前办理节点签收时间
    /// </summary>
    public DateTime? CurrentStepAcceptTime { get; set; }

    /// <summary>
    /// 当前办理时间
    /// </summary>
    public DateTime? CurrentHandleTime { get; set; }

    /// <summary>
    /// 当前办理人id
    /// </summary>
    public string? CurrentHandlerId { get; set; }

    /// <summary>
    /// 当前办理人名称
    /// </summary>
    public string? CurrentHandlerName { get; set; }

    /// <summary>
    /// 当前办理部门名称
    /// </summary>
    public string? CurrentHandleOrgName { get; set; }

    /// <summary>
    /// 当前办理部门编码
    /// </summary>
    public string? CurrentHandleOrgId { get; set; }

    /// <summary>
    /// 当前办理部门等级
    /// </summary>
    public int? CurrentHandleOrgLevel { get; set; }

    /// <summary>
    /// 当前办理部门行政区划编码
    /// </summary>
    public string? CurrentHandleOrgAreaCode { get; set; }

    /// <summary>
    /// 当前办理部门行政区划名称
    /// </summary>
    public string? CurrentHandleOrgAreaName { get; set; }

    #endregion

    #region 会签

    /// <summary>
    /// 会签类型
    /// </summary>
    public ECounterSignType? CounterSignType { get; set; }

    /// <summary>
    /// 当前会签办理节点Id，嵌套会签为最外层会签办理节点Id
    /// </summary>
    public string? TopCountersignStepId { get; set; }

    /// <summary>
    /// 流程是否处于会签中（实时）
    /// </summary>
    public bool IsInCountersign { get; set; }

    #endregion


    // /// <summary>
    // /// 办结时长（分钟）
    // /// 办结时间-交办时间
    // /// </summary>
    // public double HandleDuration { get; set; }
    //
    // /// <summary>
    // /// 办结工作日时长
    // /// </summary>
    // public double HandleDurationWorkday { get; set; }

    /// <summary>
    /// 全流程时长（秒）
    /// 归档时间-创建时间
    /// </summary>
    public double AllDuration { get; set; }

    /// <summary>
    /// 外部业务唯一标识
    /// </summary>
    public string ExternalId { get; set; }

    #region 当前办理对象

    /// <summary>
    /// 办理人id
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<HandlerGroupItem> HandlerUsers { get; set; } = new();

    /// <summary>
    /// 办理部门id
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<HandlerGroupItem> HandlerOrgs { get; set; } = new();

    #endregion

    #region 流经对象

    /// <summary>
    /// 流经部门
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string> FlowedOrgIds { get; set; } = new();
    
    /// <summary>
    /// 流经办理人
    /// </summary>
    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string> FlowedUserIds { get; set; } = new();

    #endregion

    #region 会签实际办理对象

    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string>? CsActualHandleOrgIds { get; set; }

    [SugarColumn(ColumnDataType = "json", IsJson = true)]
    public List<string>? CsActualHandleUserIds { get; set; }

    #endregion

    #region 一级部门

    /// <summary>
    /// 一级部门code
    /// </summary>
    public string? OrgLevelOneCode { get; set; }

    /// <summary>
    /// 一级部门名称
    /// </summary>
    public string? OrgLevelOneName { get; set; }

    #endregion

    #region 受理人(开启流程的话务员)

    /// <summary>
    /// 受理人id
    /// </summary>
    public string? AcceptorId { get; set; }

    /// <summary>
    /// 受理人名称
    /// </summary>
    public string? AcceptorName { get; set; }

    /// <summary>
    /// 受理人工号
    /// </summary>
    public string? AcceptorStaffNo { get; set; }

    /// <summary>
    /// 受理人部门编码
    /// </summary>
    public string? AcceptorOrgId { get; set; }

    /// <summary>
    /// 受理人部门名称
    /// </summary>
    public string? AcceptorOrgName { get; set; }

    /// <summary>
    /// 受理人部门行政区划编码
    /// </summary>
    public string? AcceptorOrgAreaCode { get; set; }

    /// <summary>
    /// 受理人部门行政区划名称
    /// </summary>
    public string? AcceptorOrgAreaName { get; set; }

    #endregion

}

public partial class Workflow
{
    [Navigate(NavigateType.OneToOne, nameof(DefinitionId))]
    public WorkflowDefinition WorkflowDefinition { get; set; }

    // /// <summary>
    // /// 补充信息
    // /// </summary>
    // [Navigate(NavigateType.OneToMany, nameof(WorkflowSupplement.WorkflowId))]
    // public List<WorkflowSupplement> Supplements { get; set; }

    /// <summary>
    /// 会签
    /// </summary>
    [Navigate(NavigateType.OneToMany, nameof(WorkflowCountersign.WorkflowId))]
    public List<WorkflowCountersign> Countersigns { get; set; }

    /// <summary>
    /// 节点，依据流转进度动态生成或删除
    /// </summary>
    [Navigate(NavigateType.OneToMany, nameof(WorkflowStep.WorkflowId))]
    public List<WorkflowStep> Steps { get; set; }

    /// <summary>
    /// 流转记录
    /// </summary>
    [Navigate(NavigateType.OneToMany, nameof(WorkflowTrace.WorkflowId))]
    public List<WorkflowTrace> Traces { get; set; }

    #region Method

    /// <summary>
    /// 流程结束
    /// </summary>
    public void Complete(WorkflowStep endStep, EReviewResult reviewResult = EReviewResult.Unknown)
    {
        //if (FlowType is EFlowType.Review && !reviewResult.HasValue)
        //    throw new UserFriendlyException("无审核结果");

        Status = EWorkflowStatus.Completed;
        EndTime = DateTime.Now;
        if (FlowType is EFlowType.Review && ReviewResult is EReviewResult.Unknown)
            ReviewResult = reviewResult;



        //ClearHandlers();

        SetAllDuration();

        UpdateActualOption();
    }

    public void Terminate(string opinion)
    {
        Status = EWorkflowStatus.Terminated;
        EndTime = DateTime.Now;
        ActualOpinion = opinion;

        //ClearHandlers();
    }

    /// <summary>
    /// 归档时为最终办理意见赋值
    /// </summary>
    public void UpdateActualOption()
    {
        if (FlowType is EFlowType.Review) return;

        WorkflowStep? step;
        if (Steps.Count == 2
           && Steps.Exists(d => d.StepType == EStepType.Start)
           && Steps.Exists(d => d.StepType == EStepType.End))
        {
            step = Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
        }
        else
        {
            step = Steps.FirstOrDefault(d => d.Id == ActualHandleStepId);
        }
        if (step is null)
            throw new UserFriendlyException($"未查询到对应实际办理子节点，workflowId: {Id}");
        ActualOpinion = step.Opinion;
        ActualHandleStepAcceptTime = step.AcceptTime;
    }

    ///// <summary>
    ///// 更新workflow中实际办理节点数据（节点，时间，部门）
    ///// </summary>
    //public void UpdateWorkflowActualHandleInfo(WorkflowStep currentStep,
    //    string actualHandlerId, string? actualHandlerName,
    //    string actualHandleOrgCode, string? actualHandleOrgName,
    //    string? actualHandleOrgAreaCode, string? actualHandleOrgAreaName,
    //    int currentHandlerOrgLevel)
    //{
    //    /*
    //      a.会签中:记录顶级会签发起节点, 会签结束前不更新。会签结束后再发起会签才会记录下一次会签的顶级发起节点
    //      b.非会签中，记录当前节点
    //    */
    //    if (currentStep.IsInCountersign()) return;

    //    if (currentStep.StepType is EStepType.Summary or EStepType.End) return;

    //    ActualHandle(currentStep,
    //        actualHandlerId, actualHandlerName,
    //        actualHandleOrgCode, actualHandleOrgName,
    //        actualHandleOrgAreaCode, actualHandleOrgAreaName);

    //    //SetHandleDuration();

    //    //实际办理部门为一级部门时记录
    //    if (currentHandlerOrgLevel == 1)
    //        UpdateLevelOneOrg(actualHandleOrgCode, actualHandleOrgName);
    //}

    /// <summary>
    /// 指派、未办理时调用
    /// </summary>
    public void UpdateActualStepWhenAssign(WorkflowStep nextStep, FlowStepHandler nextStepHandler)
    {
        ResetActualStep();
        ActualHandleStepId = nextStep.Id;
        ActualHandleStepCode = nextStep.Code;
        ActualHandleStepName = nextStep.Name;
        ActualHandleStepCreateTime = nextStep.CreationTime;
        ActualHandlerId = nextStepHandler.UserId;
        ActualHandlerName = nextStepHandler.Username;
        ActualHandleOrgCode = nextStepHandler.OrgId;
        ActualHandleOrgName = nextStepHandler.OrgName;
        if (!string.IsNullOrEmpty(ActualHandleOrgCode))
            ActualHandleOrgLevel = ActualHandleOrgCode.CalcOrgLevel();

        //实际办理部门为一级部门时记录
        if (ActualHandleOrgLevel.HasValue && ActualHandleOrgLevel == 1)
            UpdateLevelOneOrg(ActualHandleOrgCode, ActualHandleOrgName);
        
        
    }

    /// <summary>
    /// 办理时调用
    /// </summary>
    public void UpdateActualStepWhenHandle(
        WorkflowStep step,
        string? handleOrgAreaCode,
        string? handleOrgAreaName,
        int handlerOrgLevel)
    {
        //ActualHandleStepAcceptTime = null;
        ActualHandleTime = step.HandleTime;
        ActualHandleOrgAreaCode = handleOrgAreaCode;
        ActualHandleOrgAreaName = handleOrgAreaName;
        ActualHandleOrgLevel = handlerOrgLevel;

        //坐席->派单存在不选办理对象的场景，所以要补赋值
        ActualHandleStepId = step.Id;
        ActualHandleStepCode = step.Code;
        ActualHandleStepName = step.Name;
        ActualHandleStepCreateTime = step.CreationTime;
        ActualHandlerId = step.HandlerId;
        ActualHandlerName = step.HandlerName;
        ActualHandleOrgCode = step.HandlerOrgId;
        ActualHandleOrgName = step.HandlerOrgName;
    }

    /// <summary>
    /// 指派、未办理时调用
    /// </summary>
    public void UpdateCurrentStepWhenAssign(WorkflowStep nextStep, FlowStepHandler nextStepHandler)
    {
        ResetCurrentStep();
        CurrentStepId = nextStep.Id;
        CurrentStepCode = nextStep.Code;
        CurrentStepName = nextStep.Name;
        CurrentStepCreateTime = nextStep.CreationTime;
        CurrentHandlerId = nextStepHandler.UserId;
        CurrentHandlerName = nextStepHandler.Username;
        CurrentHandleOrgId = nextStepHandler.OrgId;
        CurrentHandleOrgName = nextStepHandler.OrgName;
        if (!string.IsNullOrEmpty(CurrentHandleOrgId))
            CurrentHandleOrgLevel = CurrentHandleOrgId.CalcOrgLevel();

        // //实际办理部门为一级部门时记录
        // if (CurrentHandleOrgLevel.HasValue && CurrentHandleOrgLevel == 1)
        //     UpdateLevelOneOrg(CurrentHandleOrgId, CurrentHandleOrgName);
    }

    /// <summary>
    /// 办理时调用
    /// </summary>
    public void UpdateCurrentStepWhenHandle(
        WorkflowStep step,
        string? handleOrgAreaCode,
        string? handleOrgAreaName,
        int handlerOrgLevel)
    {
        //CurrentStepAcceptTime = step.AcceptTime;
        CurrentHandleTime = step.HandleTime;
        CurrentHandleOrgAreaCode = handleOrgAreaCode;
        CurrentHandleOrgAreaName = handleOrgAreaName;
        CurrentHandleOrgLevel ??= handlerOrgLevel;

        //坐席->派单存在不选办理对象的场景，所以要补赋值
        CurrentStepId = step.Id;
        CurrentStepCode = step.Code;
        CurrentStepName = step.Name;
        CurrentStepCreateTime = step.CreationTime;
        CurrentHandlerId = step.HandlerId;
        CurrentHandlerName = step.HandlerName;
        CurrentHandleOrgId = step.HandlerOrgId;
        CurrentHandleOrgName = step.HandlerOrgName;
    }

    private void ResetActualStep()
    {
        ActualHandleStepCode = null;
        ActualHandleStepName = null;
        ActualHandleStepId = null;
        ActualHandleStepCreateTime = null;
        ActualHandleStepAcceptTime = null;
        ActualHandleTime = null;
        ActualHandlerId = null;
        ActualHandlerName = null;
        ActualHandleOrgCode = null;
        ActualHandleOrgName = null;
        ActualHandleOrgAreaCode = null;
        ActualHandleOrgAreaName = null;
    }

    private void ResetCurrentStep()
    {
        CurrentStepId = null;
        CurrentStepCode = null;
        CurrentStepName = null;
        CurrentStepCreateTime = null;
        CurrentStepAcceptTime = null;
        CurrentHandleTime = null;
        CurrentHandlerId = null;
        CurrentHandlerName = null;
        CurrentHandleOrgId = null;
        CurrentHandleOrgName = null;
        CurrentHandleOrgLevel = null;
        CurrentHandleOrgAreaCode = null;
        CurrentHandleOrgAreaName = null;
    }

    /// <summary>
    /// 检查会签是否结束
    /// </summary>
    public bool CheckIfCountersignOver()
    {
        return Countersigns.All(d => d.IsCompleted());
    }

    /// <summary>
    /// 开始会签
    /// </summary>
    public void StartCountersign(string startCsStepId, ECounterSignType? counterSignType)
    {
        IsInCountersign = true;
        TopCountersignStepId = startCsStepId;
        CounterSignType = counterSignType;
    }

    /// <summary>
    /// 结束流程会签状态（保留topStepId创建节点时判断用，直到下次会签开启时更新）
    /// </summary>
    public void EndCountersign()
    {
        IsInCountersign = false;
        //TopCountersignStepId = null;
    }

    /// <summary>
    /// 重置最终办理意见
    /// </summary>
    public void ResetOption() => ActualOpinion = "办理中...";

    /// <summary>
    /// 状态设置为可流转
    /// </summary>
    public void SetStatusRunnable() => Status = EWorkflowStatus.Runnable;

    /// <summary>
    /// 重新设置办理人（删除当前待办人/部门），撤回/跳转场景，因当前办理人不是流程指定办理人
    /// </summary>
    /// <param name="assignType"></param>
    /// <param name="handlerObjects"></param>
    public void ResetHandlers(EFlowAssignType assignType, List<HandlerGroupItem> handlerObjects)
    {
        //ClearHandlers();
        //SetHandlers(assignType, handlerObjects);
    }

    /// <summary>
    /// 清除办理对象
    /// </summary>
    public void ClearHandlers()
    {
        HandlerOrgs = new List<HandlerGroupItem>();
        HandlerUsers = new List<HandlerGroupItem>();
    }

    /// <summary>
    /// 更新当前办理人(待办人或部门)，正常流转场景
    /// </summary>
    public void UpdateHandlers(string handlerId, string handlerOrg, EFlowAssignType assignType,
        List<HandlerGroupItem> handlerObjects, bool isCreateNewStep)
    {
        //RemoveCurrentHandleGroup(handlerId, handlerOrg);
        if (isCreateNewStep)
            SetHandlers(assignType, handlerObjects);
    }

    public void UpdateHandlers(List<string> handlers, EFlowAssignType assignType, List<HandlerGroupItem> handlerObjects)
    {
        foreach (var handler in handlers)
        {
            var orgItem = HandlerOrgs.FirstOrDefault(d => d.Key == handler);
            if (orgItem != null)
            {
                HandlerOrgs.RemoveAll(d => d.GroupId == orgItem.GroupId);
            }

            var userItem = HandlerUsers.FirstOrDefault(d => d.Key == handler);
            if (userItem != null)
            {
                HandlerUsers.RemoveAll(d => d.GroupId == userItem.GroupId);
            }
        }

        SetHandlers(assignType, handlerObjects);
    }

    private void SetHandlers(EFlowAssignType assignType, List<HandlerGroupItem> handlerObjects)
    {
        switch (assignType)
        {
            case EFlowAssignType.Org:
                HandlerOrgs.AddRange(handlerObjects);
                HandlerOrgs = HandlerOrgs.Distinct().ToList();
                break;
            case EFlowAssignType.User:
            case EFlowAssignType.Role:
                HandlerUsers.AddRange(handlerObjects);
                HandlerUsers = HandlerUsers.Distinct().ToList();
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(assignType), assignType, null);
        }
    }

    /// <summary>
    /// 更新当前办理人（逐级退回场景）
    /// </summary>
    /// <param name="handlerId"></param>
    /// <param name="handlerOrg"></param>
    /// <param name="prevStep"></param>
    public void UpdatePreviousHandlers(string handlerId, string handlerOrg, WorkflowStep prevStep)
    {
        //RemoveCurrentHandleGroup(handlerId, handlerOrg);

        var groupId = Guid.NewGuid().ToString();
        var handlerObjects = new HandlerGroupItem
        {
            GroupId = groupId,
            Key = prevStep.HandlerId,
            Value = prevStep.HandlerName
        };
        HandlerUsers.Add(handlerObjects);
        HandlerUsers = HandlerUsers.Distinct().ToList();

        //switch (prevStep.HandlerType)
        //{
        //    case EHandlerType.OrgLevel:
        //    case EHandlerType.OrgType:
        //    case EHandlerType.AssignedOrg:
        //        HandlerOrgs.AddRange(handlerObjects);
        //        HandlerOrgs = HandlerOrgs.Distinct().ToList();
        //        break;
        //    case EHandlerType.Role:
        //    case EHandlerType.AssignedUser:
        //        HandlerUsers.AddRange(handlerObjects);
        //        HandlerUsers = HandlerUsers.Distinct().ToList();
        //        break;
        //    default:
        //        throw new ArgumentOutOfRangeException();
        //}
    }

    /// <summary>
    /// 当前用户是否可以办理该流程
    /// </summary>
    /// <returns></returns>
    public bool IsCanHandle(string userId, string orgId, string[] roleIds)
    {
        if (Steps is null || !Steps.Any())
            throw new UserFriendlyException("未查询节点信息");
        return Status is EWorkflowStatus.Runnable &&
               //(HandlerUsers.Any(d => d.Key == userId) || HandlerOrgs.Any(d => d.Key == orgCode));
               Steps.Any(d => d.IsCanHandle(userId, orgId, roleIds));
    }

    private void RemoveCurrentHandleGroup(string handlerId, string handlerOrg)
    {
        if (string.IsNullOrEmpty(handlerId) && string.IsNullOrEmpty(handlerOrg))
            throw new UserFriendlyException($"{nameof(RemoveCurrentHandleGroup)}, 办理对象参数为空");
        var orgItem = HandlerOrgs.FirstOrDefault(d => d.Key == handlerOrg);
        if (orgItem != null)
        {
            HandlerOrgs.RemoveAll(d => d.GroupId == orgItem.GroupId);
        }

        var userItem = HandlerUsers.FirstOrDefault(d => d.Key == handlerId);
        if (userItem != null)
        {
            HandlerUsers.RemoveAll(d => d.GroupId == userItem.GroupId);
        }
    }

    public void Assign(EFlowAssignType type, string handler)
    {
        handler = handler.ToLower();
        switch (type)
        {
            case EFlowAssignType.Org:
                var orgCodes = handler.GetHigherOrgIds(true).ToList();
                FlowedOrgIds.AddRange(orgCodes);
                FlowedOrgIds = FlowedOrgIds.Distinct().ToList();
                break;
            case EFlowAssignType.User:
            case EFlowAssignType.Role:
                if (!FlowedUserIds.Exists(d => d == handler))
                    FlowedUserIds.Add(handler);
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
        }
    }

    public void Assign(EFlowAssignType type, IEnumerable<string> handlers)
    {
        if (!handlers.Any()) return;
        FlowedUserIds ??= new();
        FlowedOrgIds ??= new();
        handlers = handlers.Select(d => d.ToLower());
        switch (type)
        {
            case EFlowAssignType.Org:
                var orgCodes = handlers.SelectMany(d => d.GetHigherOrgIds(true)).ToList();
                FlowedOrgIds.AddRange(orgCodes);
                FlowedOrgIds = FlowedOrgIds.Distinct().ToList();
                break;
            case EFlowAssignType.User:
            case EFlowAssignType.Role:
                FlowedUserIds.AddRange(handlers);
                FlowedUserIds = FlowedUserIds.Distinct().ToList();
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
        }
    }

    /// <summary>
    /// 更新受理人信息
    /// </summary>
    public void UpdateAcceptor(string userId, string? userName, string? staffNo, string orgId, string? orgName)
    {
        AcceptorId = userId;
        AcceptorName = userName;
        AcceptorStaffNo = staffNo;
        AcceptorOrgId = orgId;
        AcceptorOrgName = orgName;
    }

    /// <summary>
    /// 更新一级部门信息（实际办理部门为一级部门时记录）
    /// </summary>
    public void UpdateLevelOneOrg(string orgId, string? orgName)
    {
        OrgLevelOneCode = orgId;
        OrgLevelOneName = orgName;
    }

    public void Redo()
    {
        ResetOption();
        Status = EWorkflowStatus.Runnable;
    }

    public void SetAllDuration()
    {
        if (!EndTime.HasValue)
            throw new ArgumentNullException($"{EndTime} is null");
        AllDuration = Math.Round((EndTime - CreationTime).Value.TotalSeconds);
    }

    public bool IsReviewPass() => FlowType == EFlowType.Review && ReviewResult == EReviewResult.Approval;

    public bool IsReviewType() => FlowType == EFlowType.Review;

    /// <summary>
    /// 查询实际办理节点
    /// </summary>
    /// <returns></returns>
    public WorkflowStep? GetActualStep() => Steps.FirstOrDefault(d => d.Id == ActualHandleStepId);

    public void AddCsActualHandler(string userId, string orgId)
    {
        CsActualHandleUserIds ??= new();
        if (CsActualHandleUserIds.All(d => d != userId))
            CsActualHandleUserIds.Add(userId);

        CsActualHandleOrgIds ??= new();
        if (CsActualHandleOrgIds.All(d => d != orgId))
            CsActualHandleOrgIds.Add(orgId);
    }

    public bool IsTopCountersignEndStep(StepBasicEntity step)
    {
        // if (string.IsNullOrEmpty(TopCountersignStepId))
        //     throw new UserFriendlyException("该流程当前未开启会签");
        return step.IsCountersignEndStep 
               && !string.IsNullOrEmpty(TopCountersignStepId)
               && step.CountersignStartStepId == TopCountersignStepId;
    }

    #endregion
}

/*
 1. 弃用 workflow, order 上的 handlerUserIds, flowUserIds
 2. 弃用 step, trace 上的handlers
 3. 统一封装创建step, 复制step，指派类型及办理对象开放参数，依据3种策略进行创建
 4. 重构recall，重构recallDto(domain层传入指派信息dto), 取消session传入
 */