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

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

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Arrays;
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
@Validated
@Slf4j
public class BpmOAAttachmentServiceImpl implements BpmOAAttachmentService {

    @Resource
    private ProcessMappingConfigService processMappingConfigService;

    /**
     * 更新业务实体的附件信息
     * @param entityClazzs 业务实体类列表
     * @param entityId 业务ID
     * @param fileItems 附件数据
     */
    @Override
    public void updateAttachment(List<Class<?>> entityClazzs, Long entityId, List<UploadUserFile> fileItems) {
        try {
            // 1. 获取实体类并创建实例
            Class<?> doClass = entityClazzs.get(0);
            Object entity = doClass.getDeclaredConstructor().newInstance();
            
            // 2. 使用反射设置实体属性
            Method setIdMethod = doClass.getMethod("setId", Long.class);
            setIdMethod.invoke(entity, entityId);
            Method setFileItems = doClass.getMethod("setFileItems", List.class);
            setFileItems.invoke(entity, fileItems);
            
            // 3. 获取Mapper实例并调用updateById方法
            Class<?> mapperClass = entityClazzs.get(1);
            Object mapperBean = SpringUtil.getBean(mapperClass);
            
            // 4. 使用ReflectionInvoker调用updateById方法
            ReflectionInvoker.invokeMapperMethod(mapperBean, "updateById", Object.class, entity);
            
            log.debug("[updateAttachment][附件更新成功] entityClass={}, entityId={}, fileCount={}", 
                    doClass.getSimpleName(), entityId, fileItems != null ? fileItems.size() : 0);
                    
        } catch (Exception e) {
            log.error("[updateAttachment][附件更新失败] entityId={}, error={}", entityId, e.getMessage(), e);
            throw new ServiceException(500, "附件更新失败，请联系管理员");
        }
    }

    /**
     * 通过流程代码动态解析实体类型
     * @param processCode 流程标识码
     * @return 实体类和Mapper类的列表
     */
    @Override
    public List<Class<?>> resolveEntityType(String processCode) {
        try {
            // 1. 获取流程映射配置
            BpmProcessMappingConfigDO config = processMappingConfigService.getProcessMappingConfigByCode(processCode);
            if (config == null) {
                log.error("[resolveEntityType][流程映射配置不存在] processCode={}", processCode);
                throw exception(PROCESS_MAPPING_CONFIG_NOT_EXISTS);
            }

            // 2. 动态加载实体类和Mapper类
            Class<?> entityClass = ClassUtil.loadClass(config.getEntityClass());
            Class<?> mapperClass = ClassUtil.loadClass(config.getMapperClass());

            // 3. 验证Mapper类是否可获取Bean实例
            SpringUtil.getBean(mapperClass);

            log.debug("[resolveEntityType][成功解析流程类型] processCode={}, entityClass={}, mapperClass={}", 
                    processCode, config.getEntityClass(), config.getMapperClass());

            return Arrays.asList(entityClass, mapperClass);
            
        } catch (Exception e) {
            log.error("[resolveEntityType][解析流程类型失败] processCode={}", processCode, e);
            throw new ServiceException(500, String.format("不支持的流程类型: %s, 错误信息: %s", processCode, e.getMessage()));
        }
    }
}
