package com.qqchen.deploy.backend.workflow.listener;

import com.qqchen.deploy.backend.framework.utils.SpelExpressionResolver;
import com.qqchen.deploy.backend.workflow.dto.event.ApprovalTaskCreatedEvent;
import com.qqchen.deploy.backend.workflow.dto.inputmapping.ApprovalInputMapping;
import com.qqchen.deploy.backend.workflow.dto.outputs.ApprovalOutputs;
import com.qqchen.deploy.backend.workflow.enums.ApprovalModeEnum;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowDefinitionRepository;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowInstanceRepository;
import com.qqchen.deploy.backend.workflow.repository.IWorkflowCategoryRepository;
import lombok.extern.slf4j.Slf4j;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 审批任务创建监听器
 * 在 UserTask 创建时被调用，负责配置审批人和任务基本信息
 *
 * @author qqchen
 * @since 2025-10-23
 */
@Slf4j
@Component("approvalCreateTaskListener")
public class ApprovalCreateTaskListener extends BaseTaskListener<ApprovalInputMapping, ApprovalOutputs> {

    @Resource
    private ApplicationEventPublisher eventPublisher;

    @Resource
    private IWorkflowInstanceRepository workflowInstanceRepository;

    @Resource
    private IWorkflowDefinitionRepository workflowDefinitionRepository;

    @Resource
    private IWorkflowCategoryRepository workflowCategoryRepository;

    @Override
    protected void configureTask(
        DelegateTask delegateTask,
        Map<String, Object> configs,
        ApprovalInputMapping inputMapping
    ) {
        log.info("Configuring approval task: {}", delegateTask.getId());

        // 1. 配置审批人
        configureTaskAssignee(delegateTask, inputMapping);

        // 2. 设置任务基本信息
        if (configs.get("nodeName") != null) {
            delegateTask.setName((String) configs.get("nodeName"));
        }
        if (inputMapping.getApprovalTitle() != null) {
            delegateTask.setDescription(inputMapping.getApprovalTitle());
        }

        // 3. 设置超时时间
        if (inputMapping.getTimeoutDuration() != null && inputMapping.getTimeoutDuration() > 0) {
            java.util.Date dueDate = java.sql.Timestamp.valueOf(
                LocalDateTime.now().plusHours(inputMapping.getTimeoutDuration())
            );
            delegateTask.setDueDate(dueDate);
        }

        // 4. 保存审批信息到任务局部变量（供前端查询）
        saveApprovalInfoToTaskVariables(delegateTask, inputMapping);

        log.info("Approval task configured - assignee: {}", delegateTask.getAssignee());

        // 5. 发布审批任务创建事件
        publishApprovalTaskCreatedEvent(delegateTask);
    }

    /**
     * 发布审批任务创建事件
     */
    private void publishApprovalTaskCreatedEvent(DelegateTask delegateTask) {
        try {
            String processInstanceId = delegateTask.getProcessInstanceId();
            
            // 查询工作流实例信息
            var workflowInstance = workflowInstanceRepository.findByProcessInstanceId(processInstanceId).orElse(null);
            if (workflowInstance == null) {
                log.warn("工作流实例不存在，无法发布审批任务创建事件: processInstanceId={}", processInstanceId);
                return;
            }

            // 查询工作流定义获取分类信息
            String workflowCategoryCode = null;
            if (workflowInstance.getWorkflowDefinitionId() != null) {
                var definition = workflowDefinitionRepository.findById(workflowInstance.getWorkflowDefinitionId()).orElse(null);
                if (definition != null && definition.getCategoryId() != null) {
                    var category = workflowCategoryRepository.findById(definition.getCategoryId()).orElse(null);
                    if (category != null) {
                        workflowCategoryCode = category.getCode();
                    }
                }
            }

            // 获取候选人信息（从任务变量或通过其他方式）
            // 注意：Flowable 的 DelegateTask API 可能不直接提供 getCandidates()，这里暂时设为 null
            // 如果需要，可以通过任务查询服务获取
            List<String> candidateUsers = null;

            ApprovalTaskCreatedEvent event = ApprovalTaskCreatedEvent.builder()
                    .processInstanceId(processInstanceId)
                    .workflowInstanceId(workflowInstance.getId())
                    .nodeId(getFieldValue(nodeId, delegateTask))
                    .nodeName(delegateTask.getName())
                    .taskId(delegateTask.getId())
                    .assignee(delegateTask.getAssignee())
                    .candidateUsers(candidateUsers)
                    .workflowCategoryCode(workflowCategoryCode)
                    .businessKey((String) delegateTask.getVariable("businessKey"))
                    .createTime(java.time.LocalDateTime.now())
                    .build();

            eventPublisher.publishEvent(event);
            log.debug("发布审批任务创建事件: taskId={}, nodeId={}", delegateTask.getId(), getFieldValue(nodeId, delegateTask));

        } catch (Exception e) {
            log.error("发布审批任务创建事件失败: taskId={}", delegateTask.getId(), e);
            // 不影响主流程，只记录错误
        }
    }

    /**
     * 配置任务的审批人
     * 根据 approverType 不同，设置不同的审批人
     */
    private void configureTaskAssignee(DelegateTask task, ApprovalInputMapping input) {
        if (input.getApproverType() == null) {
            log.warn("ApproverType is null, skip setting assignee");
            return;
        }

        switch (input.getApproverType()) {
            case USER:
                // 指定用户审批
                if (input.getApprovers() != null && !input.getApprovers().isEmpty()) {
                    // ✅ 使用枚举比较而不是字符串比较
                    if (input.getApprovalMode() == ApprovalModeEnum.SINGLE) {
                        // 单人审批：设置 assignee
                        task.setAssignee(input.getApprovers().get(0));
                        log.info("Set single assignee: {}", input.getApprovers().get(0));
                    } else {
                        // 会签/或签：设置候选人
                        for (String approver : input.getApprovers()) {
                            task.addCandidateUser(approver);
                        }
                        log.info("Set candidate users: {}", input.getApprovers());
                    }
                }
                break;

            case ROLE:
                // 指定角色审批：设置候选组
                if (input.getApproverRoles() != null && !input.getApproverRoles().isEmpty()) {
                    for (String role : input.getApproverRoles()) {
                        task.addCandidateGroup(role);
                    }
                    log.info("Set candidate groups (roles): {}", input.getApproverRoles());
                }
                break;

            case DEPARTMENT:
                // 指定部门审批：设置候选组
                if (input.getApproverDepartments() != null && !input.getApproverDepartments().isEmpty()) {
                    for (String dept : input.getApproverDepartments()) {
                        task.addCandidateGroup(dept);
                    }
                    log.info("Set candidate groups (departments): {}", input.getApproverDepartments());
                }
                break;

            case VARIABLE:
                // 从流程变量中获取审批人
                if (input.getApproverVariable() != null) {
                    String approverVariableExpression = input.getApproverVariable();
                    log.info("解析审批人变量表达式: {}", approverVariableExpression);

                    Object approverValue = SpelExpressionResolver.evaluateAuto(task, approverVariableExpression, Object.class);

                    if (approverValue != null) {
                        log.info("解析得到审批人: {}", approverValue);

                        // 处理不同类型的审批人数据
                        if (approverValue instanceof List) {
                            // 列表形式：可能是多个审批人
                            List<?> approvers = (List<?>) approverValue;
                            if (!approvers.isEmpty()) {
                                if (input.getApprovalMode() == ApprovalModeEnum.SINGLE) {
                                    // 单人审批：取第一个
                                    task.setAssignee(String.valueOf(approvers.get(0)));
                                    log.info("Set single assignee from list: {}", approvers.get(0));
                                } else {
                                    // 会签/或签：设置所有候选人
                                    for (Object approver : approvers) {
                                        task.addCandidateUser(String.valueOf(approver));
                                    }
                                    log.info("Set candidate users from list: {}", approvers);
                                }
                            }
                        } else {
                            // 单个值：直接设置为审批人
                            task.setAssignee(String.valueOf(approverValue));
                            log.info("Set assignee from variable {}: {}", approverVariableExpression, approverValue);
                        }
                    } else {
                        log.warn("无法解析审批人变量: {}", approverVariableExpression);
                    }
                }
                break;
        }
    }

    /**
     * 将审批相关信息保存为任务变量
     * 这样前端查询任务时可以获取到这些信息
     */
    private void saveApprovalInfoToTaskVariables(DelegateTask delegateTask, ApprovalInputMapping input) {
        // 保存审批标题和内容
        if (input.getApprovalTitle() != null) {
            delegateTask.setVariableLocal("approvalTitle", input.getApprovalTitle());
        }
        if (input.getApprovalContent() != null) {
            delegateTask.setVariableLocal("approvalContent", input.getApprovalContent());
        }

        // 保存审批模式
        if (input.getApprovalMode() != null) {
            delegateTask.setVariableLocal("approvalMode", input.getApprovalMode().getCode());
        }

        // 保存审批配置
        if (input.getAllowDelegate() != null) {
            delegateTask.setVariableLocal("allowDelegate", input.getAllowDelegate());
        }
        if (input.getAllowAddSign() != null) {
            delegateTask.setVariableLocal("allowAddSign", input.getAllowAddSign());
        }
        if (input.getRequireComment() != null) {
            delegateTask.setVariableLocal("requireComment", input.getRequireComment());
        }

        // 保存候选组（如果有）
        if (input.getApproverRoles() != null && !input.getApproverRoles().isEmpty()) {
            delegateTask.setVariableLocal("candidateGroups", String.join(",", input.getApproverRoles()));
        } else if (input.getApproverDepartments() != null && !input.getApproverDepartments().isEmpty()) {
            delegateTask.setVariableLocal("candidateGroups", String.join(",", input.getApproverDepartments()));
        }

        log.debug("Saved approval info to task variables for taskId: {}", delegateTask.getId());
    }
}

