package com.xinyilu.system.service.applet.impl;

import com.xinyilu.common.config.AppletChatConfig;
import com.xinyilu.common.core.domain.AjaxResult;
import com.xinyilu.common.entity.AppletAccessToken;
import com.xinyilu.common.entity.AppletLoginVO;
import com.xinyilu.common.entity.AppletPhoneVO;
import com.xinyilu.common.enums.ItemCodeEnums;
import com.xinyilu.common.utils.AgeUtil;
import com.xinyilu.common.utils.AppletChatUtil;
import com.xinyilu.common.utils.DateUtils;
import com.xinyilu.system.domain.applet.*;
import com.xinyilu.system.domain.dto.AppletParentDTO;
import com.xinyilu.system.domain.parentInfo.ParentInfo;
import com.xinyilu.system.domain.studentInfo.StudentInfo;
import com.xinyilu.system.domain.vo.motionprescriptionlibrary.MotionPrescriptionLibraryAndVideoVO;
import com.xinyilu.system.domain.vo.personalcheckreport.ExistCheckReportVO;
import com.xinyilu.system.domain.vo.testItemAvgScore.ThisActionDevelopmentVO;
import com.xinyilu.system.mapper.applet.AppletMapper;
import com.xinyilu.system.mapper.parentInfo.ParentInfoMapper;
import com.xinyilu.system.mapper.personalcheckreport.PersonalCheckReportMapper;
import com.xinyilu.system.mapper.testItemScoreinfo.TestItemScoreMapper;
import com.xinyilu.system.service.applet.AppletService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 微信小程序端接口实现类
 * @Author 纪寒
 * @Date 2022-08-17 15:42:26
 * @Version 1.0
 */
@Slf4j
@Service
public class AppletServiceImpl implements AppletService {

    @Resource
    private AppletChatConfig appletChatConfig;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private AppletMapper appletMapper;
    @Resource
    private ParentInfoMapper parentInfoMapper;
    @Resource
    private TestItemScoreMapper testItemScoreMapper;
    @Resource
    private PersonalCheckReportMapper personalCheckReportMapper;

    /**
     * 定义运动程度1分及以下
     **/
    private static final String ONE_POINT = "1分及以下";

    /**
     * 定义运动程度2分-3分
     **/
    private static final String TWO_POINT = "2分-3分";

    /**
     * 定义运动程度4分及以上
     **/
    private static final String FOUR_POINT = "4分及以上";

    /**
     * 定义分数 1分
     **/
    private static final BigDecimal ONE_SCORE = BigDecimal.valueOf(1);

    /**
     * 定义分数 2分
     **/
    private static final BigDecimal TWO_SCORE = BigDecimal.valueOf(2);

    /**
     * 定义分数 3分
     **/
    private static final BigDecimal THREE_SCORE = BigDecimal.valueOf(3);

    /**
     * 返回成功状态码
     */
    private static final int SUCCESS_CODE = 0;

    /**
     * 返回成功状态码
     */
    private static final String OK = "ok";

    /**
     * 根据小程序登录唯一凭证获取用户的微信标识信息、手机号、以及该家长所属孩子信息
     *
     * @param loginCode 唯一登录凭证
     * @param phoneCode 手机号获取凭证
     * @return 家长所属孩子信息集合
     */
    @Override
    public AjaxResult appletLogin(String loginCode, String phoneCode) {
        //根据code获取用户的微信unionId以及openId等信息
        AppletLoginVO appletLoginInfo = AppletChatUtil.getAppletLoginInfo(appletChatConfig.getAppletId(), appletChatConfig.getSecret(), loginCode, appletChatConfig.getGrantType());
        if (Objects.isNull(appletLoginInfo)) {
            return AjaxResult.error("获取微信小程序用户信息失败");
        }
        if (Objects.nonNull(appletLoginInfo.getErrcode()) && appletLoginInfo.getErrcode() != SUCCESS_CODE) {
            return AjaxResult.error("获取微信小程序用户信息失败，失败信息为：" + appletLoginInfo.getErrmsg());
        }
        //获取accessToken
        AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
        if (Objects.isNull(appletAccessToken)) {
            return AjaxResult.error("获取微信小程序accessToken信息失败");
        }
        if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != SUCCESS_CODE) {
            return AjaxResult.error("获取微信小程序accessToken信息失败，失败信息为：" + appletAccessToken.getErrmsg(), 201);
        }
        if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
            return AjaxResult.error("accessToken信息为空");
        }
        //获取用户手机号
        AppletPhoneVO appletPhoneInfo = AppletChatUtil.getAppletPhoneInfo(phoneCode, appletAccessToken.getAccessToken());
        if (Objects.isNull(appletPhoneInfo)) {
            return AjaxResult.error("获取用户手机号失败");
        }
        if (StringUtils.isNotBlank(appletPhoneInfo.getErrmsg()) && !OK.equals(appletPhoneInfo.getErrmsg())) {
            return AjaxResult.error("获取用户手机号失败，失败信息为：" + appletPhoneInfo.getErrmsg());
        }
        //根据手机号查询家长信息
        ParentInfo parentInfo = appletMapper.getParentInfoByPhone(StringUtils.isBlank(appletPhoneInfo.getPhoneInfo().getPhoneNumber()) ? "" : appletPhoneInfo.getPhoneInfo().getPhoneNumber());
        if (Objects.isNull(parentInfo)) {
            AppletPhoneInfo phoneInfo = new AppletPhoneInfo();
            phoneInfo.setOpenId(appletLoginInfo.getOpenid());
            phoneInfo.setFlag("EMPTY");
            return AjaxResult.success(phoneInfo);
        }
        //将家长个人的小程序唯一标识更新到数据表中
        ParentInfo appletParent = new ParentInfo();
        appletParent.setId(parentInfo.getId());
        appletParent.setOpenid(appletLoginInfo.getOpenid());
        appletParent.setUpdateTime(DateUtils.getNowDate());
        parentInfoMapper.updateParentInfo(appletParent);
        //返回信息
        AppletPhoneInfo phoneInfo = new AppletPhoneInfo();
        phoneInfo.setPhone(appletPhoneInfo.getPhoneInfo().getPhoneNumber());
        phoneInfo.setFlag("SUCCESS");
        return AjaxResult.success(phoneInfo);
    }

    /**
     * 绑定家长手机号信息
     *
     * @param appletParentDTO 输入参数
     * @return 结果
     */
    @Override
    public AjaxResult updateParentInfo(AppletParentDTO appletParentDTO) {
        //根据学生身份证号查询家长信息
        StudentInfo studentInfo = appletMapper.getStudentInfoByCardNo(appletParentDTO.getCardNo());
        if (Objects.isNull(studentInfo)) {
            return AjaxResult.error("未查询到身份证号为：" + appletParentDTO.getCardNo() + "的学生信息，请输入正确的身份证号！");
        }
        //根据学生id和家长名称查询其家长信息
        List<ParentInfo> parentInfoList = appletMapper.getParentByStudentIdAndName(studentInfo.getId(), appletParentDTO.getParentName());
        if (CollectionUtils.isEmpty(parentInfoList)) {
            return AjaxResult.error("未查询到姓名为：" + appletParentDTO.getParentName() + "家长信息，请填写正确的姓名！");
        }
        //更新家长手机号
        for (ParentInfo parent : parentInfoList) {
            ParentInfo parentInfo = new ParentInfo();
            parentInfo.setOpenid(appletParentDTO.getOpenId());
            parentInfo.setPhone(appletParentDTO.getPhone());
            parentInfo.setId(parent.getId());
            parent.setUpdateTime(DateUtils.getNowDate());
            int updateParentCount = parentInfoMapper.updateParentInfo(parentInfo);
            if (updateParentCount <= 0) {
                return AjaxResult.error("绑定手机号为：" + appletParentDTO.getPhone() + "的家长信息失败，请联系管理员！");
            }
        }
        return AjaxResult.success(appletParentDTO.getPhone());
    }

    /**
     * 根据学生id查询学校成绩信息
     *
     * @param studentIdList 学生id集合
     * @return 成绩信息
     */
    @Override
    public AjaxResult getStudentScoreInfo(List<Long> studentIdList) {
        //查询学校批次成绩信息
        List<AppletStudentScore> appletStudentScore = appletMapper.getAppletStudentScoreById(studentIdList);
        appletStudentScore.forEach(item -> {
            item.setTotalFraction(item.getTotalFraction().setScale(2, BigDecimal.ROUND_HALF_UP));
            item.setExistFlag(!StringUtils.isBlank(item.getDownloadAddress()));
        });
        return AjaxResult.success(appletStudentScore);
    }

    /**
     * 根据手机号获取家长以及孩子信息
     *
     * @param phone 手机号码
     * @return 家长孩子相关信息
     */
    @Override
    public AjaxResult getParentAndStudentInfoByPhone(String phone) {
        //根据手机号查询家长信息
        ParentInfo parentInfo = appletMapper.getParentInfoByPhone(phone);
        if (Objects.isNull(parentInfo)) {
            return AjaxResult.success("EMPTY");
        }
        return getAppletParentAndStudentInfo(parentInfo);
    }

    /**
     * 根据学生id和批次编号查询对应得报告信息
     *
     * @param studentId 学生id
     * @param batchCode 批次编号
     * @return 报告信息
     */
    @Override
    public AjaxResult getReportDownAddress(Long studentId, String batchCode) {
        ExistCheckReportVO personalCheckInfo = appletMapper.getAppletPersonalCheckInfo(studentId, batchCode);
        //当前报告信息不存在
        if (Objects.isNull(personalCheckInfo)) {
            ExistCheckReportVO reportVO = new ExistCheckReportVO();
            reportVO.setExistFlag(false);
            return AjaxResult.success(reportVO);
        }
        personalCheckInfo.setExistFlag(true);
        return AjaxResult.success(personalCheckInfo);
    }

    /**
     * 根据学生id查询学生最新批次的成绩与报告
     *
     * @param studentIdList 学生id集合
     * @return java.util.List<com.xinyilu.system.domain.applet.AppletChildrenResultScoreInfo>
     **/
    @Override
    public AjaxResult getChildrenResultScore(List<Long> studentIdList) {
        //根据学生id与项目条件查询
        List<AppletChildrenResultScoreInfo> childrenResultScore = appletMapper.getChildrenResultScore(studentIdList, ItemCodeEnums.BMI_CODE.getInfo());
        if (CollectionUtils.isEmpty(childrenResultScore)) {
            return AjaxResult.success(new ArrayList<>());
        }
        List<AppletChildrenResultScoreInfo> dataResultList = Lists.newArrayList();
        //将list集合转换为map 循环取出第一条记录
        Map<Long, List<AppletChildrenResultScoreInfo>> childrenResultScoreMap = childrenResultScore.stream()
                .filter(Objects::nonNull)
                .filter(student -> Objects.nonNull(student.getStudentId())).collect(Collectors.groupingBy(AppletChildrenResultScoreInfo::getStudentId));
        for (List<AppletChildrenResultScoreInfo> resultScoreInfoList : childrenResultScoreMap.values()) {
            if (CollectionUtils.isEmpty(resultScoreInfoList)) {
                continue;
            }
            //倒序排序
            List<AppletChildrenResultScoreInfo> scoreInfoList = resultScoreInfoList.stream().filter(Objects::nonNull)
                    .filter(student -> Objects.nonNull(student.getCreateTime()))
                    .sorted(Comparator.comparing(AppletChildrenResultScoreInfo::getCreateTime).reversed()).collect(Collectors.toList());
            AppletChildrenResultScoreInfo scoreInfo = scoreInfoList.get(0);
            scoreInfo.setExistFlag(!StringUtils.isBlank(scoreInfo.getDownloadAddress()));
            dataResultList.add(scoreInfo);
        }
        return AjaxResult.success(dataResultList);
    }

    /**
     * 根据学生id和批次编号查询对应的处方
     *
     * @param studentId 学生id
     * @param batchCode 批次编号
     * @return java.util.List<com.xinyilu.system.domain.vo.testItemAvgScore.ThisActionDevelopmentVO>
     **/
    @Override
    public AjaxResult getMotionPrescription(Long studentId, String batchCode) {
        List<MotionPrescriptionLibraryAndVideoVO> dataList = Lists.newArrayList();
        //判断当前报告有没有并且有没有审核过
        int checkReportCount = personalCheckReportMapper.getCheckReportCount(studentId, batchCode);
        if (checkReportCount <= 0) {
            return AjaxResult.success(dataList);
        }
        //查询数据库中的分数
        List<ThisActionDevelopmentVO> actionList = testItemScoreMapper.selectThisActionDevelopmentVO(studentId, batchCode, ItemCodeEnums.BMI_CODE.getInfo());
        //查询数据库中的运动处方库数据表信息
        List<MotionPrescriptionLibraryAndVideoVO> motionPrescriptionLibraryList = testItemScoreMapper.getMotionLibraryAndVideoList();
        actionList.forEach(item -> {
            String categoryName = StringUtils.isBlank(item.getCategoryName()) ? "" : item.getCategoryName();
            BigDecimal itemScore = Objects.isNull(item.getItemFraction()) ? BigDecimal.ZERO : item.getItemFraction();
            //进行分数匹配
            List<MotionPrescriptionLibraryAndVideoVO> scoreList = motionPrescriptionLibraryList.stream()
                    .filter(library -> StringUtils.isNotBlank(library.getPhysicalQualityName()) && Objects.nonNull(library.getDegreeStartFraction()) && Objects.nonNull(library.getDegreeEndFraction()))
                    .filter(score -> StringUtils.equals(categoryName, score.getPhysicalQualityName()) && itemScore.compareTo(score.getDegreeStartFraction()) >= 0 && itemScore.compareTo(score.getDegreeEndFraction()) <= 0)
                    .collect(Collectors.toList());
            dataList.addAll(scoreList);
        });
        //匹配好的进行筛选出运动程度
        dataList.forEach(item -> {
            if (Objects.nonNull(item.getDegreeStartFraction()) && Objects.nonNull(item.getDegreeEndFraction()) &&
                    item.getDegreeStartFraction().compareTo(BigDecimal.ZERO) >= 0 && item.getDegreeEndFraction().compareTo(ONE_SCORE) <= 0) {
                item.setDegreeMovement(ONE_POINT);
            } else if (Objects.nonNull(item.getDegreeStartFraction()) && Objects.nonNull(item.getDegreeEndFraction()) &&
                    item.getDegreeStartFraction().compareTo(TWO_SCORE) >= 0 && item.getDegreeEndFraction().compareTo(THREE_SCORE) <= 0) {
                item.setDegreeMovement(TWO_POINT);
            } else {
                item.setDegreeMovement(FOUR_POINT);
            }
        });
        return AjaxResult.success(dataList);
    }

    /**
     * 查询学校信息
     *
     * @param parentInfo 家长信息
     * @return 家长信息集合
     */
    private AjaxResult getAppletParentAndStudentInfo(ParentInfo parentInfo) {
        List<ParentAndStudentInfo> parentAndStudentInfo = appletMapper.getParentAndStudentInfo(parentInfo.getId());
        AppletParentAndStudentInfo appletInfo = new AppletParentAndStudentInfo();
        appletInfo.setParentName(StringUtils.isBlank(parentInfo.getParentName()) ? "" : parentInfo.getParentName());
        appletInfo.setPhone(StringUtils.isBlank(parentInfo.getPhone()) ? "" : parentInfo.getPhone());
        appletInfo.setParentInfoId(parentInfo.getId());
        //家长的孩子数量
        long studentCount = parentAndStudentInfo.stream().filter(Objects::nonNull).filter(student -> Objects.nonNull(student.getStudentId())).count();
        appletInfo.setChildrenCount(studentCount);
        //学生信息
        List<AppletStudentInfo> studentInfoList = parentAndStudentInfo.stream().filter(item -> Objects.nonNull(item.getStudentId())).map(item -> {
            AppletStudentInfo appletStudentInfo = new AppletStudentInfo();
            try {
                appletStudentInfo.setStudentId(Objects.isNull(item.getStudentId()) ? 0L : item.getStudentId());
                appletStudentInfo.setStudentName(StringUtils.isBlank(item.getStudentName()) ? "" : item.getStudentName());
                appletStudentInfo.setStudentSex(StringUtils.isBlank(item.getStudentSex()) ? "" : item.getStudentSex());
                appletStudentInfo.setStudentAge(AgeUtil.getStudentAgeMonth(Objects.isNull(item.getBirthDate()) ? LocalDate.now().toString() : item.getBirthDate().toString()));
                appletStudentInfo.setClassId(Objects.isNull(item.getClassId()) ? 0L : item.getClassId());
                appletStudentInfo.setClassName(StringUtils.isBlank(item.getClassName()) ? "" : item.getClassName());
                appletStudentInfo.setClassTeacher(StringUtils.isBlank(item.getClassTeacher()) ? "" : item.getClassTeacher());
                appletStudentInfo.setClassPhone(StringUtils.isBlank(item.getPhone()) ? "" : item.getPhone());
                appletStudentInfo.setKindergartenName(StringUtils.isBlank(item.getKindergartenName()) ? "" : item.getKindergartenName());
                appletStudentInfo.setKindergartenId(Objects.isNull(item.getKindergartenId()) ? 0L : item.getKindergartenId());
                appletStudentInfo.setChildrenItemCount(Objects.isNull(item.getStudentItemCount()) ? 0L : item.getStudentItemCount());
                appletStudentInfo.setBirthDate(Objects.isNull(item.getBirthDate()) ? LocalDate.now() : item.getBirthDate());
            } catch (Exception e) {
                log.warn("计算年龄失败，异常信息:[{}]", e.getMessage());
            }
            return appletStudentInfo;
        }).collect(Collectors.toList());
        appletInfo.setStudentInfoList(studentInfoList);
        //幼儿园信息
        List<AppletClassInfo> classInfoList = parentAndStudentInfo.stream().filter(Objects::nonNull).map(item ->
                {
                    AppletClassInfo appletClassInfo = new AppletClassInfo();
                    appletClassInfo.setKindergartenId(Objects.isNull(item.getKindergartenId()) ? null : item.getKindergartenId());
                    appletClassInfo.setKindergartenName(StringUtils.isBlank(item.getKindergartenName()) ? "" : item.getKindergartenName());
                    appletClassInfo.setKindergartenAddress(StringUtils.isBlank(item.getKindergartenAddress()) ? "" : item.getKindergartenAddress());
                    appletClassInfo.setKindergartenType(StringUtils.isBlank(item.getKindergartenType()) ? "" : item.getKindergartenType());
                    appletClassInfo.setPrincipalId(Objects.isNull(item.getPrincipalId()) ? null : item.getPrincipalId());
                    appletClassInfo.setPrincipalName(StringUtils.isBlank(item.getPrincipalName()) ? null : item.getPrincipalName());
                    appletClassInfo.setKindergartenPhone(StringUtils.isBlank(item.getKindergartenPhone()) ? "" : item.getKindergartenPhone());
                    return appletClassInfo;
                }
        ).collect(Collectors.toList());
        //去除重复
        List<AppletClassInfo> distinctClassInfoList = classInfoList.stream().distinct().collect(Collectors.toList());
        appletInfo.setKindergartenInfoList(distinctClassInfoList);
        return AjaxResult.success(appletInfo);
    }

}
