package com.rf.psychological.institution.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.rf.psychological.group.dao.repository.GroupAuthRepository;
import com.rf.psychological.group.dao.repository.GroupInfoRepository;
import com.rf.psychological.institution.repository.InstitutionAuthRepository;
import com.rf.psychological.institution.repository.InstitutionUserRepository;
import com.rf.psychological.plan.dao.model.TestPlanEntity;
import com.rf.psychological.plan.service.TestPlanService;
import com.rf.psychological.scale.service.UserRecordService;
import com.rf.psychological.user.dao.model.UserEntity;
import com.rf.psychological.dao.vo.SaveInstitutionVO;
import com.rf.psychological.enums.UserRole;
import com.rf.psychological.enums.UserStatus;
import com.rf.psychological.group.dao.model.GroupEntity;
import com.rf.psychological.group.service.GroupInfoService;
import com.rf.psychological.institution.model.InstitutionEntity;
import com.rf.psychological.institution.repository.InstitutionRepository;
import com.rf.psychological.institution.service.InstitutionService;
import com.rf.psychological.user.dao.repository.UserRepository;
import com.rf.psychological.user.service.UserService;
import com.rf.psychological.utils.Constant;
import com.rf.psychological.utils.PageRequestUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.persistence.criteria.Predicate;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class InstitutionServiceImpl implements InstitutionService {

    @Autowired
    private InstitutionRepository institutionRepository;

    @Autowired
    private InstitutionUserRepository institutionUserRepository;

    @Autowired
    private InstitutionAuthRepository institutionAuthRepository;

    @Autowired
    private GroupInfoRepository groupInfoRepository;

    @Autowired
    private GroupAuthRepository groupAuthRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private TestPlanService testPlanService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserRecordService userRecordService;

    @Autowired
    private GroupInfoService groupInfoService;


    @Override
    public void save(InstitutionEntity institutionEntity) {
        this.institutionRepository.save(institutionEntity);
    }

    @Override
    public InstitutionEntity findByInstitutionId(String institutionId) {
        return institutionRepository.findByInstitutionNo(institutionId);
    }


    @Override
    public List<InstitutionEntity> findAllInstitutionByName(int pageNum, int pageSize, String searchKey) {
        int beginIndex = (pageNum - 1) * pageSize;
        return this.institutionRepository.findAllInstitutionByName(beginIndex, pageSize, searchKey);
    }

    @Override
    public int allInstitutionNum(String searchKey) {
        return this.institutionRepository.allInstitutionNum(searchKey);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "institution",allEntries = true)
    public void delInstitution(String institutionId) {
        //获取机构信息
        Optional<InstitutionEntity> institutionRepositoryById = institutionRepository.findById(institutionId);
        if (institutionRepositoryById.isPresent()) {
            InstitutionEntity institutionEntity = institutionRepositoryById.get();
            String institutionNo = institutionEntity.getInstitutionNo();
            if ("10000".equals(institutionNo)) {
                return;
            }
            //删除机构
            this.institutionRepository.deleteById(institutionId);
            //删除机构管理员
            institutionUserRepository.deleteAllByInstitutionNo(institutionNo);
            //删除机构权限
            institutionAuthRepository.deleteAuthDataByInstitutionNo(institutionNo);
            //删除机构下的组
            List<GroupEntity> groupInfo = groupInfoRepository.findAllByInstitutionNo(institutionNo);
            groupInfoRepository.deleteAllByInstitutionNo(institutionNo);
            //删除机构下的组权限
            List<String> groupIds = groupInfo.stream().map(GroupEntity::getId).collect(Collectors.toList());
            groupAuthRepository.deleteGroupAuthBath(groupIds);
            //删除测试计划，测试计划内容。测试计划内的用户
            List<TestPlanEntity> testPlanEntities = testPlanService.findAllByInstitutionNo(institutionNo);
            testPlanService.deleteInBatch(testPlanEntities);
            //删除用户信息
            userRepository.deleteAllByInstitutionNo(institutionNo);
            //删除测试记录
            userRecordService.deleteBatchByInstitution(institutionNo);
        }

    }

    /**
     * 分页查询
     * @param pageNum 页码
     * @param pageSize 数量
     * @param searchKey 查询值
     * @return
     */
    @Override
    public Page<InstitutionEntity> findAllInstitution(int pageNum, int pageSize, String searchKey) {
        Page<InstitutionEntity> page = null;
        try {
            Specification specification = (Specification<UserEntity>) (root, query, cb) -> {
                List<Predicate> list = new ArrayList<>();
                if (StringUtils.isNotEmpty(searchKey)) {
                    list.add(cb.or(cb.like(root.get("institutionNo"),"%"+searchKey+"%"),cb.like(root.get("institutionName"),"%"+searchKey+"%")));
                }
                query.where(cb.and(list.toArray(new Predicate[list.size()])));
                //排序的升序和倒叙的写法
                //query.orderBy(cb.desc(root.get("id")));
                return query.getRestriction();
            };
            page = institutionRepository.findAll(specification, PageRequestUtil.of(pageNum , pageSize));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return page;
    }

    @Override
    public Optional<InstitutionEntity> findById(String institutionId) {
        return this.institutionRepository.findById(institutionId);
    }

    @Override
    public void saveInstitutionAndUser(SaveInstitutionVO saveInstitutionVO) {
        String institutionNo = saveInstitutionVO.getInstitutionNo();
        String institutionName = saveInstitutionVO.getInstitutionName();
        InstitutionEntity institutionEntity =
                new InstitutionEntity(institutionName, institutionNo, saveInstitutionVO.getLoginName(),
                        DigestUtils.md5DigestAsHex(saveInstitutionVO.getSuperAdminPassword().getBytes()),
                        saveInstitutionVO.getIsTestNum(),saveInstitutionVO.getTestNum(),
                        saveInstitutionVO.getIsRegistrantsNum(),saveInstitutionVO.getRegistrantsNum());
        this.save(institutionEntity);
        UserEntity institutionUserEntity =
                new UserEntity(institutionNo,institutionName, saveInstitutionVO.getLoginName(),
                        saveInstitutionVO.getLoginName(), DigestUtils.md5DigestAsHex(saveInstitutionVO.getSuperAdminPassword().getBytes()),
                        LocalDate.now().toString(),Constant.DEFAULT_VALUE_ZERO, UserStatus.PASS.getType(), UserRole.SUPERADMIN.getType());
        //institutionUserEntity.setInstitutionNo(Constant.DEFAULT_VALUE_ZERO);
        userService.save(institutionUserEntity);
        UserEntity  adminEntity =
                new UserEntity(institutionNo,institutionName, saveInstitutionVO.getAdminPhone(),
                        saveInstitutionVO.getAdminPhone(), DigestUtils.md5DigestAsHex(saveInstitutionVO.getAdminPassword().getBytes()),
                        LocalDate.now().toString(),Constant.DEFAULT_VALUE_ZERO, UserStatus.PASS.getType(), UserRole.ADMIN.getType());
        if (saveInstitutionVO.getAddAdminFlag()) {
            userService.save(adminEntity);
        }
        UserEntity  userEntity = new UserEntity(institutionNo,institutionName, saveInstitutionVO.getUserPhone(),
                saveInstitutionVO.getUserPhone(), DigestUtils.md5DigestAsHex(saveInstitutionVO.getUserPassword().getBytes()),
                LocalDate.now().toString(),Constant.DEFAULT_VALUE_ZERO, UserStatus.PASS.getType(), UserRole.COMMON.getType());
        if (saveInstitutionVO.getAddUserFlag()) {
            //userEntity.setGId(this.addDefaultGroup(saveInstitutionVO.getInstitutionNo(), userEntity.getId()));
            userService.save(userEntity);
        }
        this.addDefaultGroup(saveInstitutionVO.getInstitutionNo(), userEntity.getId());
    }

    private String addDefaultGroup(String institutionNo, String userId) {
        String gid = Constant.DEFAULT_VALUE_ZERO;
        GroupEntity groupEntity1 = this.groupInfoService.findGroupByInstitutionNoAndName(institutionNo, Constant.DEFAULT_GROUP_NAME);
        //没有默认分组，创建默认分组
        if (groupEntity1 == null) {
            GroupEntity groupEntity = new GroupEntity();
            groupEntity.setGroupName(Constant.DEFAULT_GROUP_NAME);
            groupEntity.setInstitutionNo(institutionNo);
            groupEntity = this.groupInfoService.addGroup(groupEntity);
            if (!StringUtils.isEmpty(userId)) {
                gid = groupEntity.getId();
                this.userService.updateUserGroup(groupEntity.getId(), userId);
            }
        } else {
            if (!StringUtils.isEmpty(userId)) {
                gid = groupEntity1.getId();
                this.userService.updateUserGroup(groupEntity1.getId(), userId);
            }
        }
        return gid;
    }
    /**
     * 根据机构编号查询机构信息
     * @param institutionNo
     * @return
     */
    @Override
    @Cacheable(value = "institution",key = "#institutionNo",unless="#result == null")
    public InstitutionEntity findByInstitutionNo(String institutionNo) {
        return this.institutionRepository.findByInstitutionNo(institutionNo);
    }

    /**
     * 根据机构名称查询机构信息
     *
     * @param institutionName
     * @return
     */
    @Override
    @Cacheable(value = "institution:name",key = "#institutionName",unless="#result == null")
    public List<InstitutionEntity> findByInstitutionName(String institutionName) {
        return this.institutionRepository.findAllByInstitutionName(institutionName);
    }

    @Override
    public String newNumber() {
        //编号要求自动生成五位数字且唯一，11000+现有数量保持有序增长
        //获取到现有数量
        List<InstitutionEntity> entityList = institutionRepository.findAll();
        int number = Constant.START_NUMBER+ (CollectionUtils.isNotEmpty(entityList)?entityList.size():0);
        return String.valueOf(checkNumber(number));
    }

    @Override
    @CachePut(value = "institution",key = "#entity.institutionNo",unless="#result == null")
    public InstitutionEntity update(InstitutionEntity entity) {
        return institutionRepository.save(entity);
    }

    @Override
    public boolean checkTestNum(String institutionNo) {
        //判断是否达到最大测试次数
        InstitutionEntity entity = findByInstitutionNo(institutionNo);
        if (Constant.DEFAULT_VALUE_ONE.equals(entity.getIsTestNum().toString())){
            //获取该机构下测试数据
            int count = userRecordService.finAllByInstitutionNo(institutionNo);
            if (count>= entity.getTestNum()){
              return true;
            }
        }
        return false;
    }

    private int checkNumber(int number){
        //根据编号获取到机构
        InstitutionEntity entity = institutionRepository.findByInstitutionNo(String.valueOf(number));
        if (entity == null){
            return number;
        }else {
           return checkNumber(number+1);
        }
    }

}
