package com.ym.mec.biz.service.impl;

import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.CourseSchedule;
import com.ym.mec.biz.dal.entity.Student;
import com.ym.mec.biz.dal.entity.StudentRegistration;
import com.ym.mec.biz.dal.entity.SysUserCashAccount;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.dal.page.*;
import com.ym.mec.biz.service.StudentManageService;
import com.ym.mec.biz.service.StudentService;
import com.ym.mec.common.entity.ImResult;
import com.ym.mec.common.entity.ImUserModel;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.im.ImFeignService;
import com.ym.mec.util.collection.MapUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author Joburgess
 * @Date 2019/9/19
 */
@Service
public class StudentManageServiceImpl implements StudentManageService {

    @Autowired
    private StudentManageDao studentManageDao;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private MusicGroupStudentFeeDao musicGroupStudentFeeDao;
    @Autowired
    private CourseScheduleStudentPaymentDao scheduleStudentPaymentDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private StudentService studentService;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private StudentRegistrationDao studentRegistrationDao;
    @Autowired
    private ImFeignService imFeignService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private ClassGroupDao classGroupDao;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private VipGroupDao vipGroupDao;
    @Autowired
    private SysUserCashAccountDao sysUserCashAccountDao;

    @Override
    public PageInfo<StudentManageListDto> findStudentsByOrganId(StudentManageQueryInfo queryInfo) {
        PageInfo<StudentManageListDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Boolean hasCourse = queryInfo.getHasCourse();
        Boolean hasPracticeCourse = queryInfo.getHasPracticeCourse();
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        params.put("offset", pageInfo.getOffset());
        int count = 0;
        Set<Integer> paramUserIds = null;
        if(hasPracticeCourse != null){
            //是否有陪练课
            if(hasPracticeCourse){
                paramUserIds = studentManageDao.queryHasPracticeCourse(params);
            }else {
                paramUserIds = studentManageDao.queryNotPracticeCourse(params);
            }
            if(paramUserIds.size() == 0){
                return pageInfo;
            }
            params.put("userIds",paramUserIds);
        }
        if(hasCourse != null){
            if(hasCourse){
                paramUserIds = studentManageDao.queryHasCourse(params);
                count = studentManageDao.countHasCourse(params);
            }else {
                paramUserIds = studentManageDao.queryNotCourse(params);
                count = studentManageDao.countNotCourse(params);
            }
            if(paramUserIds.size() == 0){
                return pageInfo;
            }
            params.remove("offset");
            params.put("userIds",paramUserIds);
        }else {
            count = studentManageDao.countStudentByOrganId(params);
        }
        if(queryInfo.getIsExport() && count > 50000){
            throw new BizException("数据集太大，不能导出.最大数据集不能超过50000");
        }
        List<StudentManageListDto> dataList = null;
        if (count > 0) {
            pageInfo.setTotal(count);
            dataList = studentManageDao.findStudentsByOrganId(params);
            Set<Integer> userIds = dataList.stream().map(StudentManageListDto::getUserId).collect(Collectors.toSet());
            Set<Integer> organIds = dataList.stream().map(StudentManageListDto::getOrganId).collect(Collectors.toSet());
            List<SysUserCashAccount> byUserIds = sysUserCashAccountDao.findByUserIds(userIds);
            Map<Integer, SysUserCashAccount> collect = byUserIds.stream()
                    .collect(Collectors.toMap(SysUserCashAccount::getUserId, sysUserCashAccount -> sysUserCashAccount));
            Map<Integer,Integer> hasPracticeCourseMap = MapUtil.convertIntegerMap(studentManageDao.getHasPracticeCourse(userIds));
            //获取用户分部
            Map<Integer,String> organNames = MapUtil.convertMybatisMap(organizationDao.findOrganNameMapList(organIds));
            //获取所在乐团
            Map<Integer,String> musicGroupNames = MapUtil.convertMybatisMap(musicGroupDao.queryUserMusicNames(userIds));
            //获取所在vip
            Map<Integer,String> vipGroupNames = MapUtil.convertMybatisMap(vipGroupDao.queryUserVipNames(userIds));
            //获取所在乐团状态
            Map<Integer,String> musicGroupStatus = MapUtil.convertMybatisMap(musicGroupDao.queryUserMusicStatus(userIds));
            //获取所在vip状态
            Map<Integer,String> vipGroupStatus = MapUtil.convertMybatisMap(vipGroupDao.queryUserVipStatus(userIds));
            //获取所在声部
            Map<Integer,String> subjectNames = MapUtil.convertMybatisMap(studentManageDao.querySubjectNames(userIds));
            dataList.forEach(e -> {
                e.setOrganName(organNames.get(e.getOrganId()));
                e.setMusicGroupName(musicGroupNames.get(e.getUserId().longValue()));
                e.setVipGroupName(vipGroupNames.get(e.getUserId()));
                e.setSubjectName(subjectNames.get(e.getUserId().longValue()));
                e.setMusicGroupStatus(musicGroupStatus.get(e.getUserId().longValue()));
                e.setVipGroupStatus(vipGroupStatus.get(e.getUserId()));
                if(hasCourse == null){
                    Integer course = studentManageDao.getHasCourse(e.getUserId());
                    e.setHasCourse(course==null?YesOrNoEnum.NO:course==0?YesOrNoEnum.NO:YesOrNoEnum.YES);
                }else {
                    if(hasCourse){
                        e.setHasCourse(YesOrNoEnum.YES);
                    }else {
                        e.setHasCourse(YesOrNoEnum.NO);
                    }
                }
                e.setHasPracticeCourse(hasPracticeCourseMap.get(e.getUserId()) == null?YesOrNoEnum.NO:YesOrNoEnum.YES);
                if(collect.get(e.getUserId()) != null){
                    e.setCourseBalance(collect.get(e.getUserId()).getCourseBalance());
                }
            });
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public StudentManageListDto findStudentManageBaseInfo(Integer userId) {
        return studentManageDao.findStudentBaseInfoByUserID(userId);
    }

    @Override
    public List<StudentManageBaseInfoOfMusicGroupDto> findStudentMusicGroupsByUserId(Integer userId) {
        List<StudentManageBaseInfoOfMusicGroupDto> musicGroups = studentManageDao.findStudentMusicGroupsByUserId(userId);
        //获取学员报名时所选乐器
        if(musicGroups != null && musicGroups.size() > 0){
            for (StudentManageBaseInfoOfMusicGroupDto e:musicGroups) {
                e.setUserGoodsDtos(studentPaymentOrderDao.findGoodsIds(e.getMusicGroupId(),e.getUserId()));
            }
        }
        return musicGroups;
    }

    @Override
    public PageInfo findStudentCourseList(StudentManageCourseQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List dataList = null;
        int count = studentManageDao.countStudentCourses(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentManageDao.findStudentCourseList(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public PageInfo findStudentAttendances(StudentManageAttendanceQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<StudentManageCourseListDto> dataList = null;
        int count = studentManageDao.countStudentAttendances(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentManageDao.findStudentAttendances(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public PageInfo<StudentManageVipGroupDto> findStudentVipGroups(StudentManageCourseQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List dataList = null;
        int count = vipGroupDao.countStudentVipGroups(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = vipGroupDao.findStudentVipGroups(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public StudentManageAccountBaseInfoDto getStudentAccountBaseInfo(Integer userId) {
        return studentManageDao.getStudentAccountBaseInfo(userId);
    }

    @Override
    public PageInfo queryStudentPayment(TeacherPaymentRecordInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List dataList = null;
        int count = studentManageDao.countStudentPayment(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentManageDao.queryStudentPayment(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public PageInfo<MusicGroupStudentsDto> queryMusicGroupStudent(MusicGroupStudentQueryInfo queryInfo) {
        PageInfo<MusicGroupStudentsDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<MusicGroupStudentsDto> dataList = null;
        int count = studentManageDao.countMusicGroupStudent(params);
        if(queryInfo.getIsExport() && count > 50000){
            throw new BizException("数据集太大，不能导出.最大数据集不能超过50000");
        }
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentManageDao.queryMusicGroupStudent(params);
            Map<Integer,String> maps = MapUtil.convertIntegerMap(musicGroupStudentFeeDao.findPaymentStatusMap(queryInfo.getMusicGroupId()));
            dataList.forEach(e->{
                e.setPaymentStatus(maps.get(e.getUserId()));
            });
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public Object musicGroupStudentsSum(String musicGroupId) {
        Map<String,Integer> resultMap = new HashMap<>(3);
        //乐团在读人数
        resultMap.put("studying",studentManageDao.countStudyNum(musicGroupId));
        //退团人数
        resultMap.put("quit",studentManageDao.countQuitNum(musicGroupId));
        //新增人数
        resultMap.put("add",studentManageDao.countAddNum(musicGroupId));
        return resultMap;
    }

    @Override
    public PageInfo<MusicGroupStudentSignDto> queryMusicGroupStudentsSign(StudentSignQueryInfo queryInfo) {
        PageInfo<MusicGroupStudentSignDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<MusicGroupStudentSignDto> dataList = null;
        int count = studentManageDao.countMusicGroupStudentsSign(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentManageDao.queryMusicGroupStudentsSign(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public List<ConditionDto> queryStudentClassGroup(String musicGroupId, Integer teacherId) {
        return classGroupDao.queryStudentClassGroup(musicGroupId,teacherId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(SysUser sysUser) {
        studentManageDao.updateUser(sysUser);
        StudentRegistration studentRegistration = new StudentRegistration();
        studentRegistration.setUserId(sysUser.getId());
        studentRegistration.setCurrentClass(sysUser.getCurrentClass());
        studentRegistration.setCurrentGrade(sysUser.getCurrentGrade());
        studentRegistrationDao.updateCurrentClass(studentRegistration);
    }

    @Override
    public PageInfo<StudentManageVipGroupClassDto> findStudentVipGroupClass(StudentManageVipClassQueryInfo queryInfo) {
        PageInfo<StudentManageVipGroupClassDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<StudentManageVipGroupClassDto> dataList = null;
        int count = studentManageDao.countStudentVipGroupClass(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentManageDao.findStudentVipGroupClass(params);
            Set<Integer> teacherIds = dataList.stream().map(e -> e.getTeacherId()).collect(Collectors.toSet());
            List<Map<Integer, String>> maps = teacherDao.queryNameByIds(StringUtils.join(teacherIds, ","));
            Map<Integer, String> teacherNameMap = MapUtil.convertMybatisMap(maps);
            dataList.forEach(e->{
                e.setTeacherName(teacherNameMap.get(e.getTeacherId()));
            });
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int studentRegister(SysUser sysUser) {
        if(sysUser == null || StringUtils.isEmpty(sysUser.getPhone())){
            throw new BizException("参数校验失败");
        }
        SysUser sysUser1 = sysUserFeignService.queryUserByMobile(sysUser.getPhone());
        if(sysUser1 != null){
            if(sysUser1.getUserType().contains("STUDENT")){
                throw new BizException("手机号已被占用");
            }else {
                sysUser.setId(sysUser1.getId());
                sysUser.setUserType(sysUser1.getUserType() + ",STUDENT");
                teacherDao.updateUser(sysUser);
                return sysUser1.getId();
            }
        }
        sysUser.setUserType("STUDENT");
        teacherDao.addSysUser(sysUser);
        Integer userId = sysUser.getId();
        ImResult register = imFeignService.register(new ImUserModel(userId.toString(), sysUser.getPhone(), null));
        sysUser.setImToken(register.getToken());
        teacherDao.updateUser(sysUser);
        sysUserCashAccountDao.insert(new SysUserCashAccount(userId, "CNY"));
        Student student = new Student(userId, studentRegistrationDao.getSubjectIds(userId));
        student.setOperatingTag(sysUser.getOperatingTag());
        student.setServiceTag(sysUser.getServiceTag());
        studentService.upSet(student);
        return userId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int studentUpdate(SysUser sysUser) {
        Integer userId = sysUser.getId();
        if(userId == null || StringUtils.isEmpty(sysUser.getPhone())){
            throw new BizException("参数校验失败");
        }
        SysUser sysUser1 = sysUserFeignService.queryUserByMobile(sysUser.getPhone());
        if(sysUser1 != null && !userId.equals(sysUser1.getId())){
            throw new BizException("手机号已被占用");
        }
        teacherDao.updateUser(sysUser);
        Student student = new Student(userId, studentRegistrationDao.getSubjectIds(userId));
        student.setOperatingTag(sysUser.getOperatingTag());
        student.setServiceTag(sysUser.getServiceTag());
        studentService.upSet(student);
        return userId;
    }

    @Override
    public List<StudentRegisterPerDto> queryStudentPer() {
        Set<Integer> musicUserIds = scheduleStudentPaymentDao.queryMusicStudentPer();
        Set<Integer> vipUserIds = scheduleStudentPaymentDao.queryVipStudentPer();
        musicUserIds.addAll(vipUserIds);
        return studentRegistrationDao.queryStudentPer(musicUserIds);
    }

    @Override
    public List<StudentManageListDto> queryHasCourseStudent(StudentManageQueryInfo queryInfo) {
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        List<StudentManageListDto> studentHasCourseDtos = studentManageDao.queryHasCourseStudent(params);
        /*Set<Integer> userIds = studentHasCourseDtos.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
        Map<Integer,Integer> hasPracticeCourseMap = MapUtil.convertIntegerMap(studentManageDao.getHasPracticeCourse(userIds));
        Map<Integer,Integer> isActiveMap = MapUtil.convertIntegerMap(studentManageDao.getIsActive(userIds));
        Map<Integer,Integer> isMakeMap = MapUtil.convertIntegerMap(studentManageDao.getIsMake(userIds));
        studentHasCourseDtos.forEach(e->{
            e.setHasPracticeCourse(hasPracticeCourseMap.get(e.getUserId()) == null?YesOrNoEnum.NO:YesOrNoEnum.YES);
            e.setIsActive(isActiveMap.get(e.getUserId()) == null?YesOrNoEnum.YES:YesOrNoEnum.NO);
            e.setIsMake(isMakeMap.get(e.getUserId()) == null?YesOrNoEnum.NO:YesOrNoEnum.YES);
        });*/
        return studentHasCourseDtos;
    }

    @Override
    public Map<String, Integer> sumStudentAttendance(Integer courseScheduleId) {
        Map<String, Integer> sum = new HashMap<>(5);
        Integer studentNum = scheduleStudentPaymentDao.countStudentNum(courseScheduleId);
        sum.put("studentNum",studentNum);
        Integer signInNum = studentManageDao.countStudentSignInNum(courseScheduleId, "NORMAL");
        sum.put("signInNum",signInNum);
        Integer leaveNum = studentManageDao.countStudentSignInNum(courseScheduleId, "LEAVE");
        sum.put("leaveNum",leaveNum);
        studentNum = studentNum==null?0:studentNum;
        signInNum = signInNum==null?0:signInNum;
        leaveNum = leaveNum==null?0:leaveNum;
        sum.put("truantNum",studentNum-signInNum-leaveNum);
        sum.put("homeworkNum",studentManageDao.countHomeworkNum(courseScheduleId));
        sum.put("repliedNum",studentManageDao.countRepliedNum(courseScheduleId));
        return sum;
    }
}
