package com.ruoyi.web.service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.UserRegStatus;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.dz.domain.DzCards;
import com.ruoyi.dz.service.IDzCardsService;
import com.ruoyi.enums.CardTimeStatus;
import com.ruoyi.enums.UserTypeEnum;
import com.ruoyi.learn.domain.LearnKnowledgeCourse;
import com.ruoyi.learn.domain.LearnKnowledgeTree;
import com.ruoyi.system.service.ISysConfigService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CommService {
    private final ISysConfigService configService;
    private final IDzCardsService cardsService;

    public CommService(ISysConfigService configService, IDzCardsService cardsService) {
        this.configService = configService;
        this.cardsService = cardsService;
    }


    // 检查初始密码是否提醒修改
    public boolean initPasswordIsModify(Date pwdUpdateDate)
    {
        Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
        return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
    }

    // 检查密码是否过期
    public boolean passwordIsExpiration(Date pwdUpdateDate)
    {
        Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
        if (passwordValidateDays != null && passwordValidateDays > 0)
        {
            if (StringUtils.isNull(pwdUpdateDate))
            {
                // 如果从未修改过初始密码，直接提醒过期
                return true;
            }
            Date nowDate = DateUtils.getNowDate();
            return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
        }
        return false;
    }

    public void requireVip() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!UserRegStatus.Student.equals(user.getRegStatus()) || null == user.getCardId()) {
            if (UserTypeEnum.isCard(user.getUserType())) {
                throw new CustomException("没有权限，请开通VIP", 405);
            }
            return;
        }
        DzCards card = cardsService.selectDzCardsByCardId(user.getCardId());
        Date nowDate = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
        if (null == card || !CardTimeStatus.Valid.getVal().equals(card.getTimeStatus()) || (null != card.getOutDate() && card.getOutDate().getTime() < nowDate.getTime())) {
            throw new CustomException("没有权限，请开通VIP", 405);
        }
    }

    public List<LearnTeacherService.TreeNode> buildTree(List<LearnKnowledgeTree> ktList, Set<Long> knowledgeIdSet, Map<Long, Integer[]> knowCountMap) {
        List<LearnTeacherService.TreeNode> treeNodeList = Lists.newArrayList();
        Map<Long, LearnTeacherService.TreeNode> teMap = Maps.newHashMap();
        Integer[] counts;
        for(LearnKnowledgeTree kt : ktList) {
            LearnTeacherService.TreeNode tn;
            if(null != knowCountMap && null != (counts = knowCountMap.get(kt.getId()))) {
                tn = new LearnTeacherService.TreeNode(kt.getId(), kt.getName(),kt.getSubjectId(),  counts);
            } else {
                tn = new LearnTeacherService.TreeNode(kt.getId(), kt.getName(),kt.getSubjectId(),  null);
            }
            teMap.put(kt.getId(), tn);
        }
        for(LearnKnowledgeTree kt : ktList) {
            if(null == kt.getPid()) {
                treeNodeList.add(teMap.get(kt.getId()));
                continue;
            }
            LearnTeacherService.TreeNode parent = teMap.get(kt.getPid());
            LearnTeacherService.TreeNode node = teMap.get(kt.getId());
            if(null != node.getQuestionCount()) {
                parent.setQuestionCount(parent.getQuestionCount() + node.getQuestionCount());
                parent.setFinishedCount(parent.getFinishedCount() + node.getFinishedCount());
                parent.setRightCount(parent.getRightCount() + node.getRightCount());
                parent.calcRatio();
            }
            parent.getChildren().add(node);
        }
        if(!CollectionUtils.isEmpty(knowledgeIdSet)) {
            List<LearnTeacherService.TreeNode> childList;
            List<LearnTeacherService.TreeNode> rootList = Lists.newArrayList();
            for(LearnTeacherService.TreeNode tn : treeNodeList) {
                if(knowledgeIdSet.contains(tn.getId())) {
                    rootList.add(tn);
                } else if(!(childList = tn.getChildren().stream().filter(t -> knowledgeIdSet.contains(t.getId())).collect(Collectors.toList())).isEmpty()) {
                    tn.setChildren(childList);
                    rootList.add(tn);
                }
            }
            return rootList;
        }
        return treeNodeList;
    }

    public List<LearnTeacherService.TreeNode> buildCourseKnowledgeTree(List<LearnKnowledgeCourse> ktList, Map<Long, Integer[]> knowCountMap) {
        List<LearnTeacherService.TreeNode> treeNodeList = Lists.newArrayList();
        Map<Long, LearnTeacherService.TreeNode> teMap = Maps.newHashMap();
        Integer[] counts;
        for(LearnKnowledgeCourse kt : ktList) {
            LearnTeacherService.TreeNode tn;
            if(null != knowCountMap && null != (counts = knowCountMap.get(kt.getId()))) {
                tn = new LearnTeacherService.TreeNode(kt.getId(), kt.getName(),null,  counts);
            } else {
                tn = new LearnTeacherService.TreeNode(kt.getId(), kt.getName(),null,  null);
            }
            teMap.put(kt.getId(), tn);
        }
        for(LearnKnowledgeCourse kt : ktList) {
            if(null == kt.getPid()) {
                treeNodeList.add(teMap.get(kt.getId()));
                continue;
            }
            LearnTeacherService.TreeNode parent = teMap.get(kt.getPid());
            LearnTeacherService.TreeNode node = teMap.get(kt.getId());
            if(null != node.getQuestionCount()) {
                parent.setQuestionCount(parent.getQuestionCount() + node.getQuestionCount());
                parent.setFinishedCount(parent.getFinishedCount() + node.getFinishedCount());
                parent.setRightCount(parent.getRightCount() + node.getRightCount());
                parent.calcRatio();
            }
            parent.getChildren().add(node);
        }
        return treeNodeList;
    }
}
