using Microsoft.AspNetCore.Http;
using NetTopologySuite.Operation.Distance;
using OpenAuth.App.BaseApp.Base;
using OpenAuth.App.Interface;
using OpenAuth.Repository;
using OpenAuth.Repository.Domain;
using OpenAuth.Repository.Domain.workflow;
using OpenAuth.WebApi.Controllers.ServerController;
using SqlSugar;

namespace OpenAuth.App.workflow;

/// <summary>
/// 完整工作流引擎（适配：区县→执法监督科→5个审核科会签→汇总归档/退回）
/// 包含：流程发起/处理 + 拟办/待办/已办/未办结/已完成/全部事项查询
/// </summary>
public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext>
{
    private readonly ISqlSugarClient _sqlSugar;

    private readonly BusinessNoGenerator _businessNoGenerator;


    public WorkflowEngineApp(ISugarUnitOfWork<SugarDbContext> unitWork, ISimpleClient<SysCategoryType> repository,
        IAuth auth, BusinessNoGenerator businessNoGenerator) : base(unitWork, repository, auth)
    {
        _sqlSugar = Repository.AsSugarClient();
        _businessNoGenerator = businessNoGenerator;
    }

    #region 一、核心业务：流程发起/处理

    /// <summary>
    /// 发起流程（区县提交→流转至执法监督科）
    /// </summary>
    /// <param name="userId">发起人ID</param>
    /// <param name="userName">发起人姓名</param>
    /// <param name="requestDto">发起流程请求参数</param>
    /// <returns>流程实例ID</returns>
    public long InitiateFlow(long userId, string userName, InitiateFlowRequestDto requestDto)
    {
        // 参数校验
        /*if (string.IsNullOrEmpty(requestDto.FlowCode) || string.IsNullOrEmpty(requestDto.BusinessNo))
            throw new Exception("流程编码和业务编号不能为空");*/
        if (userId <= 0 || string.IsNullOrEmpty(userName))
            throw new Exception("发起人ID和姓名不能为空");
        var instanceId = 0L;
        try
        {
            // 开启事务（基于UnitWork，保障数据一致性）
            UnitWork.Db.Ado.BeginTran();
            // 步骤1：查询启用的流程模板（违法建设认定流程）
            var template = _sqlSugar.Queryable<ZyFlowTemplate>()
                .Where(t => t.FlowCode == requestDto.FlowCode && t.IsEnabled == true)
                .First();
            if (template == null)
                throw new Exception($"流程模板【{requestDto.FlowCode}】不存在或未启用");

            var startNode = _sqlSugar.Queryable<ZyFlowNode>()
                .Where(n => n.TemplateId == template.TemplateId && n.NodeType == "Start" && n.NodeName == "区县提交")
                .First();
            if (startNode == null)
                throw new Exception("流程开始节点【区县提交】不存在，请配置节点");
            var attachmentPaths = string.Join(",", requestDto.Attachments);


            if (_sqlSugar
                .Queryable<IllegalConstructionAssessment>()
                .Any(a => a.BusinessNumber == requestDto.BusinessNo))
            {
                var illegalUpdate = new IllegalConstructionAssessment()
                {
                    Id = requestDto.BusinessNo,
                    UpdateTime = DateTime.Now,
                    Status = "Submitted"
                };
                _sqlSugar.Updateable(illegalUpdate).IgnoreColumns().ExecuteCommand();
                var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
                    .Where(a => a.BusinessNo == requestDto.BusinessNo).First();
                instanceId = flowInstance.InstanceId;
                var flowInstanceUpdate = new ZyFlowInstance()
                {
                    InstanceId = instanceId,
                    Status = "Submitted",
                };
                _sqlSugar.Updateable(flowInstanceUpdate).IgnoreColumns().ExecuteCommand();
                var flowWorkItem = _sqlSugar.Queryable<ZyFlowWorkitem>()
                    .Where(a => a.InstanceId == instanceId
                                && a.NodeId == startNode.NodeId
                                && a.Status == "Draft").First();
                if (flowWorkItem == null)
                {
                    throw new Exception("流程工作项不存在");
                }

                var flowWorkItemUpdate = new ZyFlowWorkitem()
                {
                    WorkitemId = flowWorkItem.WorkitemId,
                    Status = "Done",
                    HandleTime = DateTime.Now,
                    Comment = "区县提交",
                };
                _sqlSugar.Updateable(flowWorkItemUpdate).IgnoreColumns().ExecuteCommand();
            }
            else
            {
                var illegal = new IllegalConstructionAssessment()
                {
                    Id = requestDto.BusinessNo,
                    Title = requestDto.Title,
                    BusinessNumber = requestDto.BusinessNo,
                    Attachments = attachmentPaths,
                    CreateTime = DateTime.Now,
                    CreateUser = userName,
                    UpdateTime = DateTime.Now,
                };
                _sqlSugar.Insertable(illegal).ExecuteCommand();

                // 步骤2：查询流程开始节点（区县提交）
                var prefix = "wfjszl";
                var businessNo = _businessNoGenerator.GenerateBusinessNo(prefix);
                requestDto.BusinessNo = businessNo;
                // 步骤3：插入流程实例，返回自增主键
                var flowInstance = new ZyFlowInstance
                {
                    TemplateId = template.TemplateId,
                    FlowCode = template.FlowCode,
                    BusinessNo = requestDto.BusinessNo,
                    Status = "Submitted", // 已提交
                    CurrentNodeId = startNode.NodeId,
                    InitiatorId = userId,
                    InitiatorName = userName,
                    CreateTime = DateTime.Now
                };
                instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
                // 步骤4：插入开始节点工作项（直接标记为已完成）
                // 开始节点无ToDo
                var startWorkitem = new ZyFlowWorkitem
                {
                    InstanceId = instanceId,
                    NodeId = startNode.NodeId,
                    NodeName = startNode.NodeName,
                    HandlerId = userId,
                    HandlerName = userName,
                    Status = "Done", // 已完成
                    ReceiveTime = DateTime.Now,
                    HandleTime = DateTime.Now,
                    Comment = "区县提交业务材料，流程发起成功"
                };
                _sqlSugar.Insertable(startWorkitem).ExecuteCommand();

                // 步骤5：保存流程变量（标题、附件路径等）
                //var attachmentPaths = SaveAttachments(requestDto.Attachments);
            }

            var flowVariables = new List<ZyFlowVariable>
            {
                new() { InstanceId = instanceId, VarKey = "Title", VarValue = requestDto.Title },
                new() { InstanceId = instanceId, VarKey = "AttachmentPaths", VarValue = attachmentPaths },
                new()
                {
                    InstanceId = instanceId, VarKey = "SubmitTime",
                    VarValue = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                },
                new() { InstanceId = instanceId, VarKey = "Type", VarValue = requestDto.type.ToString() },
            };
            _sqlSugar.Insertable(flowVariables).ExecuteCommand();

            // 步骤6：核心流转：从区县提交节点流转至执法监督科节点
            FlowToNextNode(instanceId, startNode, userId, userName, "区县提交完成，流转至执法监督科");

            // 提交事务
            UnitWork.Db.Ado.CommitTran();
        }
        catch (Exception ex)
        {
            // 回滚事务
            UnitWork.Db.Ado.RollbackTran();
            throw new Exception($"发起流程失败：{ex.Message}", ex);
        }

        return instanceId;
    }

    /// <summary>
    /// 处理工作项（执法监督科转发/审核科会签/汇总处理）
    /// </summary>
    /// <param name="userId">处理人ID</param>
    /// <param name="userName">处理人姓名</param>
    /// <param name="requestDto">处理工作项请求参数</param>
    /// <returns>处理结果（成功/失败）</returns>
    public bool HandleWorkitem(long userId, string userName, HandleWorkitemRequestDto requestDto)
    {
        // 参数校验
        if (requestDto.WorkitemId <= 0)
            throw new Exception("工作项ID无效");
        if (userId <= 0 || string.IsNullOrEmpty(userName))
            throw new Exception("处理人ID和姓名不能为空");

        try
        {
            // 开启事务
            UnitWork.Db.Ado.BeginTran();

            // 步骤1：查询待处理的工作项（仅待办状态可处理）
            var workitem = _sqlSugar.Queryable<ZyFlowWorkitem>()
                .Where(w => w.WorkitemId == requestDto.WorkitemId && w.Status == "ToDo")
                .First();
            if (workitem == null)
                throw new Exception("工作项不存在、已处理或状态异常");

            // 步骤2：查询关联的流程实例和当前节点
            var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
                .Where(i => i.InstanceId == workitem.InstanceId)
                .First();
            var currentNode = _sqlSugar.Queryable<ZyFlowNode>()
                .Where(n => n.NodeId == workitem.NodeId)
                .First();
            if (flowInstance == null || currentNode == null)
                throw new Exception("流程实例或流程节点不存在");

            // 步骤3：更新当前工作项为已完成
            workitem.Status = "Done";
            workitem.HandleTime = DateTime.Now;
            workitem.Comment = string.IsNullOrEmpty(requestDto.Comment) ? "处理完成" : requestDto.Comment;
            _sqlSugar.Updateable(workitem).ExecuteCommand();

            // 生成下一节点数据
            // 步骤4：按节点类型分支处理核心逻辑
            switch (currentNode.NodeType)
            {
                // 普通节点：执法监督科转发
                //case "Common" when currentNode.NodeName == "执法监督科转发":
                case "Common":
                    FlowToNextNode(flowInstance.InstanceId, currentNode, userId, userName, workitem.Comment);
                    break;

                case "Parallel":
                    ProcessParallelAudit(flowInstance.InstanceId, currentNode.NodeId, userId, userName, requestDto);
                    var nextNodeId = long.Parse(currentNode.NextNodeIds.Split(',')[0]);
                    var hasNextWorkItem = _sqlSugar.Queryable<ZyFlowWorkitem>()
                        .Where(w => w.InstanceId == flowInstance.InstanceId
                                    && w.Status == "ToDo"
                                    && w.NodeId == nextNodeId).First();
                    if (hasNextWorkItem != null)
                    {
                        var nextNode = _sqlSugar.Queryable<ZyFlowNode>()
                            .Where(a => a.NodeId == nextNodeId).First();
                        // 更新脚本节点
                        var scriptNodeWorkItem = new ZyFlowWorkitem()
                        {
                            WorkitemId = hasNextWorkItem.WorkitemId,
                            Status = "Done"
                        };
                        _sqlSugar.Updateable(scriptNodeWorkItem).ExecuteCommand();
                        ProcessSummaryNode(flowInstance, nextNode, userId, userName);
                    }
                    break;
                // 分支节点：汇总（归档/退回区县）
                case "Branch" when currentNode.NodeName == "汇总判断":
                    ProcessSummaryNode(flowInstance, currentNode, userId, userName);
                    break;

                // 结束节点：流程归档完成
                case "End":
                    CompleteFlowInstance(flowInstance);
                    break;
            }

            // 提交事务
            UnitWork.Db.Ado.CommitTran();
            return true;
        }
        catch (Exception ex)
        {
            // 回滚事务
            UnitWork.Db.Ado.RollbackTran();
            throw new Exception($"处理工作项失败：{ex.Message}", ex);
        }
    }

    #endregion

    #region 二、完整查询：拟办/待办/已办/未办结/已完成/全部事项

    /// <summary>
    /// 我的拟办（未认领/待分配给当前用户的事项）
    /// </summary>
    /// <param name="userId">当前用户ID</param>
    /// <param name="pageQueryDto">分页参数</param>
    /// <returns>分页结果</returns>
    public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyDraft(long userId, PageQueryRequestDto pageQueryDto)
    {
        // 参数初始化
        if (userId <= 0)
            return new PageQueryResultDto<FlowQuerySingleResultDto>();
        pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
        var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
        var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;

        // 拟办不应该是针对个人的吗？
        // 拟办逻辑：工作项状态为"Draft"（拟办）、对应角色匹配当前用户、未分配具体处理人
        var draftQuery = _sqlSugar
            .Queryable<IllegalConstructionAssessment>()
            .Where(w => w.Status == "Draft" && w.CreateUserId == userId)
            .OrderByDescending(w => w.ReceiveTime);

        // 分页查询
        var totalCount = draftQuery.Count();
        var draftWorkitems = draftQuery
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToList();

        // 组装返回结果
        var dataList = new List<FlowQuerySingleResultDto>();
        foreach (var workitem in draftWorkitems)
        {
            dataList.Add(new FlowQuerySingleResultDto
            {
                //InstanceId = flowInstance.InstanceId,
                BusinessNo = workitem.BusinessNumber,
                Title = workitem.Title,
                //NodeName = workitem.NodeName,
                Status = "Draft", // 拟办状态
                CreateTime = workitem.CreateTime,
                //InitiatorName = workitem.CreateUser //发起人姓名
            });
        }

        return new PageQueryResultDto<FlowQuerySingleResultDto>
        {
            Page = pageIndex,
            Limit = pageSize,
            Total = totalCount,
            TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
            Items = dataList
        };
    }

    /// <summary>
    /// 我的待办（已分配给当前用户、待处理的事项）
    /// </summary>
    /// <param name="userId">当前用户ID</param>
    /// <param name="pageQueryDto">分页参数</param>
    /// <returns>分页结果</returns>
    public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyToDo(long userId, PageQueryRequestDto pageQueryDto)
    {
        // 参数初始化
        if (userId <= 0)
            return new PageQueryResultDto<FlowQuerySingleResultDto>();
        pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
        var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
        var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;
        // 待办逻辑：工作项状态为"ToDo"、处理人ID为当前用户
        var nodeIdList = _sqlSugar.Queryable<ZyFlowNode>()
            // 核心：In(主表字段, 子查询Lambda表达式)
            .In(
                zy => zy.RoleId, // 主表 zy_flow_node 的 role_id 字段
                // 子查询：从 sys_userrole 中查询 UserId=2 的 RoleId
                _sqlSugar.Queryable<SysUserRole>()
                    .Where(ur => ur.UserId == userId) // 条件：UserId=2（注意：这里直接用数值，避免字符串拼接）
                    .Select(ur => ur.RoleId) // 子查询只返回 RoleId 字段
            )
            // 主查询只返回 node_id 字段（提升查询性能，避免查询全表字段）
            .Select(zy => zy.NodeId)
            // 执行查询，返回 List<long> 结果
            .ToList();
        var toDoQuery = _sqlSugar
            .Queryable<ZyFlowWorkitem>()
            .LeftJoin<ZyFlowNode>((w, n) => w.NodeId == n.NodeId)
            .Where((w, n) => nodeIdList.Contains(w.NodeId) && w.Status == "ToDo")
            .Where((w, n) => w.HandlerId == null || w.HandlerId == userId)
            .OrderByDescending(w => w.ReceiveTime);
        // 分页查询
        var totalCount = toDoQuery.Count();
        var toDoWorkitems = toDoQuery
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToList();

        // 组装返回结果
        var dataList = new List<FlowQuerySingleResultDto>();
        foreach (var workitem in toDoWorkitems)
        {
            var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
                .Where(i => i.InstanceId == workitem.InstanceId)
                .First();
            if (flowInstance == null)
                continue;

            var zyflowVarList = _sqlSugar.Queryable<ZyFlowVariable>()
                .Where(v => v.InstanceId == flowInstance.InstanceId);

            var flowTitle = zyflowVarList.Where(v => v.VarKey == "Title").First()?.VarValue;
            var type = zyflowVarList.Where(v => v.VarKey == "Type").First()?.VarValue;
            dataList.Add(new FlowQuerySingleResultDto
            {
                workitemId = workitem.WorkitemId,
                InstanceId = flowInstance.InstanceId,
                BusinessNo = flowInstance.BusinessNo,
                Title = flowTitle,
                Type = Int16.Parse(type ?? "0"),
                NodeName = workitem.NodeName,
                Status = workitem.Status,
                WorkStatus = workitem.Status,
                CreateTime = flowInstance.CreateTime,
                InitiatorName = flowInstance.InitiatorName
            });
        }

        return new PageQueryResultDto<FlowQuerySingleResultDto>
        {
            Page = pageIndex,
            Limit = pageSize,
            Total = totalCount,
            TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
            Items = dataList
        };
    }

    /// <summary>
    /// 我的已办（当前用户已处理完成的事项）
    /// </summary>
    /// <param name="userId">当前用户ID</param>
    /// <param name="pageQueryDto">分页参数</param>
    /// <returns>分页结果</returns>
    public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyDone(long userId, PageQueryRequestDto pageQueryDto)
    {
        // 参数初始化
        if (userId <= 0)
            return new PageQueryResultDto<FlowQuerySingleResultDto>();
        pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
        var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
        var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;

        // 已办逻辑：工作项状态为"Done"、处理人ID为当前用户（去重流程实例）
        var doneInstanceIds = _sqlSugar.Queryable<ZyFlowWorkitem>()
            .Where(w => w.HandlerId == userId && w.Status == "Done")
            .Select(w => w.InstanceId)
            .Distinct()
            .ToList();

        if (!doneInstanceIds.Any())
            return new PageQueryResultDto<FlowQuerySingleResultDto>();

        // 分页处理实例ID
        var pagedInstanceIds = doneInstanceIds
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToList();
        var totalCount = doneInstanceIds.Count;

        // 组装返回结果
        var dataList = new List<FlowQuerySingleResultDto>();
        foreach (var instanceId in pagedInstanceIds)
        {
            var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
                .Where(i => i.InstanceId == instanceId)
                .First();
            if (flowInstance == null)
                continue;

            var flowTitle = _sqlSugar.Queryable<ZyFlowVariable>()
                .Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
                .First()?.VarValue ?? string.Empty;

            var lastWorkitem = _sqlSugar.Queryable<ZyFlowWorkitem>()
                .Where(w => w.InstanceId == instanceId && w.HandlerId == userId && w.Status == "Done")
                .OrderByDescending(w => w.HandleTime)
                .First();

            dataList.Add(new FlowQuerySingleResultDto
            {
                InstanceId = flowInstance.InstanceId,
                BusinessNo = flowInstance.BusinessNo,
                Title = flowTitle,
                NodeName = lastWorkitem?.NodeName ?? string.Empty,
                Status = lastWorkitem?.Status,
                CreateTime = flowInstance.CreateTime,
                InitiatorName = flowInstance.InitiatorName
            });
        }

        return new PageQueryResultDto<FlowQuerySingleResultDto>
        {
            Page = pageIndex,
            Limit = pageSize,
            Total = totalCount,
            TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
            Items = dataList
        };
    }

    /// <summary>
    /// 我的未办结（当前用户参与过、流程尚未完成的事项）
    /// </summary>
    /// <param name="userId">当前用户ID</param>
    /// <param name="pageQueryDto">分页参数</param>
    /// <returns>分页结果</returns>
    public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyUnfinished(long userId, PageQueryRequestDto pageQueryDto)
    {
        // 参数初始化
        if (userId <= 0)
            return new PageQueryResultDto<FlowQuerySingleResultDto>();
        pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
        var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
        var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;

        // 未办结逻辑：
        // 1. 当前用户参与过（处理过/待处理）
        // 2. 流程状态不是"Completed"（未完成）
        var unfinishedInstanceIds = _sqlSugar
            .Queryable<ZyFlowWorkitem, ZyFlowInstance>((w, i)
                => new JoinQueryInfos(JoinType.Inner, w.InstanceId == i.InstanceId))
            .Where((w, i)
                => (w.HandlerId == userId || w.Status == "Draft")
                   && i.Status != "Completed")
            .Select((w, i) => i.InstanceId)
            .Distinct()
            .ToList();

        if (!unfinishedInstanceIds.Any())
            return new PageQueryResultDto<FlowQuerySingleResultDto>();

        // 分页处理实例ID
        var pagedInstanceIds = unfinishedInstanceIds
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToList();
        var totalCount = unfinishedInstanceIds.Count;

        // 组装返回结果
        var dataList = new List<FlowQuerySingleResultDto>();
        foreach (var instanceId in pagedInstanceIds)
        {
            var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
                .Where(i => i.InstanceId == instanceId)
                .First();
            if (flowInstance == null)
                continue;

            var flowTitle = _sqlSugar.Queryable<ZyFlowVariable>()
                .Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
                .First()?.VarValue ?? string.Empty;

            var currentNode = _sqlSugar.Queryable<ZyFlowNode>()
                .Where(n => n.NodeId == flowInstance.CurrentNodeId)
                .First();

            dataList.Add(new FlowQuerySingleResultDto
            {
                InstanceId = flowInstance.InstanceId,
                BusinessNo = flowInstance.BusinessNo,
                Title = flowTitle,
                NodeName = currentNode?.NodeName ?? string.Empty,
                Status = flowInstance.Status,
                CreateTime = flowInstance.CreateTime,
                InitiatorName = flowInstance.InitiatorName
            });
        }

        return new PageQueryResultDto<FlowQuerySingleResultDto>
        {
            Page = pageIndex,
            Limit = pageSize,
            Total = totalCount,
            TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
            Items = dataList
        };
    }

    /// <summary>
    /// 我的已完成（当前用户参与过、流程已归档完成的事项）
    /// </summary>
    /// <param name="userId">当前用户ID</param>
    /// <param name="pageQueryDto">分页参数</param>
    /// <returns>分页结果</returns>
    public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyCompleted(long userId, PageQueryRequestDto pageQueryDto)
    {
        // 参数初始化
        if (userId <= 0)
            return new PageQueryResultDto<FlowQuerySingleResultDto>();
        pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
        var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
        var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;

        // 已完成逻辑：
        // 1. 当前用户参与过（处理过/待处理）
        // 2. 流程状态是"Completed"（已完成）
        var completedInstanceIds = _sqlSugar.Queryable<ZyFlowWorkitem, ZyFlowInstance>((w, i) => new JoinQueryInfos(
                JoinType.Inner, w.InstanceId == i.InstanceId))
            .Where((w, i) => (w.HandlerId == userId || w.Status == "Draft")
                             && i.Status == "Completed")
            .Select((w, i) => i.InstanceId)
            .Distinct()
            .ToList();

        if (!completedInstanceIds.Any())
            return new PageQueryResultDto<FlowQuerySingleResultDto>();

        // 分页处理实例ID
        var pagedInstanceIds = completedInstanceIds
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToList();
        var totalCount = completedInstanceIds.Count;

        // 组装返回结果
        var dataList = new List<FlowQuerySingleResultDto>();
        foreach (var instanceId in pagedInstanceIds)
        {
            var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
                .Where(i => i.InstanceId == instanceId)
                .First();
            if (flowInstance == null)
                continue;

            var flowTitle = _sqlSugar.Queryable<ZyFlowVariable>()
                .Where(v => v.InstanceId == flowInstance.InstanceId && v.VarKey == "Title")
                .First()?.VarValue ?? string.Empty;

            var lastNode = _sqlSugar.Queryable<ZyFlowNode>()
                .Where(n => n.NodeId == flowInstance.CurrentNodeId)
                .First();

            dataList.Add(new FlowQuerySingleResultDto
            {
                InstanceId = flowInstance.InstanceId,
                BusinessNo = flowInstance.BusinessNo,
                Title = flowTitle,
                NodeName = lastNode?.NodeName ?? "流程归档",
                Status = flowInstance.Status,
                CreateTime = flowInstance.CreateTime,
                InitiatorName = flowInstance.InitiatorName
            });
        }

        return new PageQueryResultDto<FlowQuerySingleResultDto>
        {
            Page = pageIndex,
            Limit = pageSize,
            Total = totalCount,
            TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
            Items = dataList
        };
    }

    /// <summary>
    /// 我的全部事项（拟办+待办+已办+未办结+已完成，去重整合）
    /// </summary>
    /// <param name="userId">当前用户ID</param>
    /// <param name="pageQueryDto">分页参数</param>
    /// <returns>分页结果</returns>
    public PageQueryResultDto<FlowQuerySingleResultDto> QueryMyAllItems(long userId, PageQueryRequestDto pageQueryDto)
    {
        // 参数初始化
        if (userId <= 0)
            return new PageQueryResultDto<FlowQuerySingleResultDto>();
        pageQueryDto = pageQueryDto ?? new PageQueryRequestDto();
        var pageIndex = pageQueryDto.page < 1 ? 1 : pageQueryDto.page;
        var pageSize = pageQueryDto.limit < 1 ? 10 : pageQueryDto.limit;

        // todo  拟办 发起人 InitiatorId  要经手的 角色绑定的节点 handler_id = null   或者 已经手的（handler_id = user ）
        var nodeIdList = _sqlSugar.Queryable<ZyFlowNode>()
            // 核心：In(主表字段, 子查询Lambda表达式)
            .In(
                zy => zy.RoleId, // 主表 zy_flow_node 的 role_id 字段
                // 子查询：从 sys_userrole 中查询 UserId=2 的 RoleId
                _sqlSugar.Queryable<SysUserRole>()
                    .Where(ur => ur.UserId == userId) // 条件：UserId=2（注意：这里直接用数值，避免字符串拼接）
                    .Select(ur => ur.RoleId) // 子查询只返回 RoleId 字段
            )
            // 主查询只返回 node_id 字段（提升查询性能，避免查询全表字段）
            .Select(zy => zy.NodeId)
            // 执行查询，返回 List<long> 结果
            .ToList();

        var allQuery = _sqlSugar.Queryable<IllegalConstructionAssessment, ZyFlowInstance, ZyFlowNode>((t, i, n) =>
                new JoinQueryInfos(
                    // 第一个左联：t(违建表) LEFT JOIN i(流程实例表) ON 业务编号匹配
                    JoinType.Left, t.BusinessNumber == i.BusinessNo,
                    // 第二个左联：i(流程实例表) LEFT JOIN n(流程节点表) ON 当前节点ID匹配
                    JoinType.Left, i.CurrentNodeId == n.NodeId
                ))
            // WHERE条件：严格还原原生SQL的OR+IN子查询逻辑（参数化userId，替换硬编码）
            .Where((t, i, n) =>
                i.InitiatorId == userId
                || SqlFunc.Exists(
                    SqlFunc.Subqueryable<ZyFlowWorkitem>()
                        .GroupBy(w => w.InstanceId)
                        // 子查询过滤条件：仅修改Contains + 加nodeIdList非空判断
                        .Where(w => w.HandlerId == userId)
                        // 关键1：用WhereIF判断列表非空，避免IN()语法错误；用SqlFunc.Contains替代原生Contains
                        .WhereIF(nodeIdList != null && nodeIdList.Any(),
                            w => w.HandlerId == null && w.Status == "ToDo" &&
                                 SqlFunc.ContainsArray(nodeIdList, w.NodeId))
                        // 主查询与子查询的实例ID关联（原有逻辑，不变）
                        .Where(w => w.InstanceId == i.InstanceId)
                        .Select(w => w.InstanceId)
                )
            )
            // 你的指定Select：完全按FlowQuerySingleResultDto赋值，保留原空值处理逻辑
            .Select((t, i, n) => new FlowQuerySingleResultDto
            {
                InstanceId = i.InstanceId,
                BusinessNo = i.BusinessNo,
                Title = t.Title,
                Type = t.Type, // 保留原空值默认转0的处理
                NodeName = n.NodeName, // 左联可能为null，Dto中若需默认值可加??"未知节点"
                Status = i.Status,
                CreateTime = i.CreateTime,
                InitiatorName = i.InitiatorName
            });
        var totalCount = allQuery.Count();
        var dataList = allQuery
            .Skip((pageIndex - 1) * pageSize)
            .Take(pageSize)
            .ToList();
        return new PageQueryResultDto<FlowQuerySingleResultDto>
        {
            Page = pageIndex,
            Limit = pageSize,
            Total = totalCount,
            TotalPages = (int)Math.Ceiling((double)totalCount / pageSize),
            Items = dataList
        };
    }

    #endregion

    #region 三、内部核心辅助方法（仅内部调用，不对外暴露）

    /// <summary>
    /// 流程节点流转核心方法
    /// </summary>
    private void FlowToNextNode(long instanceId, ZyFlowNode currentNode, long userId, string userName, string comment)
    {
        // 解析下一节点IDs
        var nextNodeIds = currentNode.NextNodeIds?.Split(',', StringSplitOptions.RemoveEmptyEntries)
            .Select(long.Parse)
            .ToList() ?? new List<long>();
        if (!nextNodeIds.Any())
            return;

        // 查询流程实例
        var flowInstance = _sqlSugar.Queryable<ZyFlowInstance>()
            .Where(i => i.InstanceId == instanceId)
            .First();
        if (flowInstance == null)
            throw new Exception("流程实例不存在");

        // 遍历处理每个下一节点
        foreach (var nextNodeId in nextNodeIds)
        {
            var nextNode = _sqlSugar.Queryable<ZyFlowNode>()
                .Where(n => n.NodeId == nextNodeId)
                .First();
            if (nextNode == null)
                continue;

            // 更新流程实例当前节点和状态
            flowInstance.CurrentNodeId = nextNode.NodeId;
            flowInstance.Status = GetFlowStatusByNodeType(nextNode.NodeType);
            _sqlSugar.Updateable(flowInstance).ExecuteCommand();

            // 并行节点（5个审核科）：为每个审核科创建工作项
            if (nextNode.NodeType == "Parallel")
            {
                CreateAuditDeptWorkitem(instanceId, nextNode);
            }
            // 普通节点/分支节点：创建单个工作项
            else
            {
                var nextWorkitem = new ZyFlowWorkitem
                {
                    InstanceId = instanceId,
                    NodeId = nextNode.NodeId,
                    NodeName = nextNode.NodeName,
                    //HandlerId = userId,
                    //HandlerName = userName,
                    Status = "ToDo",
                    ReceiveTime = DateTime.Now,
                    Comment = comment
                };
                _sqlSugar.Insertable(nextWorkitem).ExecuteCommand();
            }
        }
    }

    /// <summary>
    /// 处理并行会签（保存结果+判断是否全部完成）
    /// </summary>
    private void ProcessParallelAudit(long instanceId, long nodeId, long userId, string userName,
        HandleWorkitemRequestDto requestDto)
    {
        // 校验会签结果
        if (string.IsNullOrEmpty(requestDto.AuditResult))
            throw new Exception("会签需选择审核结果（Pass/Reject）");

        // 步骤1：获取当前用户所属科室名称
        var deptName = GetUserDeptName(userId);

        // 步骤2：保存会签记录
        var parallelAudit = new ZyFlowParallelAudit
        {
            InstanceId = instanceId,
            NodeId = nodeId,
            DeptName = deptName,
            AuditResult = requestDto.AuditResult,
            AuditComment = requestDto.Comment,
            AuditorId = userId,
            AuditorName = userName,
            AuditTime = DateTime.Now
        };
        _sqlSugar.Insertable(parallelAudit).ExecuteCommand();

        // 步骤3：判断是否所有审核科都已完成会签
        if (IsAllAuditCompleted(instanceId, nodeId))
        {
            // 步骤4：流转至汇总节点
            var parallelNode = _sqlSugar.Queryable<ZyFlowNode>()
                .Where(n => n.NodeId == nodeId && n.NodeType == "Parallel")
                .First();
            FlowToNextNode(instanceId, parallelNode, userId, userName, "所有审核科会签完成，流转至汇总节点");
        }
    }

    private bool IsAllAuditCompleted(long instanceId, long nodeId)
    {
        // 有一个 Pending 
        var auditsCount = _sqlSugar.Queryable<ZyFlowWorkitem>()
            .Any(a => a.InstanceId == instanceId && a.NodeId == nodeId && a.Status == "ToDo");
        return !auditsCount;
    }

    /// <summary>
    /// 处理汇总节点（归档/退回区县）
    /// </summary>
    private void ProcessSummaryNode(ZyFlowInstance flowInstance, ZyFlowNode summaryNode, long userId, string userName)
    {
        // 步骤1：判断是否全部审核通过
        var hasReject = _sqlSugar.Queryable<ZyFlowParallelAudit>()
            .Where(a => a.InstanceId == flowInstance.InstanceId)
            .Any(a => a.AuditResult == "Reject");
        var isAllPass = !hasReject;
        // 步骤2：解析汇总节点下一节点（归档/退回）
        var nextNodeIds = summaryNode.NextNodeIds?.Split(',', StringSplitOptions.RemoveEmptyEntries)
            .Select(long.Parse)
            .ToList() ?? new List<long>();
        if (nextNodeIds.Count < 2)
            throw new Exception("汇总节点需配置2个后续节点（归档/退回区县）");

        // 步骤3：确定目标节点（通过→归档[下标0]，不通过→退回区县[下标1]）
        var targetNodeId = isAllPass ? nextNodeIds[0] : nextNodeIds[1];
        var targetNode = _sqlSugar.Queryable<ZyFlowNode>()
            .Where(n => n.NodeId == targetNodeId)
            .First();
        if (targetNode == null)
            throw new Exception($"汇总节点目标节点【{(isAllPass ? "归档" : "退回区县")}】不存在");

        // 步骤4：创建目标节点工作项
        var summaryWorkitem = new ZyFlowWorkitem
        {
            InstanceId = flowInstance.InstanceId,
            NodeId = targetNode.NodeId,
            NodeName = targetNode.NodeName,
            HandlerId = isAllPass ? null : flowInstance.InitiatorId,
            HandlerName = isAllPass ? "系统自动处理" : flowInstance.InitiatorName,
            Status = isAllPass ? "Done" : "ToDo",
            ReceiveTime = DateTime.Now,
            HandleTime = isAllPass ? DateTime.Now : null,
            Comment = isAllPass ? "所有审核科通过，流程归档完成" : "存在审核不通过项，退回区县修改补充材料"
        };
        _sqlSugar.Insertable(summaryWorkitem).ExecuteCommand();

        // 步骤5：更新流程实例最终状态
        flowInstance.CurrentNodeId = targetNode.NodeId;
        flowInstance.Status = isAllPass ? "Completed" : "Rejected";
        flowInstance.FinishTime = isAllPass ? DateTime.Now : null;
        _sqlSugar.Updateable(flowInstance).ExecuteCommand();
    }

    /// <summary>
    /// 完成流程实例（结束节点）
    /// </summary>
    private void CompleteFlowInstance(ZyFlowInstance flowInstance)
    {
        flowInstance.Status = "Completed";
        flowInstance.FinishTime = DateTime.Now;
        _sqlSugar.Updateable(flowInstance).ExecuteCommand();
    }

    /// <summary>
    /// 为审核科创建工作项
    /// </summary>
    private void CreateAuditDeptWorkitem(long instanceId, ZyFlowNode parallelNode)
    {
        // 获取科室用户信息

        var userInfos = _sqlSugar
            .Queryable<SysUser>()
            .LeftJoin<SysUserRole>((u, ur) => u.Id == ur.UserId)
            .LeftJoin<SysUserOrg>((u, ur, uo) => u.Id == uo.UserId)
            .LeftJoin<SysOrg>((u, ur, uo, o) => uo.OrgId == o.Id)
            .Where((u, ur, uo, o) => ur.RoleId == parallelNode.RoleId)
            .Select((u, ur, uo, o) => new
            {
                userName = u.Name,
                userId = u.Id,
                deptName = o.Name
            })
            .ToList();
        foreach (var userInfo in userInfos)
        {
            // 创建工作项
            var workitem = new ZyFlowWorkitem
            {
                InstanceId = instanceId,
                NodeId = parallelNode.NodeId,
                NodeName = $"{parallelNode.NodeName}（{userInfo.deptName}）",
                HandlerId = userInfo.userId,
                HandlerName = userInfo.userName,
                Status = "ToDo",
                ReceiveTime = DateTime.Now,
                Comment = "请完成违法建设认定相关审核工作"
            };
            _sqlSugar.Insertable(workitem).ExecuteCommand();
        }
    }

    /// <summary>
    /// 保存附件并返回路径
    /// </summary>
    private string SaveAttachments(List<IFormFile> attachments)
    {
        if (attachments == null || !attachments.Any())
            return string.Empty;

        // 定义附件存储目录
        var uploadDir = Path
            .Combine(AppContext.BaseDirectory, "Attachments/FlowAttachments");
        if (!Directory.Exists(uploadDir))
            Directory.CreateDirectory(uploadDir);

        var attachmentPaths = new List<string>();
        foreach (var file in attachments)
        {
            if (file.Length <= 0)
                continue;

            // 生成唯一文件名
            var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
            var filePath = Path.Combine(uploadDir, fileName);

            // 保存文件
            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                file.CopyTo(stream);
            }

            // 保存相对路径（用于前端访问）
            attachmentPaths.Add($"/Attachments/FlowAttachments/{fileName}");
        }

        return string.Join(",", attachmentPaths);
    }

    /// <summary>
    /// 根据节点类型获取流程状态
    /// </summary>
    private string GetFlowStatusByNodeType(string nodeType)
    {
        return nodeType switch
        {
            "Common" => "Forwarded", // 已转发
            "Parallel" => "Auditing", // 审核中
            "Branch" => "Summarized", // 已汇总
            "End" => "Completed", // 已完成
            _ => "Submitted" // 已提交
        };
    }


    /// <summary>
    /// 获取用户所属科室名称
    /// </summary>
    private string GetUserDeptName(long userId)
    {
        var deptName = _sqlSugar.Queryable<SysUserOrg, SysOrg>((uo, o) => new JoinQueryInfos(
                JoinType.Inner, uo.OrgId == o.Id))
            .Where((uo, o) => uo.UserId == userId)
            .Select((uo, o) => o.Name)
            .First();

        return deptName ?? "未知科室";
    }

    /// <summary>
    /// 获取角色下第一个用户的完整信息
    /// </summary>
    private (long userId, string userName, string deptName) GetRoleFirstUserInfo(long roleId)
    {
        var userInfo = _sqlSugar
            .Queryable<SysUserRole, SysUser, SysUserOrg, SysOrg>((ur, u, uo, o)
                => new JoinQueryInfos(
                    JoinType.Inner, ur.UserId == u.Id && u.Id == uo.UserId && uo.OrgId == o.Id))
            .Where((ur, u, uo, o) => ur.RoleId == roleId)
            .Select((ur, u, uo, o) => new
            {
                UserId = u.Id,
                UserName = u.Name,
                DeptName = o.Name
            })
            .First();

        if (userInfo == null)
            return (0, string.Empty, string.Empty);

        return (userInfo.UserId, userInfo.UserName ?? string.Empty, userInfo.DeptName ?? string.Empty);
    }

    #endregion

    /// <summary>
    ///  保存拟办
    /// </summary>
    /// <param name="requestDto"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public object SaveDraft(InitiateFlowRequestDto requestDto)
    {
        try
        {
            UnitWork.Db.Ado.BeginTran();
            requestDto.BusinessNo = _businessNoGenerator.GenerateBusinessNo("wfjszl");
            var attachmentPaths = string.Join(",", requestDto.Attachments);
            var user = _auth.GetCurrentUser().User;
            var illegalConstructionAssessment = new IllegalConstructionAssessment
            {
                Id = requestDto.BusinessNo,
                Title = requestDto.Title,
                BusinessNumber = requestDto.BusinessNo,
                Attachments = requestDto.Attachments != null ? attachmentPaths : string.Empty,
                AcceptanceTime = DateTime.Now,
                Status = "Draft",
                Type = requestDto.type,
                CreateTime = DateTime.Now,
                CreateUser = user.Name,
                UpdateTime = DateTime.Now,
                CreateUserId = user.Id
            };
            _sqlSugar.Insertable(illegalConstructionAssessment).ExecuteCommand();
            var template = _sqlSugar.Queryable<ZyFlowTemplate>()
                .Where(t => t.FlowCode == requestDto.FlowCode && t.IsEnabled == true)
                .First();
            if (template == null)
                throw new Exception($"流程模板【{requestDto.FlowCode}】不存在或未启用");

            // 步骤2：查询流程开始节点（区县提交）
            var startNode = _sqlSugar.Queryable<ZyFlowNode>()
                .Where(n => n.TemplateId == template.TemplateId && n.NodeType == "Start" && n.NodeName == "区县提交")
                .First();
            if (startNode == null)
                throw new Exception("流程开始节点【区县提交】不存在，请配置节点");
            var flowInstance = new ZyFlowInstance
            {
                TemplateId = template.TemplateId,
                FlowCode = template.FlowCode,
                BusinessNo = requestDto.BusinessNo,
                Status = "Draft", // 已提交
                CurrentNodeId = startNode.NodeId,
                InitiatorId = user.Id,
                InitiatorName = user.Name,
                CreateTime = DateTime.Now
            };
            var instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
            // 步骤4：插入开始节点工作项（直接标记为已完成）
            // 开始节点无ToDo
            var startWorkitem = new ZyFlowWorkitem
            {
                InstanceId = instanceId,
                NodeId = startNode.NodeId,
                NodeName = startNode.NodeName,
                HandlerId = user.Id,
                HandlerName = user.Name,
                Status = "Draft", // 已完成
                ReceiveTime = DateTime.Now,
                HandleTime = DateTime.Now,
                Comment = "区县拟办"
            };
            _sqlSugar.Insertable(startWorkitem).ExecuteCommand();
            UnitWork.Db.Ado.CommitTran();
            return true;
        }
        finally
        {
            UnitWork.Db.Ado.RollbackTran();
        }
    }

    public dynamic Detail(string businessNo)
    {
        return _sqlSugar
            .Queryable<IllegalConstructionAssessment>()
            .Where(i => i.Id == businessNo)
            .First();
    }
}