package com.njcn.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.exception.BusinessException;
import com.njcn.db.constant.DbConstant;
import com.njcn.redis.pojo.enums.AppRedisKey;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.system.enums.SystemResponseEnum;
import com.njcn.system.mapper.EleEpdPqdMapper;
import com.njcn.system.pojo.dto.EpdDTO;
import com.njcn.system.pojo.param.EleEpdPqdParam;
import com.njcn.system.pojo.po.DictData;
import com.njcn.system.pojo.po.EleEpdPqd;
import com.njcn.system.pojo.vo.EleEpdPqdListVO;
import com.njcn.system.pojo.vo.EleEpdPqdVO;
import com.njcn.system.service.IDictDataService;
import com.njcn.system.service.IEleEpdPqdService;
import com.njcn.web.factory.PageFactory;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xuyang
 * @since 2023-05-24
 */
@Service
@RequiredArgsConstructor
public class EleEpdPqdServiceImpl extends ServiceImpl<EleEpdPqdMapper, EleEpdPqd> implements IEleEpdPqdService {

    private final IDictDataService idictDataService;

    private final RedisUtil redisUtil;

    @Override
    public void refreshEpdPqdDataCache() {
        Map<String,String> map = new HashMap<>(16);
        List<EpdDTO> list = findAll();
        list.forEach(item->{
            map.put(item.getDictName(),item.getTableName());
        });
        redisUtil.saveByKey(AppRedisKey.ELE_EPD_PQD,map);
    }

    @Override
    public void saveData(List<EleEpdPqdParam> eleEpdPqdParam) {
        List<EleEpdPqd> list = eleEpdPqdParam.stream().map(item->{
            EleEpdPqd eleEpdPqd = new EleEpdPqd();
            BeanUtils.copyProperties(item,eleEpdPqd);
            if (StringUtils.isBlank(item.getType())){
                eleEpdPqd.setType("");
            }
            eleEpdPqd.setStatus(1);
            if (CollectionUtil.isNotEmpty(item.getStatMethod())){
                eleEpdPqd.setStatMethod(String.join(",", item.getStatMethod()));
            }
            return eleEpdPqd;
        }).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(list)){
            boolean result = this.saveBatch(list,1000);
            if (result) {
                refreshEpdPqdDataCache();
            }
        }
    }

    @Override
    public EleEpdPqd add(EleEpdPqdParam eleEpdPqdParam) {
        checkEleEpdPqdParam(eleEpdPqdParam,false);
        EleEpdPqd eleEpdPqd = new EleEpdPqd();
        BeanUtils.copyProperties(eleEpdPqdParam,eleEpdPqd);
        if (CollectionUtil.isNotEmpty(eleEpdPqdParam.getStatMethod())){
            eleEpdPqd.setStatMethod(String.join(",", eleEpdPqdParam.getStatMethod()));
        }
        if (Objects.isNull(eleEpdPqdParam.getPhase())){
            eleEpdPqd.setPhase("T");
        }
        eleEpdPqd.setStatus(1);
        boolean result = this.save(eleEpdPqd);
        if (result) {
            refreshEpdPqdDataCache();
        }
        return eleEpdPqd;
    }

    @Override
    public void delete(String id) {
        EleEpdPqd eleEpdPqd = this.lambdaQuery().eq(EleEpdPqd::getId,id).one();
        eleEpdPqd.setStatus(0);
        boolean result = this.updateById(eleEpdPqd);
        if (result) {
            refreshEpdPqdDataCache();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(EleEpdPqdParam.EleEpdPqdUpdateParam updateParam) {
        checkEleEpdPqdParam(updateParam,true);
        EleEpdPqd eleEpdPqd = new EleEpdPqd();
        BeanUtils.copyProperties(updateParam,eleEpdPqd);
        if (CollectionUtil.isNotEmpty(updateParam.getStatMethod())){
            eleEpdPqd.setStatMethod(String.join(",", updateParam.getStatMethod()));
        }
        if (Objects.isNull(updateParam.getPhase())){
            eleEpdPqd.setPhase("T");
        }
        boolean result = this.updateById(eleEpdPqd);
        if (result) {
            refreshEpdPqdDataCache();
        }
    }

    @Override
    public Page<EleEpdPqdVO> eleEpdPqdList(EleEpdPqdParam.EleEpdPqdQueryParam queryParam) {
        QueryWrapper<EleEpdPqdVO> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(queryParam)) {
            //查询参数不为空，进行条件填充
            if (StrUtil.isNotBlank(queryParam.getSearchValue())) {
                //部门根据名称模糊查询
                queryWrapper
                        .and(param -> param.like("ele_epd_pqd.Name", queryParam.getSearchValue())
                                      .or().like("ele_epd_pqd.Other_Name", queryParam.getSearchValue())
                                      .or().like("ele_epd_pqd.Show_Name", queryParam.getSearchValue()));
            }
            //排序
            if (ObjectUtil.isAllNotEmpty(queryParam.getSortBy(), queryParam.getOrderBy())) {
                queryWrapper.orderBy(true, queryParam.getOrderBy().equalsIgnoreCase(DbConstant.ASC), StrUtil.toUnderlineCase(queryParam.getSortBy()));
            } else {
                //默认根据sort排序
                queryWrapper.orderBy(true, true, "data_type","Sort");
            }
        }
        if (CollectionUtil.isNotEmpty(queryParam.getDataType())){
            queryWrapper.in("ele_epd_pqd.data_type", queryParam.getDataType());
        }
        if (CollectionUtil.isNotEmpty(queryParam.getClassId())){
            queryWrapper.in("ele_epd_pqd.Class_Id", queryParam.getClassId());
        }
        queryWrapper.eq("ele_epd_pqd.status", 1);
        return this.baseMapper.page(new Page<>(PageFactory.getPageNum(queryParam), PageFactory.getPageSize(queryParam)), queryWrapper);
    }

    @Override
    public List<EleEpdPqd> dictMarkByDataType(String dataType) {
        LambdaQueryWrapper<EleEpdPqd> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EleEpdPqd::getDataType,dataType);
        return this.baseMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public Map<String, String> saveEvt(List<EleEpdPqdParam> eleEpdPqdParam) {
        List<EleEpdPqd> list = eleEpdPqdParam.stream().map(item->{
            EleEpdPqd eleEpdPqd = new EleEpdPqd();
            BeanUtils.copyProperties(item,eleEpdPqd);
            if (StringUtils.isBlank(item.getType())){
                eleEpdPqd.setType("");
            }
            return eleEpdPqd;
        }).collect(Collectors.toList());
        this.saveBatch(list,1000);
        List<String> nameList = eleEpdPqdParam.stream().map(EleEpdPqdParam::getName).collect(Collectors.toList());
        List<EleEpdPqd> list1 = this.lambdaQuery().in(EleEpdPqd::getName,nameList).list();
        Map<String,String> map = new HashMap<>(16);
        list1.forEach(item->{
            map.put(item.getName(),item.getId());
        });
        return map;
    }

    @Override
    public EleEpdPqd selectById(String id) {
        return this.lambdaQuery().eq(EleEpdPqd::getId,id).one();
    }

    @Override
    public List<EleEpdPqdListVO> selectAll() {

        List<EleEpdPqdListVO> vos = new ArrayList<>();

        this.getBaseMapper().selectList(null);
        List<EleEpdPqd> eleEpdPqds = this.baseMapper.selectList(null);
        Map<String, List<EleEpdPqd>> collect = eleEpdPqds.stream().collect(Collectors.groupingBy(EleEpdPqd::getDataType));
        collect.forEach((k,v)->{
            EleEpdPqdListVO vo = new EleEpdPqdListVO();
            vo.setDataType(k);
            vo.setEleEpdPqdVOS(v);
            DictData dicDataById = idictDataService.getDicDataById(vo.getDataType());
            vo.setDataTypeName(dicDataById.getName());
            vos.add(vo);
        });

        return vos;
    }

    @Override
    public List<EleEpdPqd> selectByIds(List<String> ids) {
        return this.lambdaQuery().in(EleEpdPqd::getId,ids).orderByAsc(EleEpdPqd::getSort).list();
    }

    @Override
    public List<EleEpdPqd> judgeExist(String name, String dataType) {
        LambdaQueryWrapper<EleEpdPqd> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EleEpdPqd::getDataType,dataType).eq(EleEpdPqd::getName,name).eq(EleEpdPqd::getStatus,1);
        return this.baseMapper.selectList(lambdaQueryWrapper);
    }

    @Override
    public EleEpdPqd findByParam(String name, String dataType, String phase) {
        LambdaQueryWrapper<EleEpdPqd> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(EleEpdPqd::getDataType,dataType).eq(EleEpdPqd::getName,name).eq(EleEpdPqd::getPhase,phase).eq(EleEpdPqd::getStatus,1);
        return this.baseMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public List<EpdDTO> findAll() {
        List<EpdDTO> removeList = new ArrayList<>(),addList = new ArrayList<>();
        List<EpdDTO> list = this.baseMapper.findAll();
        if (CollectionUtil.isNotEmpty(list)){
            list.forEach(item->{
                if (!Objects.isNull(item.getHarmStart()) && !Objects.isNull(item.getHarmEnd())){
                    removeList.add(item);
                    for (int i = item.getHarmStart(); i <= item.getHarmEnd(); i++) {
                        EpdDTO epdDTO = new EpdDTO();
                        epdDTO.setDictName(item.getDictName() + "_" + i);
                        epdDTO.setTableName(item.getTableName());
                        addList.add(epdDTO);
                    }
                }
            });
            if (CollectionUtil.isNotEmpty(removeList)){
                list.removeAll(removeList);
            }
            if (CollectionUtil.isNotEmpty(addList)){
                list.addAll(addList);
            }
        }
        return list;
    }

    @Override
    public List<EleEpdPqd> selectByClassId(String classId) {
        return this.lambdaQuery().eq(EleEpdPqd::getClassId,classId).list();
    }

    /**
     * 校验参数，
     * 1.检查是否存在相同名称的菜单
     * 名称 && 路径做唯一判断
     */
    private void checkEleEpdPqdParam(EleEpdPqdParam eleEpdPqdParam, boolean isExcludeSelf) {
        LambdaQueryWrapper<EleEpdPqd> eleEpdPqdLambdaQueryWrapper = new LambdaQueryWrapper<>();
        eleEpdPqdLambdaQueryWrapper
                .eq(EleEpdPqd::getName, eleEpdPqdParam.getName())
                .eq(EleEpdPqd::getPhase, eleEpdPqdParam.getPhase())
                .eq(EleEpdPqd::getClassId,eleEpdPqdParam.getClassId())
                .eq(EleEpdPqd::getDataType, eleEpdPqdParam.getDataType())
                .eq(EleEpdPqd::getStatus,1);
        //更新的时候，需排除当前记录
        if (isExcludeSelf) {
            if (eleEpdPqdParam instanceof EleEpdPqdParam.EleEpdPqdUpdateParam) {
                eleEpdPqdLambdaQueryWrapper.ne(EleEpdPqd::getId, ((EleEpdPqdParam.EleEpdPqdUpdateParam) eleEpdPqdParam).getId());
            }
        }
        int countByAccount = this.count(eleEpdPqdLambdaQueryWrapper);
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            throw new BusinessException(SystemResponseEnum.DICT_DATA_NAME_REPEAT);
        }
    }
}
