package com.yiboshi.science.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yiboshi.arch.exception.BusinessException;
import com.yiboshi.science.base.BaseServiceImpl;
import com.yiboshi.science.base.Pagination;
import com.yiboshi.science.dao.SystemParameterDAO;
import com.yiboshi.science.entity.SelectListItem;
import com.yiboshi.science.entity.SystemParameter;
import com.yiboshi.science.entity.SystemParameterType;
import com.yiboshi.science.param.dto.SpecDTO;
import com.yiboshi.science.param.dto.SystemParameterDTO;
import com.yiboshi.science.param.query.SystemParameterQueryVO;
import com.yiboshi.science.service.SystemParameterService;
import com.yiboshi.science.service.SystemParameterTypeService;
import com.yiboshi.science.utils.RedisKey;
import com.yiboshi.science.utils.RedisUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 参数表 Service 实现类
 *
 * @author lkl
 * @version 2021-08-26
 */
@Service
@AllArgsConstructor
public class SystemParameterServiceImpl extends BaseServiceImpl<SystemParameterDAO, SystemParameterQueryVO, SystemParameterDTO, SystemParameter> implements SystemParameterService {

    private final RedisUtils redisUtils;

    @Autowired
    private SystemParameterDAO systemParameterDAO;

    @Autowired
    private SystemParameterTypeService systemParameterTypeService;

    @Override
    protected void setCriteriaForQuery(SystemParameterQueryVO vo, QueryWrapper<SystemParameterQueryVO> criteria) {
        if (Objects.nonNull(vo.getTypeId())) {
            criteria.eq("a.type_id", vo.getTypeId());
        }
        if (Objects.nonNull(vo.getParentId())) {
            criteria.eq("a.parent_id", vo.getParentId());
        }
        if (Objects.nonNull(vo.getName())) {
            criteria.like("a.name", vo.getName());
        }
        if (Objects.nonNull(vo.getGbCode())) {
            criteria.eq("a.gb_code", vo.getGbCode());
        }
        if (Objects.nonNull(vo.getTreeCode())) {
            criteria.eq("a.tree_code", vo.getTreeCode());
        }
        if (Objects.nonNull(vo.getDisplayOrder())) {
            criteria.eq("a.display_order", vo.getDisplayOrder());
        }
        if (Objects.nonNull(vo.getNoteState())) {
            criteria.eq("a.note_state", vo.getNoteState());
        }
        if (Objects.nonNull(vo.getSystemCode())) {
            criteria.eq("a.system_code", vo.getSystemCode());
        }
    }

    @Override
    public Pagination<SystemParameterDTO> getListByPage(SystemParameterQueryVO vo) {
        QueryWrapper criteria = new QueryWrapper();
        setCriteriaForQuery(vo, criteria);
        Page<SystemParameterQueryVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        List<SystemParameterDTO> dtoList = systemParameterDAO.getListByPage(page, criteria).getRecords();
        return new Pagination<>(dtoList, page.getTotal(), vo.getPageSize());
    }

    @Override
    public String getParaName(String Id) {
        String name = "";
        if (Objects.nonNull(Id)) {
            SystemParameter systemParameter = getParameterById(Id);
            if (null != systemParameter && Objects.nonNull(systemParameter.getName()))
                name = systemParameter.getName();
        }
        return name;
    }

    /**
     * 根据参数Id获取参数
     *
     * @return
     */
    @Override
    public SystemParameter getParameterById(String id) {
        List<SystemParameter> list = getList();
        if (null == list)
            return null;
        SystemParameter systemParameter = null;
        List<SystemParameter> list1 = list.stream().filter(e -> e.getId().equals(id)).collect(Collectors.toList());
        if (list1.size() > 0)
            systemParameter = list1.stream().findFirst().get();
        return systemParameter;
    }

    /**
     * 获取父级参数列表
     *
     * @param typeId
     * @return
     */
    public List<SystemParameter> getParentListByType(Integer typeId) {
        List<SystemParameter> list = new ArrayList<>();
        SystemParameterType systemParameterType = systemParameterTypeService.getParameterTypeByType(typeId);
        if (null != systemParameterType) {
            list = this.getListByType(systemParameterType.getParentId());
        }
        return list;
    }

    /**
     * 获取父级参数列表
     *
     * @param
     * @return
     */
    public List<SystemParameter> getParentParameterList() {
        return systemParameterDAO.getParentParameterList();
    }

    /**
     * 条件查询结果集
     *
     * @param obj 查询条件
     * @return 数据集合
     */
    public List<SystemParameter> getList(SystemParameter obj) {
        List<SystemParameter> list;
        if (null != obj.getTypeId()) {
            list = this.getListByType(obj.getTypeId());
        } else {
            list = getList();
        }
        if (null != obj.getId())
            list = list.stream().filter(e -> e.getTypeId().equals(obj.getId())).collect(Collectors.toList());
        if (null != obj.getParentId())
            list = list.stream().filter(e -> e.getParentId().equals(obj.getParentId())).collect(Collectors.toList());
        if (null != obj.getName())
            list = list.stream().filter(e -> e.getName().equals(obj.getName())).collect(Collectors.toList());
        if (null != obj.getGbCode())
            list = list.stream().filter(e -> e.getGbCode().equals(obj.getGbCode())).collect(Collectors.toList());
        if (null != obj.getNoteState())
            list = list.stream().filter(e -> e.getNoteState().equals(obj.getNoteState())).collect(Collectors.toList());
        if (null != obj.getSystemCode())
            list = list.stream().filter(e -> e.getSystemCode().equals(obj.getSystemCode())).collect(Collectors.toList());
        if (null != obj.getTreeCode())
            list = list.stream().filter(e -> e.getTreeCode().equals(obj.getTreeCode())).collect(Collectors.toList());
        if (null != obj.getDisplayOrder())
            list = list.stream().filter(e -> e.getDisplayOrder().equals(obj.getDisplayOrder())).collect(Collectors.toList());
        return list;
    }

    @Override
    public Map<String, Object> getParameterList(SystemParameter s) {
        String parent = "";
        SystemParameter systemParameter = new SystemParameter();
        if (null != s.getId()) {
            systemParameter = this.getParameterById(s.getId());
            if (null != systemParameter) {
                s.setParentId(systemParameter.getParentId());
                parent = systemParameter.getParentId();
                s.setId(null);
            }
        }
        List<SelectListItem> list = new ArrayList<>();
        List<SystemParameter> paraList = this.getList(s);
        paraList.forEach((e) -> {
            SelectListItem selectListItem = new SelectListItem(e.getName(), e.getId(), "", true, true, null);
            list.add(selectListItem);
        });
        String par = parent;
        Map<String, Object> data = new HashMap<String, Object>(2) {
            {
                put("parent", par);
                put("data", list);
            }
        };
        return data;
    }

    public List<SelectListItem> getArrayListByType(Integer typeId) {
        List<SystemParameter> parentList = this.getListByType(typeId);
        List<SystemParameter> childList = this.getListByType(typeId + 1);
        List<SelectListItem> list = new ArrayList<>();
        parentList.forEach((e) -> {
            SelectListItem selectListItem = new SelectListItem(e.getName(), e.getId(), "", true, true, new ArrayList<>());
            List<SystemParameter> itemList = childList.stream().filter(f -> e.getId().equals(f.getParentId())).collect(Collectors.toList());
            List<SelectListItem> child = new ArrayList<>();
            itemList.forEach((f) -> {
                SelectListItem item = new SelectListItem(f.getName(), f.getId(), "", true, true, null);
                child.add(item);
            });
            selectListItem.setChildren(child);
            list.add(selectListItem);
        });
        return list;
    }

    public List<SelectListItem> getTreeListByType(Integer typeId) {
        List<SystemParameter> parentList = this.getListByType(typeId);
        List<SystemParameter> childList = this.getListByType(typeId + 1);
        List<SelectListItem> list = new ArrayList<>();
        parentList.forEach((e) -> {
            SelectListItem treeListItem = new SelectListItem(e.getName(), e.getId(), "", false, false, new ArrayList<>());
            List<SystemParameter> itemList = childList.stream().filter(f -> e.getId().equals(f.getParentId())).collect(Collectors.toList());
            List<SelectListItem> child = new ArrayList<>();
            itemList.forEach((f) -> {
                SelectListItem item = new SelectListItem(f.getName(), f.getId(), "", false, false, null);
                child.add(item);
            });
            treeListItem.setChildren(child);
            list.add(treeListItem);
        });
        List<SelectListItem> all = new ArrayList<>();
        all.add(new SelectListItem("全部", "", "", false, false, list));
        return all;
    }

    /**
     * 获取所有参数
     *
     * @return
     */
    public List<SystemParameter> getList() {
        List<SystemParameter> list = null;
        Object obj = redisUtils.get(RedisKey.ParameterList + "all");
        if (null != obj)
            list = (List<SystemParameter>) redisUtils.get(RedisKey.ParameterList + "all");
        else {
            QueryWrapper w = new QueryWrapper();
            w.orderByAsc("display_order");
            list = systemParameterDAO.getList(new QueryWrapper());
            redisUtils.set(RedisKey.ParameterList + "all", list, 7, TimeUnit.DAYS);
        }
        return list;
    }

    /**
     * 根据参数类型获取参数列表
     *
     * @param type
     * @return
     */
    public List<SystemParameter> getListByType(Integer type) {
        List<SystemParameter> list = null;
        Object obj = redisUtils.get(RedisKey.ParameterList + type);
        if (null != obj)
            list = (List<SystemParameter>) redisUtils.get(RedisKey.ParameterList + type);
        if (null == list || list.size() == 0) {
            list = getList().stream().filter(e -> e.getTypeId().equals(type) && e.getNoteState() == 1).collect(Collectors.toList());
            redisUtils.set(RedisKey.ParameterList + type, list, 7, TimeUnit.DAYS);
        }
        return list;
    }

    public SystemParameter getParentModelByChildId(String id) {
        SystemParameter childModel = getParameterById(id);
        if (null == childModel)
            return null;
        if (null == childModel.getParentId() || childModel.getParentId().isEmpty())
            return null;
        return getParameterById(childModel.getParentId());
    }

    public String save(SystemParameterDTO dto) {
        if (null == dto.getId()) {
            return insert(dto);
        } else {
            return update(dto);
        }
    }

    public String insert(SystemParameterDTO dto) {
        SystemParameter parameter = this.convert2Entity(dto);
        parameter.setNoteState(1);
        String id = this.insert(parameter);
        refreshSystemParameter();
        return id;
    }

    public String update(SystemParameterDTO dto) {
        SystemParameter parameter = this.entityById(dto.getId());
        if (null == parameter)
            throw new BusinessException("参数不存在或已删除!");
        String id = this.update(this.convert2Entity(dto));
        refreshSystemParameter();
        return id;
    }

    public String deleteParameterById(String id) {
        SystemParameter parameter = this.entityById(id);
        if (null == parameter)
            throw new BusinessException("参数不存在或已删除!");
        this.deleteById(id);
        refreshSystemParameter();
        return "ok";
    }

    public String refreshSystemParameter() {
        List<SystemParameterType> typeList = systemParameterTypeService.getList();
        typeList.forEach(e -> {
            if (redisUtils.hasKey(RedisKey.ParameterList + e.getTypeId()))
                redisUtils.del(RedisKey.ParameterList + e.getTypeId());
        });
        redisUtils.del(RedisKey.ParameterList + "all");
        redisUtils.del(RedisKey.MultiLevelList);
        redisUtils.del(RedisKey.SpecArrayList);
        redisUtils.del(RedisKey.ProjectKPIList);
        redisUtils.del(RedisKey.ParameterTypeList);
        return "ok";
    }

    public String judgmentTitleLevel(String titleId) {
        List<SystemParameter> parentList = getListByType(6);
        List<SystemParameter> childList = getListByType(7);
        String titleName = null;
        List<SystemParameter> findList = childList.stream().filter(e -> e.getId().equals(titleId)).collect(Collectors.toList());
        if (null == findList || findList.size() <= 0)
            return titleName;
        else {
            SystemParameter childTitle = findList.get(0);
            findList = parentList.stream().filter(e -> e.getId().equals(childTitle.getParentId())).collect(Collectors.toList());
            if (null == findList || findList.size() <= 0)
                return titleName;
            else {
                return findList.get(0).getName();
            }
        }
    }

    public List<SelectListItem> getMultiLevelList(Integer typeId) {
        List<SelectListItem> list = new ArrayList<>();
        Object obj = redisUtils.get(RedisKey.MultiLevelList+typeId);
        if (null != obj)
            list = (List<SelectListItem>) redisUtils.get(RedisKey.MultiLevelList+typeId);
        if (null == list || list.size() == 0) {
            list = new ArrayList<>();
            List<SystemParameter> parentList = this.getListByType(typeId);
            List<SystemParameter> FirstList = new ArrayList<>();
            FirstList = parentList.stream().filter(e -> e.getParentId() == null).collect(Collectors.toList());
            List<SelectListItem> finalList = list;
            FirstList.forEach(e -> {
                SelectListItem treeListItem = new SelectListItem(e.getName(), e.getId(), e.getSystemCode(), false, false, new ArrayList<>());
                finalList.add(treeListItem);
            });
            list.forEach(e -> {
                List<SelectListItem> SecondList = addChildList(parentList, e);
                e.setChildren(SecondList);
                SecondList.forEach(f -> {
                    List<SelectListItem> ThirdList = addChildList(parentList, f);
                    f.setChildren(ThirdList);
                });
            });
            redisUtils.set(RedisKey.MultiLevelList+typeId, list, 7, TimeUnit.DAYS);
        }
        return list;
    }

    private List<SelectListItem> addChildList(List<SystemParameter> parentList, SelectListItem s) {
        List<SelectListItem> SelectList = new ArrayList<>();
        List<SystemParameter> itemList = parentList.stream().filter(f -> f.getParentId() != null && f.getParentId().equals(s.getKey())).collect(Collectors.toList());
        itemList.forEach(e -> {
            SelectListItem treeListItem = new SelectListItem(e.getName(), e.getId(), e.getSystemCode(), false, false, new ArrayList<>());
            SelectList.add(treeListItem);
        });
        return SelectList;
    }

    public List<SpecDTO> getMultiLevelIdList(Integer typeId) {
        List<SpecDTO> list = null;
        Object obj = redisUtils.get(RedisKey.SpecArrayList+typeId);
        if (null != obj)
            list = (List<SpecDTO>) redisUtils.get(RedisKey.SpecArrayList+typeId);
        if (null == list || list.size() == 0) {
            list = systemParameterDAO.getParameterArray(typeId);
            redisUtils.set(RedisKey.SpecArrayList+typeId, list, 7, TimeUnit.DAYS);
        }
        return list;
    }
}
