package com.qxgmat.service.inline;

import com.github.pagehelper.Page;
import com.nuliji.tools.AbstractService;
import com.nuliji.tools.exception.ParameterException;
import com.nuliji.tools.exception.SystemException;
import com.nuliji.tools.mybatis.Example;
import com.qxgmat.data.dao.ExaminationStructMapper;
import com.qxgmat.data.dao.ExerciseStructMapper;
import com.qxgmat.data.dao.entity.ExaminationPaper;
import com.qxgmat.data.dao.entity.ExaminationStruct;
import com.qxgmat.data.dao.entity.ExerciseStruct;
import com.qxgmat.service.ExaminationPaperService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ExaminationStructService extends AbstractService {
    private static final Logger logger = LoggerFactory.getLogger(ExaminationStructService.class);

    @Resource
    private ExaminationStructMapper examinationStructMapper;

    @Resource
    private ExaminationPaperService examinationPaperService;

    /**
     * 根据第三层结构建立paper
     * @param entity
     * @return
     */
    @Transactional
    public ExaminationStruct addPaper(ExaminationStruct entity){
        entity = add(entity);
        if (entity.getLevel() == 3){
            ExaminationPaper paper = examinationPaperService.add(ExaminationPaper.builder()
                    .isAdapt(entity.getIsAdapt())
                    .structTwo(entity.getParentId())
                    .structThree(entity.getId())
                    .title(entity.getTitleZh())
                    .build()
            );
        }
        return entity;
    }

    @Transactional
    public ExaminationStruct editPaper(ExaminationStruct entity){
        entity = add(entity);
        if (entity.getLevel() == 3){
            ExaminationPaper paper = examinationPaperService.getByThree(entity.getId());
            if(paper == null){
                paper = examinationPaperService.add(ExaminationPaper.builder()
                        .isAdapt(entity.getIsAdapt())
                        .structTwo(entity.getParentId())
                        .structThree(entity.getId())
                        .title(entity.getTitleZh())
                        .build()
                );
            }else{
                examinationPaperService.edit(ExaminationPaper.builder()
                        .id(paper.getId())
                        .isAdapt(entity.getIsAdapt())
                        .structTwo(entity.getParentId())
                        .structThree(entity.getId())
                        .title(entity.getTitleZh())
                        .build()
                );
            }
        }
        return entity;
    }

    @Transactional
    public Boolean deletePaper(Integer id){
        Boolean result = delete(id);
        ExaminationPaper paper = examinationPaperService.getByThree(id);
        if(paper != null){
            examinationPaperService.delete(paper.getId());
        }
        return result;
    }

    @Cacheable(value = "examination_struct/main")
    public List<ExaminationStruct> main(){
        List<ExaminationStruct> list = all();
        return list.stream()
                .filter((ExaminationStruct b) -> b.getLevel()<=2)
                .collect(Collectors.toList());
    }

    @Cacheable(value = "examination_struct", key="children/#id/#children")
    public List<ExaminationStruct> children(Integer id, boolean children){
        List<ExaminationStruct> list = all();
        List<Integer> ids = new ArrayList<>();

        return list.stream()
                .filter((ExaminationStruct b) -> {
                    if (b.getParentId().equals(id)){
                        if (children) ids.add(b.getId());
                        return true;
                    }else if(ids.contains(b.getParentId())){
                        if (children) ids.add(b.getId());
                        return true;
                    }
                    return false;
                } )
                .collect(Collectors.toList());
    }

    @Cacheable(value = "examination_struct/all")
    public List<ExaminationStruct> all(){
        Example example = new Example(ExaminationStruct.class);
        example.setOrderByClause("level asc, id asc");
        return select(examinationStructMapper);
    }

    @CacheEvict(value={"examination_struct", "examination_struct/main", "examination_struct/all"}, allEntries = true)
    public ExaminationStruct add(ExaminationStruct struct){
        if(struct.getParentId() > 0){
            ExaminationStruct parent = get(struct.getParentId());
            struct.setLevel(parent.getLevel()+1);
        }else{
            struct.setLevel(1);
        }
        int result = insert(examinationStructMapper, struct);
        struct = one(examinationStructMapper, struct.getId());
        if(struct == null){
            throw new SystemException("添加失败");
        }
        return struct;
    }

    @CacheEvict(value={"examination_struct", "examination_struct/main", "examination_struct/all"}, allEntries = true)
    public ExaminationStruct edit(ExaminationStruct struct){
        ExaminationStruct in = one(examinationStructMapper, struct.getId());
        if(in == null){
            throw new ParameterException("层级不存在");
        }
        int result = update(examinationStructMapper, struct);
        return struct;
    }

    @CacheEvict(value={"examination_struct", "examination_struct/main", "examination_struct/all"}, allEntries = true)
    public boolean delete(Number id){
        ExaminationStruct in = one(examinationStructMapper, id);
        if(in == null){
            throw new ParameterException("层级不存在");
        }
        int result = delete(examinationStructMapper, id);
        return result > 0;
    }

    public ExaminationStruct get(Number id){
        ExaminationStruct in = one(examinationStructMapper, id);

        if(in == null){
            throw new ParameterException("层级不存在");
        }
        return in;
    }

    public Page<ExaminationStruct> select(int page, int pageSize){
        return select(examinationStructMapper, page, pageSize);
    }

    public List<ExaminationStruct> select(Collection ids){
        return select(examinationStructMapper, ids);
    }

}
