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

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 lombok.extern.slf4j.Slf4j;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.stereotype.Component;

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

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

    @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());
    }

    /**
     * 配置任务的审批人
     * 根据 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) {
                    Object approverValue = task.getVariable(input.getApproverVariable());
                    if (approverValue != null) {
                        task.setAssignee(approverValue.toString());
                        log.info("Set assignee from variable {}: {}", input.getApproverVariable(), approverValue);
                    }
                }
                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());
    }
}

