package cn.iocoder.yudao.module.llm.service.basemodel;

import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.llm.controller.admin.basemodel.vo.BaseModelPageReqVO;
import cn.iocoder.yudao.module.llm.controller.admin.basemodel.vo.BaseModelSaveReqVO;
import cn.iocoder.yudao.module.llm.dal.dataobject.basemodel.BaseModelDO;
import cn.iocoder.yudao.module.llm.dal.mysql.basemodel.BaseModelMapper;
import cn.iocoder.yudao.module.llm.service.application.ApplicationService;
import cn.iocoder.yudao.module.llm.service.finetuningtask.FineTuningTaskService;
import cn.iocoder.yudao.module.llm.service.modelassesstaskauto.ModelAssessTaskAutoService;
import cn.iocoder.yudao.module.llm.service.modelassesstaskmanual.ModelAssessTaskManualService;
import cn.iocoder.yudao.module.llm.service.modelassesstaskmanualbackup.ModelAssessTaskManualBackupService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.llm.enums.ErrorCodeConstants.*;

/**
 * 基座模型 Service 实现类
 *
 * @author 华大大模型
 */
@Service
@Validated
public class BaseModelServiceImpl implements BaseModelService {

    @Resource
    private BaseModelMapper baseModelMapper;

    @Lazy
    @Resource
    private ApplicationService applicationService;

    @Resource
    private FineTuningTaskService fineTuningTaskService;

    @Resource
    private ModelAssessTaskManualService modelAssessTaskManualService;

    @Resource
    private ModelAssessTaskAutoService modelAssessTaskAutoService;

    @Resource
    private ModelAssessTaskManualBackupService modelAssessTaskManualBackupService;

    @Override
    public Long createBaseModel (BaseModelSaveReqVO createReqVO) {
        validateBaseModelNameExists(createReqVO);
        // 插入
        BaseModelDO baseModel = BeanUtils.toBean(createReqVO, BaseModelDO.class);
        baseModelMapper.insert(baseModel);
        // 返回
        return baseModel.getId();
    }

    /**
     * 校验模型名称是否重复
     *
     * @param reqVO 模型信息
     */
    private void validateBaseModelNameExists (BaseModelSaveReqVO reqVO) {
        LambdaQueryWrapper<BaseModelDO> wrapper = new LambdaQueryWrapper<BaseModelDO>()
                .eq(BaseModelDO::getModelName, reqVO.getModelName().trim());

        if (reqVO.getId() != null) {
            wrapper.ne(BaseModelDO::getId, reqVO.getId());
        }
        List<BaseModelDO> baseModel = baseModelMapper.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(baseModel)) {
            throw exception(BASE_MODEL_NAME_EXISTS);
        }
    }

    @Override
    public void updateBaseModel (BaseModelSaveReqVO updateReqVO) {
        validateBaseModelNameExists(updateReqVO);
        // 校验存在
        validateBaseModelExists(updateReqVO.getId());
        // 更新
        BaseModelDO updateObj = BeanUtils.toBean(updateReqVO, BaseModelDO.class);
        baseModelMapper.updateById(updateObj);
    }

    @Override
    public void deleteBaseModel (Long id) {
        // 校验存在
        validateBaseModelExists(id);
        // 校验使用
        validateModelUse(id);
        // 删除
        baseModelMapper.deleteById(id);
    }

    private void validateBaseModelExists (Long id) {
        if (baseModelMapper.selectById(id) == null) {
            throw exception(BASE_MODEL_NOT_EXISTS);
        }
    }

    @Override
    public BaseModelDO getBaseModel (Long id) {

        return baseModelMapper.selectById(id);
    }

    @Override
    public PageResult<BaseModelDO> getBaseModelPage (BaseModelPageReqVO pageReqVO) {
        return baseModelMapper.selectPage(pageReqVO);
    }

    @Override
    public List<BaseModelDO> getBaseModelList () {
        LambdaQueryWrapper<BaseModelDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseModelDO::getIsActive, 1);
        List<BaseModelDO> baseModelDOS = baseModelMapper.selectList(queryWrapper);
        return baseModelDOS;
    }

    @Override
    public BaseModelDO getByAigcId (Long id) {
        LambdaQueryWrapper<BaseModelDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseModelDO::getAigcId, id);
        return baseModelMapper.selectOne(queryWrapper);
    }

    /**
     * 获取模型管理数量
     *
     * @return 模型管理数量
     */
    @Override
    public Long getCount () {
        return baseModelMapper.selectCount(null);
    }

    /**
     * 禁用 基座模型
     *
     * @param updateReqVO 更新信息
     */
    @Override
    public void unActive (BaseModelSaveReqVO updateReqVO) {
        // 校验使用
        validateModelUse(updateReqVO.getId());

        updateReqVO.setIsActive(false);
        updateBaseModel(updateReqVO);
    }

    /**
     * 校验模型使用情况
     *
     * @param id 模型ID
     */
    private void validateModelUse (Long id) {
        BaseModelDO modelDO = baseModelMapper.selectById(id);
        String modelName = modelDO.getModelName();

        // 校验 基座模型 是否在 应用中心 有使用
        validateModelUsesInApplicationCenter(id, modelName);
        // 校验 基座模型 是否在 模型调优 有使用 （是否为等待中、进行中）
        validateModelUsesInModelTuning(id, modelName);
        // 校验 基座模型 是否在 模型评估任务-人工 有使用 （是否为进行中）
        validateModelUsesInModelAssessTaskManual(id, modelName);
        // 校验 基座模型 是否在 模型评估任务-自动 有使用 （是否为进行中、推理中）
        validateModelUsesInModelAssessTaskAuto(id, modelName);
        // 校验 基座模型 是否在 模型评估任务备份-人工 有使用
        validateModelUsesInModelAssessTaskBackupManual(id, modelName);
    }

    /**
     * 校验模型是否在 应用中心 有使用
     *
     * @param id        模型ID
     * @param modelName 模型名称
     */
    private void validateModelUsesInApplicationCenter (Long id, String modelName) {
        Map<Long, String> application = applicationService.getApplicationByBaseModelId(id);
        if (CollectionUtils.isNotEmpty(application)) {
            String msg = String.format("模型【%s】在应用中心 %s 有使用，请先取消使用", modelName, application.values());
            throw exception(new ErrorCode(10022_001, msg));
        }
    }

    /**
     * 校验模型是否在 模型调优 有使用
     *
     * @param id        模型ID
     * @param modelName 模型名称
     */
    private void validateModelUsesInModelTuning (Long id, String modelName) {
        Map<Long, String> modelTuning = fineTuningTaskService.getModelTuningByModelId(id);
        if (CollectionUtils.isNotEmpty(modelTuning)) {
            String msg = String.format("模型【%s】在模型调优 %s 有正在等待的任务，请先结束任务", modelName, modelTuning.values());
            throw exception(new ErrorCode(10022_002, msg));
        }
    }

    /**
     * 校验模型是否在 模型评估任务-人工 有使用
     *
     * @param id        模型ID
     * @param modelName 模型名称
     */
    private void validateModelUsesInModelAssessTaskManual (Long id, String modelName) {
        Map<Long, String> modelAssessmentTask = modelAssessTaskManualService.getModelAssessmentTaskByModelId(id);
        if (CollectionUtils.isNotEmpty(modelAssessmentTask)) {
            String msg = String.format("模型【%s】在模型评估-人工评估 %s 有正在进行的任务，请先结束任务", modelName, modelAssessmentTask.values());
            throw exception(new ErrorCode(10022_003, msg));
        }
    }

    /**
     * 校验模型是否在 模型评估任务-自动 有使用
     *
     * @param id        模型ID
     * @param modelName 模型名称
     */
    private void validateModelUsesInModelAssessTaskAuto (Long id, String modelName) {
        Map<Long, String> modelAssessmentTask = modelAssessTaskAutoService.getModelAssessmentTaskByModelId(id);
        if (CollectionUtils.isNotEmpty(modelAssessmentTask)) {
            String msg = String.format("模型【%s】在模型评估-自动评估 %s 有正在进行的任务，请先结束任务", modelName, modelAssessmentTask.values());
            throw exception(new ErrorCode(10022_004, msg));
        }
    }

    /**
     * 校验模型是否在 模型评估任务备份-人工 有使用
     *
     * @param id        模型ID
     * @param modelName 模型名称
     */
    private void validateModelUsesInModelAssessTaskBackupManual (Long id, String modelName) {
        Map<Long, String> modelAssessmentTask = modelAssessTaskManualBackupService.getModelAssessmentTaskByModelId(id);
        if (CollectionUtils.isNotEmpty(modelAssessmentTask)) {
            String msg = String.format("模型【%s】在模型评估-人工评估 %s 存在备份，请先取消备份", modelName, modelAssessmentTask.values());
            throw exception(new ErrorCode(10022_005, msg));
        }
    }

}
