using Hotline.FlowEngine.Definitions;
using Hotline.FlowEngine.WorkflowModules;
using Hotline.Settings;
using Hotline.Share.Dtos;
using Hotline.Share.Dtos.File;
using Hotline.Share.Dtos.FlowEngine;
using Hotline.Share.Dtos.FlowEngine.Workflow;
using Hotline.Share.Enums.FlowEngine;
using Hotline.Share.Enums.Settings;
using Hotline.Users;
using XF.Domain.Authentications;
using XF.Domain.Entities;

namespace Hotline.FlowEngine.Workflows
{
    public interface IWorkflowDomainService
    {
        /// <summary>
        /// 创建流程
        /// </summary>
        Task<Workflow> CreateWorkflowAsync(WorkflowModule wfModule, string title, string userId, string orgId,
            string? externalId = null, CancellationToken cancellationToken = default);

        // /// <summary>
        // /// 进行流程的开始节点
        // /// </summary>
        // Task StartAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto, StepDefine firstStepDefine,
        //     bool isNextDynamic, FlowAssignInfo flowAssignInfo, ECounterSignType? counterSignType, DateTime? expiredTime,
        //     CancellationToken cancellationToken);

        /// <summary>
        /// new 
        /// </summary>
        Task<(Workflow, WorkflowStep)> StartAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep>? newStepConfig = null,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// new
        /// </summary>
        Task<(Workflow, WorkflowStep, StepDefine, List<WorkflowStep>)> NextAsync(
            NextWorkflowDto dto,
            EHandleMode handleMode = EHandleMode.Normal,
            DateTime? expiredTime = null, bool isAutoFillSummaryOpinion = false,
            Action<Workflow, WorkflowStep, StepDefine>? currentStepConfig = null,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep>? newStepConfig = null,
            CancellationToken cancellationToken = default);

        Task<(Workflow, WorkflowStep, StepDefine, List<WorkflowStep>)> NextAsync(
            Workflow workflow,
            NextWorkflowDto dto,
            EHandleMode handleMode = EHandleMode.Normal,
            DateTime? expiredTime = null, bool isAutoFillSummaryOpinion = false,
            Action<Workflow, WorkflowStep, StepDefine>? currentStepConfig = null,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep>? newStepConfig = null,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 开启流程并办理至第一个节点
        /// </summary>
        Task<List<WorkflowStep>> StartToFirstStepAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep>? newStepConfig = null,
            CancellationToken cancellationToken = default);


        /// <summary>
        /// 开启流程直接归档
        /// </summary>
        Task StartToEndAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
            CancellationToken cancellationToken = default);


        /// <summary>
        /// 查询工作流
        /// </summary>
        Task<Workflow> GetWorkflowAsync(string workflowId, bool withDefine = false, bool withSteps = false,
            bool withTraces = false, bool withTracesTree = false, bool withSupplements = false,
            bool withCountersigns = false, CancellationToken cancellationToken = default);

        /// <summary>
        /// 查询工作流包含当前用户办理权限（是否可办理）
        /// </summary>
        Task<(Workflow Workflow, string? CountersignId, bool CanHandle, bool CanPrevious, WorkflowTrace? Trace)> GetWorkflowHandlePermissionAsync(
            string workflowId, string userId, string orgId, string[] roleIds, CancellationToken cancellationToken = default);

        /// <summary>
        /// 受理,接办
        /// </summary>
        Task<DateTime?> AcceptAsync(Workflow workflow, string userId, string? userName, string orgId, string? orgName,
            string? orgAreaCode, string? orgAreaName, CancellationToken cancellationToken);

        ///// <summary>
        ///// 办理（流转至下一节点）
        ///// </summary>
        //Task NextAsync(Workflow workflow, WorkflowStep currentStep, NextWorkflowDto dto, StepDefine nextStepDefine,
        //    bool isNextDynamic, FlowAssignInfo flowAssignInfo, DateTime? expiredTime, CancellationToken cancellationToken);

        // /// <summary>
        // /// 退回（返回前一节点）
        // /// </summary>
        // /// <returns></returns>
        // Task<EFlowDirection> PreviousAsync(Workflow workflow, PreviousWorkflowDto dto,
        //     string applicantId, string applicantName,
        //     string applicantOrgId, string applicantOrgName,
        //     string applicantOrgAreaCode, string applicantOrgAreaName,
        //     bool applicantIsCenter, string[] applicantRoleIds,
        //     CancellationToken cancellationToken);

        /// <summary>
        /// 退回（new）
        /// </summary>
        Task<(Workflow workflow, WorkflowStep currentStep, StepDefine prevDefine,
                WorkflowStep prevStep, WorkflowStep newStep, EFlowDirection flowDirection)> PreviousAsync
            (Workflow workflow, PreviousWorkflowDto dto, OperatorInfo operatorInfo,
                EHandleMode handleMode = EHandleMode.Previous,
                Action<Workflow, WorkflowStep, StepDefine, WorkflowStep, WorkflowStep>? newStepConfig = null,
                CancellationToken cancellationToken = default);

        /// <summary>
        /// 退回
        /// </summary>
        Task<(Workflow workflow, WorkflowStep currentStep, StepDefine prevDefine,
                WorkflowStep prevStep, WorkflowStep newStep, EFlowDirection flowDirection)>
            PreviousAsync(PreviousWorkflowDto dto,
                EHandleMode handleMode = EHandleMode.Previous,
                Action<Workflow, WorkflowStep, StepDefine, WorkflowStep, WorkflowStep>? newStepConfig = null,
                CancellationToken cancellationToken = default);

        /// <summary>
        /// 撤回（返回到之前任意节点）
        /// </summary>
        Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
            RecallDto dto, StepAssignInfo stepAssignInfo,
            EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep, WorkflowStep>? newStepConfig = null,
            CancellationToken cancellationToken = default);

        Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
            Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
            StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep, WorkflowStep>? newStepConfig = null,
            CancellationToken cancellationToken = default);

        Task<(Workflow, StepDefine, WorkflowStep, WorkflowStep, WorkflowStep, bool)> RecallAsync(
            Workflow workflow, BasicWorkflowDto dto, StepAssignInfo stepAssignInfo,
            WorkflowStep targetStep, EWorkflowTraceType traceType,
            DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep, WorkflowStep>? newStepConfig = null,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 撤回至开始节点
        /// </summary>
        Task RecallToStartStepAsync(string workflowId, string opinion, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
    EFlowAssignType? flowAssignType = EFlowAssignType.Role, CancellationToken cancellationToken = default);

        Task RecallToStartStepAsync(Workflow workflow, string opinion, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
            EFlowAssignType? flowAssignType = EFlowAssignType.Role, CancellationToken cancellationToken = default);

        /// <summary>
        /// 特提至派单节点（无派单节点会抛异常）
        /// </summary>
        Task RecallToSendStepAsync(Workflow workflow, string opinion, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
            EFlowAssignType? flowAssignType = EFlowAssignType.Role, CancellationToken cancellationToken = default);

        /// <summary>
        /// 特提至中心（优先派单组其次坐席）
        /// </summary>
        /// <returns></returns>
        Task<(bool, Workflow workflow)> RecallToCenterFirstToSendAsync(string workflowId, string opinion,
            bool isOrderFiled, DateTime? expiredTime, EHandleMode handleMode, EFlowAssignType? flowAssignType = EFlowAssignType.User,
            CancellationToken cancellationToken = default);

        ///// <summary>
        ///// 否决（审批流程不通过）
        ///// </summary>
        ///// <returns></returns>
        //Task RejectAsync(Workflow workflow, BasicWorkflowDto dto, CancellationToken cancellationToken);
        Task RejectAsync(RejectDto dto, CancellationToken cancellationToken);

        /// <summary>
        /// 补充
        /// </summary>
        /// <returns></returns>
        Task SupplementAsync(Workflow workflow, EndWorkflowDto dto, CancellationToken cancellationToken);

        /// <summary>
        /// 终止流程
        /// </summary>
        Task TerminateAsync(TerminateDto dto, CancellationToken cancellationToken);

        /// <summary>
        /// 结束流程（流程直接流转至结束节点）
        /// </summary>
        Task<(WorkflowStep, WorkflowTrace)> EndAsync(ISessionContext current, Workflow workflow, BasicWorkflowDto dto, StepDefine endStepDefine,
            WorkflowStep currentStep, DateTime? expiredTime, CancellationToken cancellationToken);

        StepDefine GetStepDefine(WorkflowDefinition workflowDefinition, string stepCode);

        /// <summary>
        /// 查询当前待办理节点
        /// </summary>
        WorkflowStep FindCurrentStepWaitForHandle(Workflow workflow, string userId, string orgId, string[] roleIds);

        /// <summary>
        /// 查询当前节点中最后一个节点
        /// </summary>
        Task<WorkflowStep?> FindLastStepAsync(string workflowId, CancellationToken cancellationToken);

        /// <summary>
        /// 查询所有办理部门及实际办理部门
        /// </summary>
        Task<(Kv, IReadOnlyList<Kv>)> GetHandleOrgsAsync(string workflowId, CancellationToken cancellationToken);

        /// <summary>
        /// 新增流程流转记录
        /// </summary>
        Task AddStepsAsync(string workflowId, List<WorkflowStep> steps, CancellationToken cancellationToken);

        /// <summary>
        /// 创建开始节点
        /// </summary>
        WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto, UserInfo assigner,
            StepAssignInfo handler, DateTime? expiredTime, //EFlowAssignType? flowAssignType = EFlowAssignType.User,
            Action<Workflow, WorkflowStep, StepDefine, WorkflowStep>? newStepConfig = null);

        /// <summary>
        /// 查询未完成节点
        /// </summary>
        /// <param name="steps"></param>
        /// <param name="orgId"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        WorkflowStep GetUnHandleStep(List<WorkflowStep> steps, string orgId, string userId, string[] roleIds);

        /// <summary>
        /// 检查当前办理节点是否为开始节点
        /// </summary>
        /// <param name="workflowId"></param>
        /// <param name="userId">当前办理人Id</param>
        /// <param name="orgId">当前办理人orgId</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> CheckCurrentIsStartStepAsync(string workflowId, string userId, string orgId,
            CancellationToken cancellationToken);

        /// <summary>
        /// 检查动态节点是否该终止
        /// </summary>
        bool DynamicShouldTerminal(StepDefine currentStepDefine, int currentOrgLevel);

        /// <summary>
        /// 终止会签
        /// </summary>
        /// <param name="countersignId"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<Workflow> TerminalCountersignAsync(string countersignId, DateTime expireTime, CancellationToken cancellationToken);

        Task<Workflow> TerminalCountersignAsync(WorkflowCountersign countersign, DateTime expireTime, CancellationToken cancellationToken);

        /// <summary>
        /// 办理节点
        /// </summary>
        Task HandleStepAsync(WorkflowStep step, Workflow workflow, BasicWorkflowDto dto,
            ECounterSignType? counterSignType, DateTime? expiredTime, EHandleMode handleMode,
            CancellationToken cancellationToken);

        /// <summary>
        /// 获取会签类型
        /// </summary>
        ECounterSignType? GetCounterSignType(bool isStartCountersign, EBusinessType currentStepBusinessType);

        /// <summary>
        /// 查询退回节点信息
        /// </summary>
        (WorkflowStep currentStep, WorkflowStep prevStep, WorkflowStep? countersignStartStep) GetPreviousStep(
            Workflow workflow, string operaterId, string operaterOrgId, string[] roleIds);

        /// <summary>
        /// 查询派单池中流程节点id
        /// </summary>
        Task<IReadOnlyList<string>> GetUnhandleStepIdsFromSendPoolAsync(string sendPoolId, CancellationToken cancellationToken);

        /// <summary>
        /// 查询归属某用户的所有流程节点
        /// </summary>
        Task<List<WorkflowStep>> GetStepsBelongsToAsync(string userId, CancellationToken cancellationToken);



		/// <summary>
		/// 查询归属多个用户的所有流程节点 当天
		/// </summary>
		/// <returns></returns>
		Task<List<WorkflowStep>> GetStepsBelongsDayToAsync(List<string> userIds, DateTime time, CancellationToken cancellationToken);

        /// <summary>
        /// 批量修改工单办理对象
        /// </summary>
        Task ChangeHandlerBatchAsync(
            IReadOnlyList<(string userId, string username, string orgId, string orgName, string? roleId, string? roleName, ICollection<WorkflowStep>
                steps)> handlers,
            CancellationToken cancellationToken);

        /// <summary>
        /// 查询工单办理中的一级部门
        /// </summary>
        Task<ICollection<Kv>> GetLevelOneOrgsAsync(string workflowId, CancellationToken cancellation);

        /// <summary>
        /// 更新未办理节点的期满时间
        /// </summary>
        Task UpdateUnhandleExpiredTimeAsync(string workflowId, DateTime? expiredTime, CancellationToken cancellation);

        /// <summary>
        /// 查询该部门最后办理节点
        /// </summary>
        /// <returns></returns>
        Task<WorkflowStep> FindLastHandleStepAsync(string workflowId, string orgId, CancellationToken cancellation);

        /// <summary>
        /// 部门会签工单获取流程最顶级办理节点
        /// </summary>
        /// <returns></returns>
        Task<WorkflowStep> FindTopHandleStepAsync(string workflowId, CancellationToken cancellation);

        /// <summary>
        /// 查询流转方向
        /// </summary>
        EFlowDirection GetFlowDirection(EBusinessType sourceStepBusinessType, EBusinessType directionStepBusinessType);

        /// <summary>
        /// 流程被签收至某个用户（更新流转对象，办理对象，节点办理对象以及stepHandlers）
        /// </summary>
        Task<Workflow> SignToSomebodyAsync(string workflowId, string userId, string username, string orgId, string orgName,
            CancellationToken cancellationToken);

        /// <summary>
        /// 非节点办理人员查询待办节点
        /// </summary>
        /// <returns></returns>
        Task<ICollection<WorkflowStep>> GetUnhandleStepsByOthersAsync(string workflowId, CancellationToken cancellationToken);

        /// <summary>
        /// 根据汇总对象id找到被汇总节点,生成指派到用户的办理对象
        /// </summary>
        StepAssignInfo GetSummaryTargetFlowStepHandler(Workflow workflow, string summaryTargetStepCode);

        /// <summary>
        /// 追加归档信息（接收ds推送12315归档信息）
        /// </summary>
        Task AppendFileOpinionAsync(string workflowId, string opinion, List<FileDto> files, CancellationToken cancellationToken);

        /// <summary>
        /// 跳转至结束节点(无视流程模板配置以及当前办理对象，直接跳至结束节点)
        /// </summary>
        Task JumpToEndAsync(ISessionContext current, string workflowId, string opinion, List<FileDto> files, DateTime? expiredTime,
            EReviewResult reviewResult = EReviewResult.Unknown, CancellationToken cancellationToken = default);

        Task JumpToEndAsync(ISessionContext current, Workflow workflow, string opinion, List<FileDto> files, DateTime? expiredTime,
            EReviewResult reviewResult = EReviewResult.Unknown, CancellationToken cancellationToken = default);

        /// <summary>
        /// 查找会签循环的初始会签发起节点
        /// </summary>
        WorkflowStep GetCsLoopStartStep(List<WorkflowStep> steps, WorkflowStep currentStep);

        Task HandlePublishTraceAsync(string workflowId, string orderPublishId, UserInfo acceptor, UserInfo handler, DateTime handleTime,
            UserInfo visitAcceptor, string orderVisitId, CancellationToken cancellation);

        Task HandleVisitTraceAsync(string orderVisitId, UserInfo visitor, DateTime visitTime, CancellationToken cancellation);

        Task<FlowAssignInfo> GetNextStepFlowAssignInfoByDefineAsync(StepDefine nextStepDefine,
            EHandlerType handlerType, bool isStartCountersign, List<Kv> handlers, CancellationToken cancellationToken);
    }
}