package com.njcn.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.constant.BizParamConstant;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.db.constant.DbConstant;
import com.njcn.system.enums.EventResponseEnum;
import com.njcn.system.mapper.EventDictMapper;
import com.njcn.system.pojo.dto.EventReportDictDTO;
import com.njcn.system.pojo.param.EventDictParam;
import com.njcn.system.pojo.po.ReportDict;
import com.njcn.system.pojo.vo.EventReportDictVO;
import com.njcn.system.service.IEventDictService;
import com.njcn.web.factory.PageFactory;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author hany
 * @createTime 2022/10/08
 */
@AllArgsConstructor
@Service
public class EventDictServiceImpl extends ServiceImpl<EventDictMapper, ReportDict> implements IEventDictService {

    private final EventDictMapper eventDictMapper;


    @Override
    public boolean addDict (EventDictParam eventDictParam) {
        checkName(eventDictParam,false);
        ReportDict rptDict = new ReportDict();
        BeanUtils.copyProperties(eventDictParam,rptDict);
        rptDict.setState(DataStateEnum.ENABLE.getCode());
        if (Objects.equals(eventDictParam.getPid(), BizParamConstant.PARENT_ID)){
            rptDict.setPids(BizParamConstant.PARENT_ID);
        }else{
            ReportDict fatherPid = this.lambdaQuery().eq(ReportDict::getId, eventDictParam.getPid()).one();
            if (Objects.equals(fatherPid.getPid(), BizParamConstant.PARENT_ID)) {
                rptDict.setPids(eventDictParam.getPid());
            } else {
                String pidS = fatherPid.getPids();
                rptDict.setPids(pidS + StrPool.COMMA + eventDictParam.getPid());
            }
        }
        return this.save(rptDict);
    }


    @Override
    public boolean updateDict (EventDictParam.DictUpdateParam dictUpdateParam){
        checkName(dictUpdateParam,true);
        ReportDict rptDict = new ReportDict();
        BeanUtils.copyProperties(dictUpdateParam,rptDict);
        rptDict.setPid(rptDict.getPids());
        return this.updateById(rptDict);
    }

    @Override
    public boolean delete (String id){
        LambdaQueryWrapper<ReportDict> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ReportDict::getPid,id).eq(ReportDict::getState,DataStateEnum.ENABLE.getCode());
        int res = this.count(lambdaQueryWrapper);
        if(res>0){
            throw new BusinessException(EventResponseEnum.CHILDREN_EXIT);
        }
        UpdateWrapper<ReportDict> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(ReportDict::getState,DataStateEnum.ENABLE.getCode()).set(ReportDict::getState,DataStateEnum.DELETED.getCode()).eq(ReportDict::getId,id);
        return this.update(updateWrapper);
    }

    @Override
    public Page<ReportDict> getList (EventDictParam.DictQueryParam dictQueryParam) {
        QueryWrapper<ReportDict> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(dictQueryParam)) {
            //查询参数不为空，进行条件填充
            if (StrUtil.isNotBlank(dictQueryParam.getSearchValue())) {
                //字典类型表，提供名称、编码模糊查询
                queryWrapper
                        .and(param -> param.like("report_dict.name",dictQueryParam.getSearchValue())
                                .or().like("report_dict.report_describe",dictQueryParam.getSearchValue()));
            }
            //排序
            if (ObjectUtil.isAllNotEmpty(dictQueryParam.getSortBy(), dictQueryParam.getOrderBy())) {
                queryWrapper.orderBy(true, dictQueryParam.getOrderBy().equals(DbConstant.ASC), StrUtil.toUnderlineCase(dictQueryParam.getSortBy()));
            } else {
                queryWrapper.eq("report_dict.pid",dictQueryParam.getPid());
                //没有排序参数，默认根据sort字段排序，没有排序字段的，根据updateTime更新时间排序
                queryWrapper.orderBy(true, true, "report_dict.update_time");
            }
        }
        queryWrapper.eq("report_dict.state", DataStateEnum.ENABLE.getCode());
        return this.baseMapper.selectPage(new Page<>(PageFactory.getPageNum(dictQueryParam),PageFactory.getPageSize(dictQueryParam)),queryWrapper);
    }

    @Override
    public List<EventReportDictVO> getReportDictList (EventDictParam.DictQueryParam dictQueryParam) {
        QueryWrapper<ReportDict> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(dictQueryParam)) {
            //查询参数不为空，进行条件填充
            if (StrUtil.isNotBlank(dictQueryParam.getSearchValue())) {
                //字典类型表，提供名称、编码模糊查询
                queryWrapper
                        .and(param -> param.like("report_dict.name",dictQueryParam.getSearchValue())
                                .or().like("report_dict.report_describe",dictQueryParam.getSearchValue()));
            }
            //排序
            if (ObjectUtil.isAllNotEmpty(dictQueryParam.getSortBy(), dictQueryParam.getOrderBy())) {
                queryWrapper.orderBy(true, dictQueryParam.getOrderBy().equals(DbConstant.ASC), StrUtil.toUnderlineCase(dictQueryParam.getSortBy()));
            } else {
                //没有排序参数，默认根据sort字段排序，没有排序字段的，根据updateTime更新时间排序
                queryWrapper.orderBy(true, true, "report_dict.update_time");
            }
        }
        queryWrapper.eq("report_dict.state", DataStateEnum.ENABLE.getCode()).eq("report_dict.Type",dictQueryParam.getType());
        List<ReportDict> reportAllDicts = this.baseMapper.selectList(queryWrapper);
        List<ReportDict> reportDicts = new ArrayList<>();
        List<ReportDict> rootList = reportAllDicts.stream().filter(reportDict -> Objects.equals(reportDict.getPid(),"0")).collect(Collectors.toList());
        rootList.forEach(reportDict -> {
            reportDicts.add(reportDict);
            getChild(reportDicts, reportDict, reportAllDicts);
        });
        Map<String, String> map = reportAllDicts.stream().collect(Collectors.toMap(ReportDict::getId, ReportDict::getName));
        List<EventReportDictVO> list = new ArrayList<>();
        reportDicts.forEach(dict -> {
            EventReportDictVO dictVO = new EventReportDictVO();
            BeanUtil.copyProperties(dict, dictVO);
            dictVO.setPidName(map.get(dict.getPid()));
            list.add(dictVO);
        });
        return list;
    }

    private void getChild(List<ReportDict> reportDicts, ReportDict reportDict, List<ReportDict> reportAllDicts) {
        for (ReportDict dict : reportAllDicts) {
            if (dict.getPid().equals(reportDict.getId())) {
                reportDicts.add(dict);
                getChild(reportDicts,dict,reportAllDicts);
            }
        }
    }


    @Override
    public ReportDict getDictById(String id){
        return this.getById(id);
    }


    @Override
    public List<EventReportDictVO> getDictTree(String type) {
        List<EventReportDictVO> list = new ArrayList<>();
        List<EventReportDictDTO> dictList = eventDictMapper.getAllDict(type);
        dictList.forEach(item -> {
            EventReportDictVO dictVO = new EventReportDictVO();
            BeanUtil.copyProperties(item, dictVO);
            list.add(dictVO);
        });
        return list.stream()
                .filter(fun -> Objects.equals(BizParamConstant.PARENT_ID, fun.getPid()))
                .peek(funS -> funS.setChildren(getChildList(funS, list)))
                .collect(Collectors.toList());
    }

    /**
     * 递归组装字典树
     */
    private List<EventReportDictVO> getChildList(EventReportDictVO dictMenu, List<EventReportDictVO> categories) {
        return categories.stream().filter(o -> Objects.equals(o.getPid(), dictMenu.getId()))
                .peek(o -> o.setChildren(getChildList(o, categories)))
                .collect(Collectors.toList());
    }

    /**
     * 名称重复校验
     * @author hany
     * @date 2022/09/27
     */
    private void checkName(EventDictParam eventDictParam,boolean flag){
        LambdaQueryWrapper<ReportDict> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(ReportDict::getName,eventDictParam.getName())
                .eq(ReportDict::getState, DataStateEnum.ENABLE.getCode());
        //修改
        if(flag){
            if(eventDictParam instanceof EventDictParam.DictUpdateParam ){
                lambdaQueryWrapper.ne(ReportDict::getId, ((EventDictParam.DictUpdateParam) eventDictParam).getId());
            }
        }
        int resCount = this.count(lambdaQueryWrapper);
        //大于等于1个则表示重复
        if (resCount >= 1) {
            throw new BusinessException(EventResponseEnum.DIC_NAME_REPEAT);
        }

    }
}
