package com.njcn.gather.err.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gather.detection.pojo.enums.DetectionCodeEnum;
import com.njcn.gather.err.mapper.PqErrSysMapper;
import com.njcn.gather.err.pojo.param.PqErrSysDtlsParam;
import com.njcn.gather.err.pojo.param.PqErrSysParam;
import com.njcn.gather.err.pojo.po.PqErrSys;
import com.njcn.gather.err.pojo.po.PqErrSysDtls;
import com.njcn.gather.err.pojo.vo.PqErrSysDtlsVO;
import com.njcn.gather.err.service.IPqErrSysDtlsService;
import com.njcn.gather.err.service.IPqErrSysService;
import com.njcn.gather.pojo.enums.DetectionResponseEnum;
import com.njcn.gather.report.pojo.enums.PowerIndexEnum;
import com.njcn.gather.system.dictionary.pojo.po.DictData;
import com.njcn.gather.system.dictionary.pojo.po.DictTree;
import com.njcn.gather.system.dictionary.service.IDictDataService;
import com.njcn.gather.system.dictionary.service.IDictTreeService;
import com.njcn.web.factory.PageFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author caozehui
 * @date 2024-11-27
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PqErrSysServiceImpl extends ServiceImpl<PqErrSysMapper, PqErrSys> implements IPqErrSysService {

    private final IPqErrSysDtlsService pqErrSysDtlsService;
    private final IDictTreeService dictTreeService;
    private final IDictDataService dictDataService;

    @Override
    public Page<PqErrSys> listPqErrSys(PqErrSysParam.QueryParam param) {
        QueryWrapper<PqErrSys> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(param)) {
            queryWrapper.between(ObjectUtil.isNotEmpty(param.getStandardTime()), "pq_err_sys.Standard_Time", param.getStandardTime() + "-01-01", param.getStandardTime() + "-12-31").eq(ObjectUtil.isNotEmpty(param.getDevLevel()), "pq_err_sys.Dev_Level", param.getDevLevel());
        }
        queryWrapper.eq("pq_err_sys.state", DataStateEnum.ENABLE.getCode()).orderByDesc("pq_err_sys.Create_Time");
        return this.page(new Page<>(PageFactory.getPageNum(param), PageFactory.getPageSize(param)), queryWrapper);
    }

    @Override
    public PqErrSys getPqErrSysById(String id) {
        PqErrSys pqErrSys = this.lambdaQuery().eq(PqErrSys::getId, id).eq(PqErrSys::getState, DataStateEnum.ENABLE.getCode()).one();
        if (ObjectUtil.isNotNull(pqErrSys)) {
            pqErrSys.setPqErrSysDtlsList(pqErrSysDtlsService.listPqErrSysDtlsByPqErrSysId(id));
        }
        return pqErrSys;
    }

    @Override
    @Transactional
    public boolean addPqErrSys(PqErrSysParam param) {
        param.setStandardName(param.getStandardName().trim());
        this.checkRepeat(param, false);
        PqErrSys pqErrSys = new PqErrSys();
        BeanUtils.copyProperties(param, pqErrSys);
        String id = UUID.randomUUID().toString().replaceAll("-", "");
        pqErrSys.setId(id);
        pqErrSys.setName(generateErrSysName(param));
        pqErrSys.setStandardTime(LocalDate.of(Integer.parseInt(param.getStandardTime()), 1, 1));
        pqErrSys.setState(DataStateEnum.ENABLE.getCode());
        boolean result1 = this.save(pqErrSys);
        boolean result2 = pqErrSysDtlsService.updatePqErrSysDtls(id, param.getPqErrSysDtlsList());
        return result1 && result2;
    }


    @Override
    @Transactional
    public boolean updatePqErrSys(PqErrSysParam.UpdateParam param) {
        param.setStandardName(param.getStandardName().trim());
        this.checkRepeat(param, true);
        PqErrSys pqErrSys = new PqErrSys();
        BeanUtils.copyProperties(param, pqErrSys);
        pqErrSys.setName(generateErrSysName(param));
        pqErrSys.setStandardTime(LocalDate.of(Integer.parseInt(param.getStandardTime()), 1, 1));
        boolean result1 = this.updateById(pqErrSys);
        boolean result2 = pqErrSysDtlsService.updatePqErrSysDtls(param.getId(), param.getPqErrSysDtlsList());
        return result1 && result2;
    }

    @Override
    @Transactional
    public boolean deletePqErrSys(List<String> ids) {
        Integer count = this.baseMapper.getCountBoundByIds(ids);
        if (count > 0) {
            throw new BusinessException(DetectionResponseEnum.ERR_SYS_BOUND_NOT_DELETE);
        }
        pqErrSysDtlsService.deletePqErrSysDtlsByPqErrSysId(ids);
        this.lambdaUpdate().in(PqErrSys::getId, ids).set(PqErrSys::getState, DataStateEnum.DELETED.getCode()).update();
        return true;
    }

    @Override
    public List<PqErrSysDtlsVO> getDetail(String id) {
        List<PqErrSysDtlsVO> result = new ArrayList<>();
        List<PqErrSysDtls> pqErrSysDtls = pqErrSysDtlsService.listPqErrSysDtlsByPqErrSysId(id);
        if (ObjectUtil.isNotEmpty(pqErrSysDtls)) {
            PqErrSysDtlsVO temp = new PqErrSysDtlsVO();
            temp.setDevLevel(this.getById(id).getDevLevel());
            //按照测量项分组
            Map<String, List<PqErrSysDtls>> map = pqErrSysDtls.stream().collect(Collectors.groupingBy(PqErrSysDtls::getErrorType));
            map.forEach((key, value) -> {
                this.visualize(value, temp);
                result.add(temp);
            });
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> listAllPqErrSys() {
        List<PqErrSys> pqErrSysList = this.lambdaQuery()
                .eq(PqErrSys::getEnable, DataStateEnum.ENABLE.getCode())
                .eq(PqErrSys::getState, DataStateEnum.ENABLE.getCode()).list();
        List<Map<String, Object>> result = pqErrSysList.stream().map(pqErrSys -> {
            Map<String, Object> map = new HashMap<>();
            map.put("id", pqErrSys.getId());
            map.put("name", pqErrSys.getName());
            return map;
        }).collect(Collectors.toList());
        return result;
    }

    @Override
    public PqErrSys getPqErrSysByName(String name) {
        return this.lambdaQuery().eq(PqErrSys::getName, name).eq(PqErrSys::getState, DataStateEnum.ENABLE.getCode()).one();
    }

    /**
     * 将检测项可视化
     *
     * @param list
     * @param temp
     */
    private void visualize(List<PqErrSysDtls> list, PqErrSysDtlsVO temp) {
        if (ObjectUtil.isNotEmpty(list)) {
            String type = list.get(0).getErrorType();
            DictTree dictTree = dictTreeService.queryById(type);
            if (ObjectUtil.isNotNull(dictTree)) {
                String[] pids = dictTree.getPids().split(StrPool.COMMA);
                temp.setTestType(dictTree.getName());
                temp.setCol1(dictTreeService.queryById(pids[1]).getName());
                if (pids.length == 3) {
                    temp.setCol2(dictTreeService.queryById(pids[2]).getName());
                }
//                if (pids.length == 2) {
//                    temp.setCol2(dictTreeService.queryById(pids[1]).getName());
//                }
            }

            list.forEach(pqErrSysDtls -> {
                if (ObjectUtil.isNull(temp.getInfo())) {
                    temp.setInfo(new ArrayList<>());
                }
                Map<String, Object> map1 = new HashMap();
                map1.put("startValue", pqErrSysDtls.getStartValue());
                map1.put("startFlag", pqErrSysDtls.getStartFlag());
                map1.put("endValue", pqErrSysDtls.getEndValue());
                map1.put("endFlag", pqErrSysDtls.getEndFlag());
                map1.put("conditionType", pqErrSysDtls.getConditionType());
                map1.put("maxErrorValue", pqErrSysDtls.getMaxErrorValue());
                map1.put("errorValueType", pqErrSysDtls.getErrorValueType());
                temp.getInfo().add(map1);
            });
        }
    }

    /**
     * 生成误差体系名称（标准号+年份+设备等级）
     *
     * @return 误差体系名称
     */
    private String generateErrSysName(PqErrSysParam param) {
        DictData devLevelDictData = dictDataService.getDictDataById(param.getDevLevel());
        if (ObjectUtil.isNotNull(devLevelDictData)) {
            return param.getStandardName() + "-" + param.getStandardTime() + "-" + devLevelDictData.getName();
        }
        throw new BusinessException(DetectionResponseEnum.PQ_ERRSYS_GEN_NAME_ERROR);
    }

    @Override
    public boolean copyPqErrSys(String id) {
        PqErrSys pqErrSys = this.getPqErrSysById(id);
        pqErrSys.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        pqErrSys.setName(pqErrSys.getName() + "_copy");
        pqErrSys.setStandardName(pqErrSys.getStandardName() + "_copy");
        pqErrSys.setStandardTime(LocalDate.of(pqErrSys.getStandardTime().getYear(), 1, 1));
        List<PqErrSysDtlsParam> pqErrSysDtlsParams = BeanUtil.copyToList(pqErrSys.getPqErrSysDtlsList(), PqErrSysDtlsParam.class);
        pqErrSysDtlsService.addPqErrSysDtls(pqErrSys.getId(), pqErrSysDtlsParams);
        return this.save(pqErrSys);
    }

    @Override
    public Map<String, String> getTestItems(String id) {
        List<PqErrSysDtls> pqErrSysDtls = pqErrSysDtlsService.listPqErrSysDtlsByPqErrSysId(id);
        List<String> scriptTypeList = pqErrSysDtls.stream().map(PqErrSysDtls::getScriptType).distinct().collect(Collectors.toList());
        List<DictTree> dictTreeList = dictTreeService.lambdaQuery().in(CollUtil.isNotEmpty(scriptTypeList), DictTree::getId, scriptTypeList).list();
        if (CollUtil.isNotEmpty(dictTreeList)) {
            List<String> pids = dictTreeList.stream().map(DictTree::getPid).collect(Collectors.toList());
            List<DictTree> parentDictTreeList = dictTreeService.listByIds(pids);
            Map<String, String> map = new HashMap<>();
            parentDictTreeList.forEach(dictTree -> {
                if(!dictTree.getCode().equals(PowerIndexEnum.VOLTAGE.getKey())&&!dictTree.getCode().equals(PowerIndexEnum.P.getKey())){
                    map.put(dictTree.getId(), dictTree.getName());
                }
            });
            return map;
        }
        return null;
    }

    /**
     * 检查重复
     *
     * @param param         检测参数
     * @param isExcludeSelf 是否排除自己
     */
    private void checkRepeat(PqErrSysParam param, boolean isExcludeSelf) {
        QueryWrapper<PqErrSys> wrapper = new QueryWrapper<>();
        wrapper.eq("Standard_Name", param.getStandardName())
                .eq("Standard_Time", param.getStandardTime() + "-01-01")
                .eq("Dev_Level", param.getDevLevel())
                .eq("state", DataStateEnum.ENABLE.getCode());
        if (isExcludeSelf) {
            if (param instanceof PqErrSysParam.UpdateParam) {
                wrapper.ne("Id", ((PqErrSysParam.UpdateParam) param).getId());
            }
        }
        int count = this.count(wrapper);
        if (count > 0) {
            throw new BusinessException(DetectionResponseEnum.ERR_SYS_REPEAT);
        }
    }
}
