/**
 * 20241029 ©WANGKANG 1686617586@qq.com
 */

package com.taais.biz.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.taais.biz.constant.BizConstant;
import com.taais.biz.domain.AlgorithmConfigTrack;
import com.taais.biz.domain.vo.AlgorithmConfigTrackVo;
import com.taais.biz.mapper.AlgorithmConfigTrackMapper;
import com.taais.common.core.config.TaaisConfig;
import com.taais.common.core.constant.Constants;
import com.taais.common.core.core.domain.CommonResult;
import com.taais.common.core.utils.DateUtils;
import com.taais.common.core.utils.MapstructUtils;
import com.taais.common.core.utils.StringUtils;
import com.taais.common.orm.core.page.PageQuery;
import com.taais.common.core.core.page.PageResult;
import com.taais.common.orm.core.service.impl.BaseServiceImpl;
import com.taais.system.domain.SysOss;
import com.taais.system.domain.vo.SysOssVo;
import com.taais.system.service.ISysOssService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.taais.biz.mapper.AlgorithmModelTrackMapper;
import com.taais.biz.domain.AlgorithmModelTrack;
import com.taais.biz.domain.bo.AlgorithmModelTrackBo;
import com.taais.biz.domain.vo.AlgorithmModelTrackVo;
import com.taais.biz.service.IAlgorithmModelTrackService;

import static com.taais.biz.domain.table.AlgorithmModelTrackTableDef.ALGORITHM_MODEL_TRACK;
import static com.taais.biz.constant.BizConstant.AlgorithmType;
import static com.taais.biz.utils.ZipUtils.unzip;

/**
 * 算法模型配置Service业务层处理
 *
 * @author wangkang
 * 2024-09-26
 */
@Service
public class AlgorithmModelTrackServiceImpl extends BaseServiceImpl<AlgorithmModelTrackMapper, AlgorithmModelTrack> implements IAlgorithmModelTrackService {
    @Autowired
    private ISysOssService ossService;

    @Autowired
    private AlgorithmConfigTrackServiceImpl algorithmConfigTrackService;

    @Resource
    private AlgorithmModelTrackMapper algorithmModelTrackMapper;

    @Override
    public QueryWrapper query() {
        return super.query().from(ALGORITHM_MODEL_TRACK);
    }

    private QueryWrapper buildQueryWrapper(AlgorithmModelTrackBo algorithmModelTrackBo) {
        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
        queryWrapper.and(ALGORITHM_MODEL_TRACK.ALGORITHM_ID.eq(algorithmModelTrackBo.getAlgorithmId()));
        queryWrapper.and(ALGORITHM_MODEL_TRACK.MODEL_NAME.like(algorithmModelTrackBo.getModelName()));
        queryWrapper.and(ALGORITHM_MODEL_TRACK.MODEL_ADDRESS.eq(algorithmModelTrackBo.getModelAddress()));
        queryWrapper.and(ALGORITHM_MODEL_TRACK.SAMPLE_NUMBER.eq(algorithmModelTrackBo.getSampleNumber()));
        queryWrapper.and(ALGORITHM_MODEL_TRACK.CYCLE_EPOCH.eq(algorithmModelTrackBo.getCycleEpoch()));
        queryWrapper.and(ALGORITHM_MODEL_TRACK.REMARKS.eq(algorithmModelTrackBo.getRemarks()));
        queryWrapper.and(ALGORITHM_MODEL_TRACK.SYSTEM.eq(algorithmModelTrackBo.getSystem()));
        queryWrapper.and(ALGORITHM_MODEL_TRACK.ALGORITHM_TYPE.eq(algorithmModelTrackBo.getAlgorithmType()));

        return queryWrapper;
    }

    /**
     * 查询算法模型配置
     *
     * @param id 算法模型配置主键
     * @return 算法模型配置
     */
    @Override
    public AlgorithmModelTrackVo selectById(Long id) {
        AlgorithmModelTrackVo algorithmModelTrackVo = this.getOneAs(query().where(ALGORITHM_MODEL_TRACK.ID.eq(id)), AlgorithmModelTrackVo.class);

        if (algorithmModelTrackVo == null) {
            return null;
        }

        Long algorithmId = algorithmModelTrackVo.getAlgorithmId();

        AlgorithmConfigTrackVo algorithmConfigTrackVo = algorithmConfigTrackService.selectById(algorithmId);
        String parameterConfig = algorithmConfigTrackVo.getParameterConfig();

        algorithmModelTrackVo.setParameterConfig(parameterConfig);

        return algorithmModelTrackVo;
    }

    /**
     * 查询算法模型配置列表
     *
     * @param algorithmModelTrackBo 算法模型配置Bo
     * @return 算法模型配置集合
     */
    @Override
    public List<AlgorithmModelTrackVo> selectList(AlgorithmModelTrackBo algorithmModelTrackBo) {
        QueryWrapper queryWrapper = buildQueryWrapper(algorithmModelTrackBo);
        return this.listAs(queryWrapper, AlgorithmModelTrackVo.class);
    }

    /**
     * 分页查询算法模型配置列表
     *
     * @param algorithmModelTrackBo 算法模型配置Bo
     * @return 分页算法模型配置集合
     */
    @Override
    public PageResult<AlgorithmModelTrackVo> selectPage(AlgorithmModelTrackBo algorithmModelTrackBo) {
        QueryWrapper queryWrapper = buildQueryWrapper(algorithmModelTrackBo);
        Page<AlgorithmModelTrackVo> page = this.pageAs(PageQuery.build(), queryWrapper, AlgorithmModelTrackVo.class);
        page.getRecords().forEach(model -> {
            Long algorithmId = model.getAlgorithmId();

            AlgorithmConfigTrackVo algorithmConfig = algorithmConfigTrackService.selectById(algorithmId);
            model.setType(algorithmConfig.getType());
            model.setSubsystem(algorithmConfig.getSubsystem());
        });

        return PageResult.build(page);
    }

    /**
     * 新增算法模型配置
     *
     * @param algorithmModelTrackBo 算法模型配置Bo
     * @return 结果:true 操作成功，false 操作失败
     */
    @Override
    public CommonResult<String> insert(AlgorithmModelTrackBo algorithmModelTrackBo) {
        AlgorithmConfigTrackVo algorithmConfigTrackVo = algorithmConfigTrackService.selectById(algorithmModelTrackBo.getAlgorithmId());
        if (algorithmConfigTrackVo.getType().equals(AlgorithmType.REASONING) && ObjectUtil.isEmpty(algorithmModelTrackBo.getModelInputOssId()) && ObjectUtil.isEmpty(algorithmModelTrackBo.getModelPath())) {
            return CommonResult.fail("预测算法必须上传模型文件或指定模型路径！");
        }

        AlgorithmModelTrack algorithmModelTrack = MapstructUtils.convert(algorithmModelTrackBo, AlgorithmModelTrack.class);

        String resourcePath = null;
        if (ObjectUtil.isNotEmpty(algorithmModelTrackBo.getModelInputOssId())) {
            SysOssVo inputOssEntity = ossService.getById(algorithmModelTrackBo.getModelInputOssId());

            String filePath = inputOssEntity.getFileName();
            String localPath = TaaisConfig.getProfile();
            resourcePath = localPath + StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX);


            if (resourcePath.endsWith(".zip")) {
                String modelAddress = resourcePath.substring(0, resourcePath.lastIndexOf("."));
                File file = new File(modelAddress);
                if (!file.exists()) {
                    unzip(resourcePath, modelAddress);
                }
                algorithmModelTrack.setModelAddress(modelAddress);
            } else if (resourcePath.endsWith(".pt")) {
                algorithmModelTrack.setModelAddress(resourcePath);
            } else {
                return CommonResult.fail("模型格式不正确，请上传.zip或.pt文件");
            }
        } // 这是使用ossid上传
        else if (ObjectUtil.isNotEmpty(algorithmModelTrackBo.getModelPath())) { // 这是使用路径上传
            File modelFile = new File(algorithmModelTrackBo.getModelPath());
            if (!modelFile.exists()) {
                return CommonResult.fail("模型路径不存在！");
            }
            algorithmModelTrack.setModelAddress(algorithmModelTrackBo.getModelPath());
        }

        if (AlgorithmType.REASONING.equals(algorithmConfigTrackVo.getType()) || AlgorithmType.TEST.equals(algorithmConfigTrackVo.getType())) {
            algorithmModelTrack.setModelStatus(BizConstant.ModelStatus.END);
        } else if (AlgorithmType.TRAIN.equals(algorithmConfigTrackVo.getType())) {
            algorithmModelTrack.setModelStatus(BizConstant.ModelStatus.NOT_START);
        } else {
            return CommonResult.fail("算法类型不正确");
        }


        algorithmModelTrack.setAlgorithmId(algorithmModelTrackBo.getAlgorithmId());
        algorithmModelTrack.setAlgorithmType(algorithmConfigTrackVo.getAlgorithmName());

        boolean inserted = this.save(algorithmModelTrack); // 使用全局配置的雪花算法主键生成器生成ID值
        if (inserted) {
            return CommonResult.success("新增算法模型配置成功");
        }
        return CommonResult.fail("新增算法模型配置失败");
    }

    /**
     * 修改算法模型配置
     *
     * @param algorithmModelTrackBo 算法模型配置Bo
     * @return 结果:true 更新成功，false 更新失败
     */
    @Override
    public boolean update(AlgorithmModelTrackBo algorithmModelTrackBo) {
        AlgorithmModelTrack algorithmModelTrack = MapstructUtils.convert(algorithmModelTrackBo, AlgorithmModelTrack.class);
        if (ObjectUtil.isNotNull(algorithmModelTrack) && ObjectUtil.isNotNull(algorithmModelTrack.getId())) {
            boolean updated = this.updateById(algorithmModelTrack);
            return updated;
        }
        return false;
    }

    /**
     * 批量删除算法模型配置
     *
     * @param ids 需要删除的算法模型配置主键集合
     * @return 结果:true 删除成功，false 删除失败
     */
    @Transactional
    @Override
    public boolean deleteByIds(Long[] ids) {
        return this.removeByIds(Arrays.asList(ids));
    }

    @Override
    public List<Object> enums() {
        List<AlgorithmModelTrack> algorithmModelTracks = algorithmModelTrackMapper.selectAll();

        List<Object> result = new ArrayList<>();

        for (AlgorithmModelTrack algorithmModelTrack : algorithmModelTracks) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("value", algorithmModelTrack.getId());
            map.put("label", algorithmModelTrack.getModelName());

            AlgorithmConfigTrack config = algorithmConfigTrackService.getById(algorithmModelTrack.getAlgorithmId());
            map.put("algorithmName", config.getAlgorithmName());
            map.put("type", config.getType());
            map.put("subsystem", config.getSubsystem());

            result.add(map);
        }

        return result;
    }

}
