package cn.iocoder.yudao.module.bpm.service.processmapping;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.bpm.dal.dataobject.processmapping.BpmProcessMappingConfigDO;
import cn.iocoder.yudao.module.bpm.framework.core.util.ReflectionInvoker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_MAPPING_CONFIG_NOT_EXISTS;

/**
 * 流程动态查询 Service 实现类
 *
 * @author 系统
 */
@Service
@Validated
@Slf4j
public class ProcessQueryServiceImpl implements ProcessQueryService {

    @Resource
    private ProcessMappingConfigService processMappingConfigService;

    @Override
    public Object queryById(String processCode, Serializable id) {
        // 1. 获取流程配置
        BpmProcessMappingConfigDO config = getProcessMappingConfig(processCode);

        // 2. 动态获取Mapper实例
        Object mapperBean = getMapperBean(config.getMapperClass());

        // 3. 调用selectById方法
        return ReflectionInvoker.invokeMapperMethod(mapperBean, "selectById", Serializable.class, id);
    }

    @Override
    public List<?> queryList(String processCode, QueryWrapper<?> queryWrapper) {
        // 1. 获取流程配置
        BpmProcessMappingConfigDO config = getProcessMappingConfig(processCode);

        // 2. 动态获取Mapper实例
        Object mapperBean = getMapperBean(config.getMapperClass());

        // 3. 调用selectList方法
        return (List<?>) ReflectionInvoker.invokeMapperMethod(mapperBean, "selectList", QueryWrapper.class, queryWrapper);
    }

    /**
     * 获取流程映射配置
     */
    private BpmProcessMappingConfigDO getProcessMappingConfig(String processCode) {
        BpmProcessMappingConfigDO config = processMappingConfigService.getProcessMappingConfigByCode(processCode);
        if (config == null) {
            throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS);
        }
        return config;
    }

    /**
     * 动态获取Mapper Bean实例
     */
    private Object getMapperBean(String mapperClassName) {
        try {
            Class<?> mapperClass = ClassUtil.loadClass(mapperClassName);
            return SpringUtil.getBean(mapperClass);
        } catch (Exception e) {
            log.error("[getMapperBean][获取Mapper实例失败] mapperClassName={}", mapperClassName, e);
            throw new ServiceException(500, String.format("获取Mapper实例失败: %s", e.getMessage()));
        }
    }
}
