package com.tykj.dev.device.matching.service.impl;

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.device.matching.repository.MatchingDeviceLibraryDao;
import com.tykj.dev.device.matching.service.MatchingDeviceLibraryService;
import com.tykj.dev.device.matching.subject.domin.MatchingDeviceLibrary;
import com.tykj.dev.device.matching.subject.vo.MatchingDeviceSelectVo;
import com.tykj.dev.device.user.subject.service.UserPublicService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.misc.exception.ApiException;
import com.tykj.dev.misc.utils.PageUtil;
import com.tykj.dev.misc.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author dengdiyi
 */
@Service
public class MatchingDeviceLibraryServiceImpl implements MatchingDeviceLibraryService {

    @Autowired
    private MatchingDeviceLibraryDao matchingDeviceLibraryDao;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private UserPublicService userPublicService;

    @Override
    public MatchingDeviceLibrary addEntity(MatchingDeviceLibrary matchingDeviceLibraryEntity) {
        return matchingDeviceLibraryDao.save(matchingDeviceLibraryEntity);
    }

    @Override
    public MatchingDeviceLibrary getOne(Integer id) {
        Optional<MatchingDeviceLibrary> matchingDeviceLibraryEntity = matchingDeviceLibraryDao.findById(id);
        return matchingDeviceLibraryEntity.orElse(null);
    }

    @Override
    public MatchingDeviceLibrary update(MatchingDeviceLibrary matchingDeviceLibraryEntity) {
        return matchingDeviceLibraryDao.save(matchingDeviceLibraryEntity);
    }

    @Override
    public void delete(Integer id) {
        matchingDeviceLibraryDao.deleteById(id);
    }

    @Override
    public Page<MatchingDeviceLibrary> getPage(MatchingDeviceSelectVo matchingDeviceSelectVo, Pageable pageable) {
        PredicateBuilder<MatchingDeviceLibrary> predicateBuilder = getPredicate(matchingDeviceSelectVo);
        Integer selectUnitId = matchingDeviceSelectVo.getUnitId();
        Integer selectAreaId = matchingDeviceSelectVo.getAreaId();
        if (selectAreaId==null){
            //如果areaId和unitId都传Null,返回当前单位的配套设备
            if (selectUnitId==null){
                predicateBuilder.eq("createUnit", userUtils.getCurrentUserUnitName());
                return matchingDeviceLibraryDao.findAll(predicateBuilder.build(), matchingDeviceSelectVo.getPageable());
            }
            //如果areaId为Null,unitId不为null,返回对应单位的配套设备
            else {
                String unitName = userPublicService.findByUnitsToname(selectUnitId);
                predicateBuilder.eq("createUnit", unitName);
                return matchingDeviceLibraryDao.findAll(predicateBuilder.build(), matchingDeviceSelectVo.getPageable());
            }
        }
        //areaId不为null,返回该区域下所有单位的配套设备
        else {
            //获取区域等级
            Integer selectLevel = userPublicService.getArea(selectAreaId).getType();
            //获取区域下所有单位名称
            List<String> units = userPublicService.findAllUnitNameByAreaId(selectAreaId);
            //如果是市或县，筛选出创建单位在units中的设备
            if (selectLevel==3||selectLevel==2){
                List<MatchingDeviceLibrary> resultList = matchingDeviceLibraryDao.findAll().stream()
                        .filter(matchingDeviceLibraryEntity -> units.contains(matchingDeviceLibraryEntity.getCreateUnit()))
                        .collect(Collectors.toList());
                return PageUtil.getPerPage(matchingDeviceSelectVo.getPage(),matchingDeviceSelectVo.getSize(),resultList,pageable);
            }
            //如果是省，直接返回全部设备
            if (selectLevel==1){
                List<MatchingDeviceLibrary> resultList = matchingDeviceLibraryDao.findAll();
                return PageUtil.getPerPage(matchingDeviceSelectVo.getPage(),matchingDeviceSelectVo.getSize(),resultList,pageable);
            }
            else{
                throw new ApiException(ResultUtil.failed("单位等级只能为1,2,3"));
            }
        }
    }

    /**
     * @return 所有类型
     */
    @Override
    public List<String> getAllModel() {
        Set<String> models = new HashSet<>();
        matchingDeviceLibraryDao.findAll().forEach(matchingDeviceLibrary -> models.add(matchingDeviceLibrary.getModel()));
        return new ArrayList<>(models);
    }

    /**
     * @return 所有名称
     */
    @Override
    public List<String> getAllName() {
        Set<String> names = new HashSet<>();
        matchingDeviceLibraryDao.findAll().forEach(matchingDeviceLibrary -> names.add(matchingDeviceLibrary.getName()));
        return new ArrayList<>(names);
    }

    /**
     * @param matchingDeviceSelectVo 配套设备查询vo
     * 创建通用查询条件筛选器
     */
    private PredicateBuilder<MatchingDeviceLibrary> getPredicate(MatchingDeviceSelectVo matchingDeviceSelectVo){
        PredicateBuilder<MatchingDeviceLibrary> predicateBuilder = Specifications.and();
        if (matchingDeviceSelectVo.getType()!=null){
            predicateBuilder.eq("type",matchingDeviceSelectVo.getType());
        }
        if (matchingDeviceSelectVo.getModel()!=null){
            predicateBuilder.eq("model",matchingDeviceSelectVo.getModel());
        }
        if (matchingDeviceSelectVo.getName()!=null){
            predicateBuilder.eq("name",matchingDeviceSelectVo.getName());
        }
        if (matchingDeviceSelectVo.getContent()!=null){
            Class<MatchingDeviceLibrary> taskEntityClass = MatchingDeviceLibrary.class;
            Field[] declaredFields = taskEntityClass.getDeclaredFields();
            PredicateBuilder<MatchingDeviceLibrary> p = Specifications.or();
            for (Field field : declaredFields) {
                if (field.getType().equals(String.class)&&field.getAnnotation(Transient.class)==null) {
                    p.like(field.getName(), "%" + matchingDeviceSelectVo.getContent() + "%");
                }
            }
            predicateBuilder.predicate(p.build());
        }
        return predicateBuilder;
    }
}
