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

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.modelassesstaskauto.vo.*;
import cn.iocoder.yudao.module.llm.dal.dataobject.basemodel.BaseModelDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.dataset.DatasetDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelassessstoplist.ModelAssessStoplistDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelassesstaskauto.ModelAssessTaskAutoBackupDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelassesstaskauto.ModelAssessTaskAutoDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelassesstaskauto.ModelAssessTaskStoplistBackupDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelassesstaskauto.ModelAssessTaskStoplistDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelassesstaskautoinfo.ModelAssessTaskAutoInfoBackupDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelassesstaskautoinfo.ModelAssessTaskAutoInfoDO;
import cn.iocoder.yudao.module.llm.dal.dataobject.modelservice.ModelServiceDO;
import cn.iocoder.yudao.module.llm.dal.mysql.basemodel.BaseModelMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.dataset.DatasetMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.modelassessstoplist.ModelAssessStoplistMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.modelassesstaskauto.ModelAssessTaskAutoBackupMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.modelassesstaskauto.ModelAssessTaskAutoMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.modelassesstaskauto.ModelAssessTaskStoplistBackupMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.modelassesstaskauto.ModelAssessTaskStoplistMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.modelassesstaskautoinfo.ModelAssessTaskAutoInfoBackupMapper;
import cn.iocoder.yudao.module.llm.dal.mysql.modelservice.ModelServiceMapper;
import cn.iocoder.yudao.module.llm.service.async.AsyncModelAccessManualService;
import cn.iocoder.yudao.module.llm.service.modelassesstaskautoinfo.ModelAssessTaskAutoInfoBackupService;
import cn.iocoder.yudao.module.llm.service.modelassesstaskautoinfo.ModelAssessTaskAutoInfoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

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

/**
 * 模型评估任务 —— 自动评估 Service 实现类
 *
 * @author 华大大模型
 */
@Service
@Validated
public class ModelAssessTaskAutoServiceImpl implements ModelAssessTaskAutoService {

    @Resource
    private ModelAssessTaskAutoMapper modelAssessTaskAutoMapper;
    @Resource
    private ModelAssessTaskStoplistMapper modelingTaskStoplistMapper;
    @Resource
    private ModelServiceMapper modelServiceMapper;
    @Resource
    private DatasetMapper datasetMapper;
    @Resource
    private BaseModelMapper baseModelMapper;
    @Resource
    private ModelAssessTaskAutoBackupMapper modelAssessTaskAutoBackupMapper;
    @Resource
    private ModelAssessTaskStoplistBackupMapper modelAssessTaskStoplistBackupMapper;
    @Resource
    private AsyncModelAccessManualService asyncModelAccessManualService;
    @Resource
    private ModelAssessTaskAutoInfoService modelAssessTaskAutoInfoService;
    @Resource
    private ModelAssessTaskAutoInfoBackupService modelAssessTaskAutoInfoBackupService;
    @Resource
    private ModelAssessStoplistMapper modelAssessStoplistMapper;
    @Resource
    private ModelAssessTaskAutoInfoBackupMapper modelAssessTaskAutoInfoBackupMapper;


    @Override
    public Long createModelAssessTaskAuto (ModelAssessTaskAutoSaveReqVO createReqVO) {
        // 插入
        ModelAssessTaskAutoDO modelAssessTaskAuto = BeanUtils.toBean(createReqVO, ModelAssessTaskAutoDO.class);
        modelAssessTaskAuto.setStatus(3);
        List<String> dimension = createReqVO.getDimension();
        String dimensions = String.join(",", dimension);
        modelAssessTaskAuto.setDimension(dimensions);
        LambdaUpdateWrapper<ModelAssessTaskAutoDO> eq = new LambdaUpdateWrapper<ModelAssessTaskAutoDO>().eq(ModelAssessTaskAutoDO::getTaskName, createReqVO.getTaskName());
        if (modelAssessTaskAutoMapper.selectCount(eq) > 0) {
            throw exception(new ErrorCode(11000, "任务名称重复"));
        }
        modelAssessTaskAutoMapper.insert(modelAssessTaskAuto);
        List<ModelAssessTaskStoplistSaveReqVO> stoplists = createReqVO.getStoplists();
        if (!CollectionUtils.isEmpty(stoplists)) {
            stoplists.stream().forEach(stoplist -> {
                stoplist.setTaskId(modelAssessTaskAuto.getId());
                ModelAssessTaskStoplistDO modelAssessTaskStoplistDO = BeanUtils.toBean(stoplist, ModelAssessTaskStoplistDO.class);
                modelingTaskStoplistMapper.insert(modelAssessTaskStoplistDO);
            });
        }

        asyncModelAccessManualService.auto(modelAssessTaskAuto, stoplists);
        // 返回
        return modelAssessTaskAuto.getId();
    }


    @Override
    public void updateModelAssessTaskAuto (ModelAssessTaskAutoSaveReqVO updateReqVO) {
        // 校验存在
        validateModelAssessTaskAutoExists(updateReqVO.getId());
        // 更新
        ModelAssessTaskAutoDO updateObj = BeanUtils.toBean(updateReqVO, ModelAssessTaskAutoDO.class);
        List<ModelAssessTaskStoplistSaveReqVO> stoplists = updateReqVO.getStoplists();
        if (!CollectionUtils.isEmpty(stoplists)) {
            List<Long> stopIds = stoplists.stream().filter(stoplist -> stoplist.getId() != null)
                    .map(stoplist -> stoplist.getId()).collect(Collectors.toList());
            LambdaQueryWrapper<ModelAssessTaskStoplistDO> wrapper = new LambdaQueryWrapper<ModelAssessTaskStoplistDO>();
            wrapper.eq(ModelAssessTaskStoplistDO::getTaskId, updateReqVO.getId());
            if (!CollectionUtils.isEmpty(stopIds)) {
                wrapper.notIn(ModelAssessTaskStoplistDO::getId, stopIds);
            }
            modelingTaskStoplistMapper.delete(wrapper);
            stoplists.stream().forEach(stoplist -> {
                //            stoplist.setTaskId(updateObj.getId());
                ModelAssessTaskStoplistDO modelAssessTaskStoplistDO = BeanUtils.toBean(stoplist, ModelAssessTaskStoplistDO.class);
                modelingTaskStoplistMapper.insertOrUpdate(modelAssessTaskStoplistDO);
            });
        }
        modelAssessTaskAutoMapper.updateById(updateObj);
    }

    @Override
    public void deleteModelAssessTaskAuto (Long id) {
        // 校验存在
        validateModelAssessTaskAutoExists(id);
        LambdaUpdateWrapper<ModelAssessTaskAutoDO> wrapper = new LambdaUpdateWrapper<>();
        // 删除
        wrapper.eq(ModelAssessTaskAutoDO::getId, id)
                .set(ModelAssessTaskAutoDO::getDeleted, true);
        modelAssessTaskAutoMapper.update(null, wrapper);
    }

    private void validateModelAssessTaskAutoExists (Long id) {
        if (modelAssessTaskAutoMapper.selectById(id) == null) {
            throw exception(MODEL_ASSESS_TASK_AUTO_NOT_EXISTS);
        }
    }

    @Override
    public ModelAssessTaskAutoRespVO getModelAssessTaskAuto (Long id) {
        ModelAssessTaskAutoDO modelAssessTaskAutoDO = modelAssessTaskAutoMapper.selectById(id);
        ModelAssessTaskAutoRespVO result = BeanUtils.toBean(modelAssessTaskAutoDO, ModelAssessTaskAutoRespVO.class);
        String dimension = modelAssessTaskAutoDO.getDimension();
        List<String> list = Arrays.asList(dimension.split(","));
        result.setDimension(list);
        // 标注查询
        List<ModelAssessTaskStoplistDO> modelAssessTaskStoplistDOS = modelingTaskStoplistMapper.selectList(new LambdaQueryWrapper<ModelAssessTaskStoplistDO>()
                .eq(ModelAssessTaskStoplistDO::getTaskId, id)
                .eq(ModelAssessTaskStoplistDO::getDeleted, false));
        List<ModelAssessTaskStoplistRespVO> stoplistRespVOS = BeanUtils.toBean(modelAssessTaskStoplistDOS, ModelAssessTaskStoplistRespVO.class);
        // 提取id
        List<Long> stoplistIds = modelAssessTaskStoplistDOS.stream().map(ModelAssessTaskStoplistDO::getStoplistId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(stoplistIds)) {
            // 查询停用词表 将词表word返回
            LambdaQueryWrapper<ModelAssessStoplistDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(ModelAssessStoplistDO::getId, stoplistIds);
            List<ModelAssessStoplistDO> modelAssessStoplistDOs = modelAssessStoplistMapper.selectList(wrapper);
            Map<Long, ModelAssessStoplistDO> longModelServiceDOMap = cn.iocoder.yudao.framework.common.util.collection.
                    CollectionUtils.convertMap(modelAssessStoplistDOs, ModelAssessStoplistDO::getId);
            stoplistRespVOS.stream().forEach(stoplistRespVO -> {
                ModelAssessStoplistDO modelAssessStoplistDO = longModelServiceDOMap.get(stoplistRespVO.getStoplistId());
                if (modelAssessStoplistDO != null) {
                    stoplistRespVO.setStoplistName(modelAssessStoplistDO.getWord());
                }
            });
        }
        result.setStoplists(stoplistRespVOS);

        if (modelAssessTaskAutoDO.getModelType() == 0) {
            ModelServiceDO modelServiceDO = modelServiceMapper.selectById(modelAssessTaskAutoDO.getModelService());
            if (modelServiceDO != null) {
                result.setModelServiceName(modelServiceDO.getServiceName());
            }
        } else {
            BaseModelDO baseModelDO = baseModelMapper.selectById(modelAssessTaskAutoDO.getModelService());
            if (baseModelDO != null) {
                result.setModelServiceName(baseModelDO.getModelName());
            }
        }
        DatasetDO datasetDO = datasetMapper.selectById(modelAssessTaskAutoDO.getDataset());
        if (datasetDO != null) {
            result.setDatasetName(datasetDO.getDatasetName());
        }
        return result;
    }

    @Override
    public PageResult<ModelAssessTaskAutoDO> getModelAssessTaskAutoPage (ModelAssessTaskAutoPageReqVO pageReqVO) {
        return modelAssessTaskAutoMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<ModelAssessTaskAutoRespVO> getModelAssessTaskAutoPage1 (ModelAssessTaskAutoPageReqVO pageReqVO) {

        PageResult<ModelAssessTaskAutoDO> modelAssessTaskAutoDOPageResult = modelAssessTaskAutoMapper.selectPage(pageReqVO);
        PageResult<ModelAssessTaskAutoRespVO> result = BeanUtils.toBean(modelAssessTaskAutoDOPageResult, ModelAssessTaskAutoRespVO.class);

        if (CollectionUtils.isNotEmpty(result.getList())) {
            // 我的模型获取校验
            List<Long> serviceIds = modelAssessTaskAutoDOPageResult.getList().stream().
                    filter(modelAssessTaskManualDO -> modelAssessTaskManualDO.getModelType() == 0)
                    .map(ModelAssessTaskAutoDO::getModelService).collect(Collectors.toList());
            Map<Long, ModelServiceDO> longModelServiceDOMap = null;
            if (!CollectionUtils.isEmpty(serviceIds)) {
                LambdaQueryWrapper<ModelServiceDO> wrapper = new LambdaQueryWrapper<>();
                wrapper.in(ModelServiceDO::getId, serviceIds);
                List<ModelServiceDO> modelServiceDOS = modelServiceMapper.selectList(wrapper);
                longModelServiceDOMap = cn.iocoder.yudao.framework.common.util.collection.
                        CollectionUtils.convertMap(modelServiceDOS, ModelServiceDO::getId);
            }
            // 人工模型获取校验
            List<Long> serviceForeseeIds = modelAssessTaskAutoDOPageResult.getList().stream().
                    filter(modelAssessTaskManualDO -> modelAssessTaskManualDO.getModelType() == 1)
                    .map(ModelAssessTaskAutoDO::getModelService).collect(Collectors.toList());
            Map<Long, BaseModelDO> serviceForeseeMaps = null;
            if (!CollectionUtils.isEmpty(serviceForeseeIds)) {
                List<BaseModelDO> baseModelDOS = baseModelMapper.selectList(new LambdaQueryWrapper<BaseModelDO>()
                        .in(BaseModelDO::getId, serviceForeseeIds));
                serviceForeseeMaps = cn.iocoder.yudao.framework.common.util.collection.
                        CollectionUtils.convertMap(baseModelDOS, BaseModelDO::getId);
            }
            for (ModelAssessTaskAutoRespVO modelAssessTaskManualRespVO : result.getList()) {
                if (modelAssessTaskManualRespVO.getModelType() == 0 && longModelServiceDOMap != null) {
                    ModelServiceDO modelServiceDO = longModelServiceDOMap.get(modelAssessTaskManualRespVO.getModelService());
                    if (modelServiceDO != null) {
                        modelAssessTaskManualRespVO.setModelServiceName(modelServiceDO.getServiceName());
                    }
                } else if (modelAssessTaskManualRespVO.getModelType() == 1 && serviceForeseeMaps != null) {
                    BaseModelDO baseModelDO = serviceForeseeMaps.get(modelAssessTaskManualRespVO.getModelService());
                    if (baseModelDO != null) {
                        modelAssessTaskManualRespVO.setModelServiceName(baseModelDO.getModelName());
                    }
                }

            }
        }
        return result;
    }

    @Override
    public void dataBackup (Long id) {
        ModelAssessTaskAutoDO modelAssessTaskAutoDO = modelAssessTaskAutoMapper.selectById(id);
        if (modelAssessTaskAutoDO == null) {
            throw exception(MODEL_ASSESS_TASK_AUTO_NOT_EXISTS);
        }
        ModelAssessTaskAutoBackupDO bean = BeanUtils.toBean(modelAssessTaskAutoDO, ModelAssessTaskAutoBackupDO.class);
        bean.setId(null);
        bean.setTaskId(id);
        modelAssessTaskAutoBackupMapper.insert(bean);
        modelAssessTaskAutoDO.setBackupId(bean.getId());
        modelAssessTaskAutoMapper.updateById(modelAssessTaskAutoDO);

        List<ModelAssessTaskStoplistDO> modelAssessTaskStoplistDOS = modelingTaskStoplistMapper.selectList(new LambdaQueryWrapper<ModelAssessTaskStoplistDO>().eq(ModelAssessTaskStoplistDO::getTaskId, id));
        if (CollectionUtils.isEmpty(modelAssessTaskStoplistDOS)) {
            throw exception(MODEL_ASSESS_TASK_STOPLIST_NOT_EXISTS);
        }
        List<ModelAssessTaskStoplistBackupDO> bean1 = BeanUtils.toBean(modelAssessTaskStoplistDOS, ModelAssessTaskStoplistBackupDO.class);
        modelAssessTaskStoplistBackupMapper.insertBatch(bean1);

        ModelAssessTaskAutoInfoPageReqVO modelAssessTaskAutoInfoPageReqVO = new ModelAssessTaskAutoInfoPageReqVO();
        modelAssessTaskAutoInfoPageReqVO.setTaskId(id);
        List<ModelAssessTaskAutoInfoDO> listByTaskId = modelAssessTaskAutoInfoService.getListByTaskId(modelAssessTaskAutoInfoPageReqVO);
        for (ModelAssessTaskAutoInfoDO infoDO : listByTaskId) {
            ModelAssessTaskAutoInfoSaveReqVO modelAssessTaskAutoInfoSaveReqVO = BeanUtils.toBean(infoDO, ModelAssessTaskAutoInfoSaveReqVO.class);
            modelAssessTaskAutoInfoSaveReqVO.setTaskId(id);
            modelAssessTaskAutoInfoBackupService.createModelAssessTaskAutoInfo(modelAssessTaskAutoInfoSaveReqVO);

        }

    }

    @Override
    public void cancelTheBackUp (Long id) {
        modelAssessTaskAutoBackupMapper.delete(new LambdaQueryWrapper<ModelAssessTaskAutoBackupDO>().eq(ModelAssessTaskAutoBackupDO::getTaskId, id));
        ModelAssessTaskAutoDO modelAssessTaskAutoDO = modelAssessTaskAutoMapper.selectById(id);
        if (modelAssessTaskAutoDO != null) {
            modelAssessTaskAutoDO.setBackupId(0L);
            modelAssessTaskAutoMapper.updateById(modelAssessTaskAutoDO);
        }
        modelAssessTaskStoplistBackupMapper.delete(new LambdaQueryWrapper<ModelAssessTaskStoplistBackupDO>().eq(ModelAssessTaskStoplistBackupDO::getTaskId, id));
        modelAssessTaskAutoInfoBackupMapper.delete(new LambdaQueryWrapper<ModelAssessTaskAutoInfoBackupDO>().eq(ModelAssessTaskAutoInfoBackupDO::getTaskId, id));
    }

    /**
     * 通用的根据条件查询 ModelAssessTaskAutoDO 列表并转换为 Map 的方法
     *
     * @param condition   条件，使用 BiFunction 接收 LambdaQueryWrapper 和参数并设置条件
     * @param keyMapper   键映射函数，将 ModelAssessTaskAutoDO 映射为 Map 的键
     * @param valueMapper 值映射函数，将 ModelAssessTaskAutoDO 映射为 Map 的值
     * @param param       查询参数
     * @return 自动评估的 Map 集合
     */
    private Map<Long, String> getModelAssessmentTaskMap (BiFunction<LambdaQueryWrapper<ModelAssessTaskAutoDO>, Long, LambdaQueryWrapper<ModelAssessTaskAutoDO>> condition,
                                                         Function<ModelAssessTaskAutoDO, Long> keyMapper,
                                                         Function<ModelAssessTaskAutoDO, String> valueMapper,
                                                         Long param) {
        if (param == null) {
            return Collections.emptyMap();
        }

        LambdaQueryWrapper<ModelAssessTaskAutoDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper = condition.apply(queryWrapper, param);
//        queryWrapper.in(ModelAssessTaskAutoDO::getStatus, 2, 3);

        List<ModelAssessTaskAutoDO> modelAssessTaskAutoDOS = modelAssessTaskAutoMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(modelAssessTaskAutoDOS)) {
            return Collections.emptyMap();
        }

        return modelAssessTaskAutoDOS.stream().collect(Collectors.toMap(keyMapper, valueMapper));
    }


    /**
     * 根据基础模型 id 获取自动评估
     *
     * @param baseModelId 基础模型 id
     * @return 自动评估的 Map 集合
     */
    @Override
    public Map<Long, String> getModelAssessmentTaskByModelId (Long baseModelId) {
        return getModelAssessmentTaskMap((wrapper, id) -> wrapper.eq(ModelAssessTaskAutoDO::getModelService, id).eq(ModelAssessTaskAutoDO::getModelType, 1),
                ModelAssessTaskAutoDO::getId, ModelAssessTaskAutoDO::getTaskName, baseModelId);
    }


    /**
     * 根据模型服务 id 获取自动评估
     *
     * @param modelServiceId 模型服务 id
     * @return 自动评估的 Map 集合
     */
    @Override
    public Map<Long, String> getModelAssessmentTaskByModelServiceId (Long modelServiceId) {
        return getModelAssessmentTaskMap((wrapper, id) -> wrapper.eq(ModelAssessTaskAutoDO::getModelService, id).eq(ModelAssessTaskAutoDO::getModelType, 0),
                ModelAssessTaskAutoDO::getId, ModelAssessTaskAutoDO::getTaskName, modelServiceId);
    }

    /**
     * 根据 数据集id 获取 自动评估
     *
     * @param datasetId 数据集id
     * @return 自动评估
     */
    @Override
    public Map<Long, String> getModelAssessmentTaskByDatasetId (Long datasetId) {
        return getModelAssessmentTaskMap((wrapper, id) ->
                        wrapper.eq(ModelAssessTaskAutoDO::getDataset, datasetId),
                ModelAssessTaskAutoDO::getId, ModelAssessTaskAutoDO::getTaskName, datasetId);

    }

}
