package com.yonge.cooleshow.biz.dal.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.yonge.cooleshow.biz.dal.dao.SubjectDao;
import com.yonge.cooleshow.biz.dal.entity.Subject;
import com.yonge.cooleshow.biz.dal.queryInfo.SubjectQueryInfo;
import com.yonge.cooleshow.biz.dal.service.SubjectService;
import com.yonge.cooleshow.common.enums.CacheNameEnum;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.page.PageInfo;
import com.yonge.toolset.base.util.StringUtil;
import com.yonge.toolset.mybatis.dal.BaseDAO;
import com.yonge.toolset.mybatis.service.impl.BaseServiceImpl;

@Service
public class SubjectServiceImpl extends BaseServiceImpl<Long, Subject> implements SubjectService {

    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public BaseDAO<Long, Subject> getDAO() {
        return subjectDao;
    }

    @Override
    public List<Subject> findBySubjectByIdList(List<Long> subjectIdList) {
        return subjectDao.findBySubjectIds(subjectIdList);
    }

    @Override
    public List<Subject> findBySubjectByIdList(String subjectIdList) {
        return subjectDao.findBySubjectByIdList(subjectIdList);
    }

    @Override
    public PageInfo<Subject> queryPageTree(SubjectQueryInfo queryInfo) {
        PageInfo<Subject> pageInfo = queryPage(queryInfo);
        for (Subject subject : pageInfo.getRows()) {
            subject = getTree(subject, queryInfo.getDelFlag());
        }
        return pageInfo;
    }

    @Override
    public int deleteById(Long id) {
        List<Subject> subjectList = subjectDao.findByParentId(id);
        if (subjectList != null && subjectList.size() > 0) {
            throw new BizException("该分类下已创建下级，无法删除");
        }
        Boolean flag = subjectDao.useSubject(id);
        if (flag) {
            throw new BizException("该分类有用户使用，无法删除");
        }
        return subjectDao.deleteById(id);
    }

    @Override
    public void upSetSubject(Subject subject) {
        Subject subjectByCode = subjectDao.queryByCode(subject.getCode());
        if (subjectByCode != null && subjectByCode.getId() != subject.getId()) {
            throw new BizException("声部编码已存在，请修改编码");
        }

        Subject subjectByName = subjectDao.queryByName(subject.getName());
        if (subjectByName != null && subjectByName.getId() != subject.getId()) {
            throw new BizException("名称已存在，请修改名称");
        }

        if (subject.getId() != null) {
            subject.setUpdateTime(new Date());
            subjectDao.update(subject);
        } else {
            subjectDao.insert(subject);
        }
    }

    @Override
    public List<Subject> subjectSelect(String type, String userExtSubjectIds) {
        Object cacheRes = redissonClient.getBucket(CacheNameEnum.SUBJECT_ITEM.getRedisKey(type)).get();
        if (null != cacheRes) {
            List<Subject> resList = (List<Subject>) cacheRes;
            if (!CollectionUtils.isEmpty(resList)) {
                return resList;
            }
        }

        List<Subject> parents;
        List<Subject> subjects;

        if(StringUtil.isEmpty(type)){
            List<Subject> allList = subjectDao.findAll(new HashMap<>());

            parents = allList.stream()
                    .filter(o -> (null == o.getParentSubjectId() || o.getParentSubjectId().equals(0L)))
                    .collect(Collectors.toList());

            subjects = allList.stream()
                    .filter(o -> !(null == o.getParentSubjectId() || o.getParentSubjectId().equals(0L)))
                    .collect(Collectors.toList());
        }else{
            subjects = subjectDao.subjectSelect(type);
            
            if(subjects == null){
            	subjects = new ArrayList<Subject>();
            }
            if(StringUtils.isNotBlank(userExtSubjectIds)){
            	List<Long> idList = subjects.stream().map(t -> t.getId()).collect(Collectors.toList());
            	
            	List<Subject> extSubjectList = findBySubjectByIdList(userExtSubjectIds);
            	for(Subject ext : extSubjectList){
            		if(!idList.contains(ext.getId())){
            			subjects.add(ext);
            		}
            	}
            }

            List<Long> parentIds = subjects.stream().map(Subject::getParentSubjectId).collect(Collectors.toList());

            if(CollectionUtils.isEmpty(parentIds)){
                return subjectSelect(null, null);
            }
            parents = findBySubjectByIdList(parentIds);
        }


        for (Subject parent : parents) {
            if (null == parent.getId()) {
                continue;
            }
            for (Subject subject : subjects) {
                if (null == subject.getId() || null == subject.getParentSubjectId()) {
                    continue;
                }
                if (subject.getParentSubjectId().equals(parent.getId())) {
                    List<Subject> children = parent.getSubjects();
                    if (CollectionUtils.isEmpty(children)) {
                        children = new ArrayList<>();
                    }
                    children.add(subject);
                    parent.setSubjects(children);
                }
            }
        }

        redissonClient.getBucket(CacheNameEnum.SUBJECT_ITEM.getRedisKey(type)).set(parents,
                CacheNameEnum.STUDENT_SUBJECT_ITEM.getDuration().toMinutes(),TimeUnit.MINUTES);
        return parents;
    }

    /***
     * 查询声部树
     * @param: sub
     * @param: yesOrNoEnum
     * @updateTime 2022/4/6 11:33
     * @return: com.yonge.cooleshow.biz.dal.entity.Subject
     */
    private Subject getTree(Subject sub, Boolean delFlag) {
        //得到根节点对象
        //获取子节点list
        List<Subject> subjects = subjectDao.findByParentId(sub.getId());
        //如果存在子节点
        if (subjects != null && subjects.size() > 0) {
            //将子节点list放入父节点对象
            sub.setSubjects(subjects);
            //遍历子节点....
            for (Subject subject : subjects) {
                getTree(subject, delFlag);
            }
        }
        return sub;
    }
}
