package com.zt.plat.module.qms.common.data.service;

import cn.hutool.core.collection.CollUtil;
import com.zt.plat.framework.common.exception.ServiceException;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.module.qms.common.data.controller.vo.DataCollectionFieldSaveReqVO;
import com.zt.plat.module.qms.common.data.dal.dataobject.DataCollectionDO;
import com.zt.plat.module.qms.common.data.dal.mapper.DataCollectionMapper;
import com.zt.plat.module.qms.common.data.controller.vo.DataCollectionPageReqVO;
import com.zt.plat.module.qms.common.data.controller.vo.DataCollectionRespVO;
import com.zt.plat.module.qms.common.data.controller.vo.DataCollectionSaveReqVO;
import com.zt.plat.module.qms.core.constant.DataTypeConstant;
import com.zt.plat.module.qms.enums.ErrorCodeConstants;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

import java.util.List;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.qms.enums.ErrorCodeConstants.DATA_COLLECTION_NOT_EXISTS;

/**
 * 数据集 Service 实现类
 *
 * @author 后台管理
 */
@Service
@Validated
public class DataCollectionServiceImpl implements DataCollectionService {

    private int id_path_update_level_limit = 7;

    @Resource private DataCollectionMapper dataCollectionMapper;
    @Resource private DataCollectionFieldService dataCollectionFieldService;


    @Override
    public DataCollectionDO getLatestDataCollectionByKey(String key) {
        LambdaQueryWrapper<DataCollectionDO> query = new LambdaQueryWrapper<>();
        query.eq(DataCollectionDO::getDataKey, key);
        query.eq(DataCollectionDO::getCurrentFlag, "1");
        query.orderByDesc(DataCollectionDO::getUpdateTime);
        query.last("limit 1");
        return dataCollectionMapper.selectOne(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> saveDataCollection(DataCollectionSaveReqVO reqV) {
        String newVersionFlag = reqV.getNewVersionFlag();
        if("1".equals(newVersionFlag))
            return saveDataCollectionWithNewVersion(reqV);
        Long id = reqV.getId();
        DataCollectionDO backData = this.getDataCollection(id);
        if(backData.getCancelFlag() == null || backData.getCancelFlag().equals("-1")){
            reqV.setCancelFlag("0");
            reqV.setCurrentFlag("1");
            reqV.setMainId( id);
        }

        List<DataCollectionFieldSaveReqVO> fieldList = reqV.getFieldList();
        String deleteFieldIds = reqV.getDeleteFieldIds();
        dataCollectionFieldService.saveFields(fieldList, id, "0");
        dataCollectionFieldService.deleteFields(deleteFieldIds, id);
        this.updateDataCollection(reqV);
        return CommonResult.success("保存成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> saveDataCollectionWithNewVersion(DataCollectionSaveReqVO createReqVO) {

        DataCollectionDO dataCollection = BeanUtils.toBean(createReqVO, DataCollectionDO.class);
        dataCollection.setCurrentFlag(0);
        dataCollectionMapper.updateById(dataCollection);

        //创建新版本
        Integer version = dataCollection.getVersion();
        if(version != null)
            version ++;
        else
            version = 1;
        dataCollection.setId(null);
        dataCollection.setVersion(version);
        dataCollection.setCurrentFlag(1);
        dataCollection.setMainId(createReqVO.getMainId());
        dataCollectionMapper.insert(dataCollection);
        //保存字段列表
        Long newId = dataCollection.getId();
        List<DataCollectionFieldSaveReqVO> fieldList = createReqVO.getFieldList();
        dataCollectionFieldService.saveFields(fieldList, newId, "1");
        return CommonResult.success("保存成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<DataCollectionRespVO> saveClassify(DataCollectionSaveReqVO entity) {
        if(ObjectUtils.isEmpty(entity.getParentId()))
            entity.setParentId(0L);
        Long parentId = entity.getParentId();
        //检查同一层级下是否重名
        List<DataCollectionDO> checkList = listByParId(parentId);
        boolean duplicate = false;
        DataCollectionDO duplicateEntity = checkList.stream().filter(e->e.getName().equals(entity.getName())).findFirst().orElse(null);
        if(duplicateEntity != null && !duplicateEntity.getId().equals(entity.getId()))
            duplicate = true;
        if(duplicate)
            throw new ServiceException(ErrorCodeConstants.DATA_COLLECTION_CLASSIFY_DUPLICATE);
        entity.setNodeType(DataTypeConstant.DATA_TYPE_CATEGORY);
        Long id = entity.getId();
        DataCollectionDO dataCollection = BeanUtils.toBean(entity, DataCollectionDO.class);
        if(ObjectUtils.isEmpty(id)){
            dataCollectionMapper.insert(dataCollection);
            id = dataCollection.getId();
        }
        DataCollectionDO backData = this.getDataCollection(id);
        Long parentId_ = backData.getParentId();
        //检查parId，避免父节点设置为本节点的后代节点
        if(parentId_.equals(id))
            throw new ServiceException(ErrorCodeConstants.DATA_COLLECTION_CLASSIFY_PARENT_ERROR);
        String idPath = getIdPath(dataCollection);
        int curIdIndex = idPath.indexOf("/" + id.toString() + "/");
        int parIdIndex = idPath.indexOf("/" + parentId.toString() + "/");
        if(curIdIndex <= parIdIndex)
            throw new ServiceException(ErrorCodeConstants.DATA_COLLECTION_CLASSIFY_PARENT_ERROR);
        dataCollection.setIdPath(idPath);

        //更新后代节点路径
        updateAllIdPath(id, 1);
        dataCollectionMapper.updateById(dataCollection);
        return CommonResult.success(BeanUtils.toBean(dataCollection, DataCollectionRespVO.class));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> updateAllIdPath(Long parentId, Integer level) {
        if(level > id_path_update_level_limit)
            return CommonResult.success("更新完成（超出层数限制："+id_path_update_level_limit+"）");
        List<DataCollectionDO> list = listByParId(parentId);
        DataCollectionDO parEntity = this.getDataCollection(parentId);
        if(list.isEmpty())
            return CommonResult.success("");
        String parIdPath = "/0/";
        if(parEntity != null)
            parIdPath = parEntity.getIdPath();
        for(DataCollectionDO entity : list){
            entity.setIdPath(parIdPath + "/" + entity.getId() + "/");
            dataCollectionMapper.updateById( entity);
            updateAllIdPath(entity.getId(),level+1);
        }
        return CommonResult.success("");
    }

    @Override
    public List<DataCollectionDO> getTreeData() {
        LambdaQueryWrapper<DataCollectionDO> query = new LambdaQueryWrapper<>();
        query.eq(DataCollectionDO::getNodeType, DataTypeConstant.DATA_TYPE_CATEGORY);
        query.orderByAsc(DataCollectionDO::getSortNo);
        return dataCollectionMapper.selectList(query);
    }

    @Override
    public DataCollectionRespVO createDataCollection(DataCollectionSaveReqVO createReqVO) {
        // 插入
        DataCollectionDO dataCollection = BeanUtils.toBean(createReqVO, DataCollectionDO.class);
        dataCollectionMapper.insert(dataCollection);
        // 返回
        return BeanUtils.toBean(dataCollection, DataCollectionRespVO.class);
    }

    @Override
    public void updateDataCollection(DataCollectionSaveReqVO updateReqVO) {
        // 校验存在
        validateDataCollectionExists(updateReqVO.getId());
        // 更新
        DataCollectionDO updateObj = BeanUtils.toBean(updateReqVO, DataCollectionDO.class);
        dataCollectionMapper.updateById(updateObj);
    }

    @Override
    public void deleteDataCollection(Long id) {
        // 校验存在
        validateDataCollectionExists(id);
        // 删除
        dataCollectionMapper.deleteById(id);
    }

    @Override
        public void deleteDataCollectionListByIds(List<Long> ids) {
        // 校验存在
        validateDataCollectionExists(ids);
        // 删除
        dataCollectionMapper.deleteByIds(ids);
        }

    private void validateDataCollectionExists(List<Long> ids) {
        List<DataCollectionDO> list = dataCollectionMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(DATA_COLLECTION_NOT_EXISTS);
        }
    }

    private void validateDataCollectionExists(Long id) {
        if (dataCollectionMapper.selectById(id) == null) {
            throw exception(DATA_COLLECTION_NOT_EXISTS);
        }
    }

    @Override
    public DataCollectionDO getDataCollection(Long id) {
        return dataCollectionMapper.selectById(id);
    }

    @Override
    public PageResult<DataCollectionDO> getDataCollectionPage(DataCollectionPageReqVO pageReqVO) {
        return dataCollectionMapper.selectPage(pageReqVO);
    }

    @Override
    public List<DataCollectionDO> listByParId(Long parId) {
        LambdaQueryWrapper<DataCollectionDO> query = new LambdaQueryWrapper<>();
        query.eq(DataCollectionDO::getParentId, parId);
        query.ne(DataCollectionDO::getCancelFlag, -1);
        return dataCollectionMapper.selectList(query);
    }


    private String getIdPath(DataCollectionDO entity){
        String parIdPath = "";
        if(ObjectUtils.isEmpty(entity.getParentId()) || 0L == entity.getParentId())
            parIdPath = "/0/";
        DataCollectionDO parEntity = this.getDataCollection(entity.getParentId());
        if(parEntity != null){
            parIdPath = parEntity.getIdPath();
        }
        return parIdPath + entity.getId() + "/";
    }
}