package com.yonge.cooleshow.biz.dal.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.dto.RealnameAuthReq;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.auth.api.enums.SysUserType;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.biz.dal.dao.EmployeeDao;
import com.yonge.cooleshow.biz.dal.dto.TeacherDto;
import com.yonge.cooleshow.biz.dal.dto.req.TeacherSubmitReq;
import com.yonge.cooleshow.biz.dal.dto.search.TeacherSearch;
import com.yonge.cooleshow.biz.dal.entity.*;
import com.yonge.cooleshow.biz.dal.enums.AuthStatusEnum;
import com.yonge.cooleshow.biz.dal.enums.CacheNameEnum;
import com.yonge.cooleshow.biz.dal.enums.TeacherTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.YesOrNoEnum;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.biz.dal.vo.TeacherAuthEntryRecordVo;
import com.yonge.cooleshow.biz.dal.vo.TeacherHomeVo;
import com.yonge.cooleshow.biz.dal.vo.TeacherTotalVo;
import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.exception.BizException;
import com.yonge.toolset.utils.idcard.IdcardInfoExtractor;
import com.yonge.toolset.utils.string.StringUtil;
import com.yonge.toolset.utils.string.ValueUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
import org.springframework.transaction.annotation.Transactional;

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

@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherDao, Teacher> implements TeacherService {
    @Autowired
    private TeacherStyleVideoService teacherStyleVideoService;
    @Autowired
    private SysUserFeignService userFeignService;
    @Autowired
    private TeacherAuthEntryRecordService entryRecordService;
    @Autowired
    private TeacherAuthMusicianRecordService musicianRecordService;
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private LiveRoomService liveRoomService;
    @Autowired
    private StudentStarService studentStarService;

    @Override
    public TeacherVo detail(Long userId) {
        TeacherVo detail = baseMapper.detail(userId);
        if (null == detail) {
            detail = new TeacherVo();
        }
        List<TeacherStyleVideo> teacherStyleVideos = teacherStyleVideoService.selectListByUserId(userId);
        detail.setStyleVideo(teacherStyleVideos);
        TeacherAuthEntryRecordVo lastRecordByUserId = entryRecordService.getLastRecordByUserId(userId);
        if (null != lastRecordByUserId) {
            detail.setVerifyUser(lastRecordByUserId.getVerifyUser());
        }
        String teacherType = TeacherTypeEnum.getTeacherType(detail.getEntryFlag(), detail.getMusicianFlag());
        detail.setTeacherType(teacherType);
        return detail;
    }

    @Override
    public IPage<TeacherVo> selectPage(IPage<TeacherVo> page, TeacherSearch search) {
        List<TeacherVo> teacherVos = baseMapper.selectPage(page, search);
        return page.setRecords(teacherVos);
    }

    @Override
    @Transactional(rollbackFor = BizException.class)
    public HttpResponseResult<Boolean> submit(TeacherSubmitReq teacherSubmitReq) throws BizException {
        if (null == teacherSubmitReq.getUserId()) {
            //创建
            return doCreate(teacherSubmitReq);
        } else {
            //修改
            return doUpdate(teacherSubmitReq);
        }
    }

    @Override
    public HttpResponseResult<TeacherHomeVo> queryUserInfo(Long userId) {
        TeacherVo teacher = detail(userId);
        if (null == teacher) {
            return HttpResponseResult.failed("未查询到老师信息");
        }
        TeacherHomeVo teacherHomeVo = new TeacherHomeVo();
        try {
            BeanUtils.copyProperties(teacherHomeVo, teacher);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //身份证号、手机号脱敏
        teacherHomeVo.setIdCardNo(ValueUtil.fuzzyIdCard(teacherHomeVo.getIdCardNo()));
        teacherHomeVo.setPhone(ValueUtil.fuzzyMobile(teacherHomeVo.getPhone()));
        teacherHomeVo.setHeardUrl(teacher.getAvatar());

        if (YesOrNoEnum.YES.equals(teacher.getEntryFlag())) {
            teacherHomeVo.setEntryStatus(AuthStatusEnum.PASS);
        } else {
            TeacherAuthEntryRecordVo entryRecord = entryRecordService.getLastRecordByUserId(userId);
            if (null == entryRecord) {
                teacherHomeVo.setEntryStatus(AuthStatusEnum.UNPAALY);
            } else {
                teacherHomeVo.setEntryStatus(entryRecord.getTeacherAuthStatus());
            }
        }

        if (YesOrNoEnum.YES.equals(teacher.getMusicianFlag())) {
            teacherHomeVo.setMusicianAuthStatus(AuthStatusEnum.PASS);
        } else {
            TeacherAuthMusicianRecord musicianRecord = musicianRecordService.getLastRecordByUserId(userId);
            if (null == musicianRecord) {
                teacherHomeVo.setMusicianAuthStatus(AuthStatusEnum.UNPAALY);
            } else {
                teacherHomeVo.setMusicianAuthStatus(musicianRecord.getTeacherAuthStatus());
            }
        }

        TeacherTotal total = (TeacherTotal) redissonClient.getBucket(CacheNameEnum.TEACHER_TOTAL.getRedisKey(userId)).get();
        if (null == total) {
            total = new TeacherTotal();
        }
        teacherHomeVo.setStarGrade((null == total.getStarGrade()) ? 0 : total.getStarGrade().intValue());
        teacherHomeVo.setFansNum((null == total.getFansNum()) ? 0 : total.getFansNum());
        teacherHomeVo.setExpTime((null == total.getExpTime()) ? 0 : total.getExpTime());
        teacherHomeVo.setUnExpTime((null == total.getUnExpTime()) ? 0 : total.getUnExpTime());
        return HttpResponseResult.succeed(teacherHomeVo);
    }

    @Override
    public HttpResponseResult<Boolean> openLive(Long id) {
        TeacherTotalVo totalVo = (TeacherTotalVo) redissonClient.getBucket(CacheNameEnum.TEACHER_TOTAL.getRedisKey(id)).get();
        if (null == totalVo) {
            return HttpResponseResult.succeed(false);
        }
        //开通直播需要粉丝数
        Integer fansNum = Integer.parseInt(sysConfigService.findByParamName(SysConfigConstant.OPEN_LIVE_FANS_NUM).getParamValue());
        //开通直播需要已完成课时数
        Integer overClass = Integer.parseInt(sysConfigService.findByParamName(SysConfigConstant.OPEN_LIVE_OVER_CLASS).getParamValue());
        //根据老师规则，判断老师直播权限
        if (totalVo.getFansNum() > fansNum && totalVo.getExpTime() > overClass) {
            Teacher teacher = new Teacher();
            teacher.setUserId(id);
            teacher.setLiveFlag(YesOrNoEnum.YES);
            teacher.setLiveDate(new Date());
            teacher.setUpdateTime(new Date());
            baseMapper.updateById(teacher);
            return HttpResponseResult.status(true);
        } else {
            return HttpResponseResult.failed("不满足开通条件");
        }
    }

    @Override
    public List<Subject> querySubject(Long userId) {
        return baseMapper.querySubject(userId);
    }

    private HttpResponseResult<Boolean> doCreate(TeacherSubmitReq teacherSubmitReq) throws BizException {
        //判断手机号
        SysUser sysUser = employeeDao.querySysUserByPhone(teacherSubmitReq.getPhone());
        if (null != sysUser) {
            return HttpResponseResult.failed("该手机号已经被注册");
        }
        sysUser = new SysUser();
        sysUser = getUserDetil(sysUser, teacherSubmitReq);
        sysUser.setUserType(SysUserType.TEACHER.getCode());
        //初始密码，手机号后6位
        String password = sysUser.getPhone().substring(sysUser.getPhone().length() - 6);
        sysUser.setPassword(new BCryptPasswordEncoder().encode(password));
        //插入
        int num = employeeDao.insertSysUser(sysUser);
        if (num <= 0) {
            throw new BizException("插入用户信息失败");
        }
        //插入老师表
        Teacher teacher = new Teacher();
        teacher.setUserId(sysUser.getId());
        teacher = getTeacherDetil(teacher, teacherSubmitReq);
        baseMapper.insert(teacher);
        return HttpResponseResult.succeed(true);
    }

    private HttpResponseResult<Boolean> doUpdate(TeacherSubmitReq teacherSubmitReq) {
        //判断手机号
        SysUser sysUser = employeeDao.querySysUserByPhone(teacherSubmitReq.getPhone());
        if (null != sysUser && !teacherSubmitReq.getUserId().equals(sysUser.getId())) {
            return HttpResponseResult.failed("该手机号已经被注册");
        }
        sysUser = employeeDao.querySysUserById(teacherSubmitReq.getUserId());
        if (null == sysUser) {
            return HttpResponseResult.failed("未找到用户");
        }
        sysUser = getUserDetil(sysUser, teacherSubmitReq);

        Teacher teacher = baseMapper.selectById(teacherSubmitReq.getUserId());
        teacher = getTeacherDetil(teacher, teacherSubmitReq);
        teacher.setUpdateTime(new Date());
        baseMapper.updateById(teacher);
        if (null == teacher.getEntryAuthDate() || null == teacher.getMusicianDate()) {
            baseMapper.update(teacher, Wrappers.<Teacher>lambdaUpdate()
                    .set(Teacher::getEntryAuthDate, teacher.getEntryAuthDate())
                    .set(Teacher::getMusicianDate, teacher.getMusicianDate())
                    .eq(Teacher::getUserId, teacher.getUserId())
            );
        }

        sysUser.setUpdateTime(new Date());
        employeeDao.updateSysUser(sysUser);
        return HttpResponseResult.succeed(true);
    }

    /***
     * 封装用户信息
     * @author liweifan
     * @updateTime 2022/3/23 17:23
     */
    private SysUser getUserDetil(SysUser sysUser, TeacherSubmitReq teacherSubmitReq) throws BizException {
        if (!teacherSubmitReq.getIdCardNo().equals(sysUser.getIdCardNo())
                || !teacherSubmitReq.getRealName().equals(sysUser.getRealName())) {

            //实名信息
            RealnameAuthReq realNameAuthDto = new RealnameAuthReq();
            realNameAuthDto.setIdCardNo(teacherSubmitReq.getIdCardNo());
            realNameAuthDto.setRealName(teacherSubmitReq.getRealName());
            realNameAuthDto.setSave(false);

            HttpResponseResult<IdcardInfoExtractor> idcardInfoExtractorResult = userFeignService.realNameAuth(realNameAuthDto);
            if (!idcardInfoExtractorResult.getStatus() || null == idcardInfoExtractorResult.getData()) {
                throw new BizException("实名认证未通过");
            }
            //身份证解析信息
            IdcardInfoExtractor idcardInfo = idcardInfoExtractorResult.getData();
            sysUser.setGender(idcardInfo.getGender());
            sysUser.setBirthdate(idcardInfo.getBirthday());
            sysUser.setRealName(teacherSubmitReq.getRealName());
            sysUser.setIdCardNo(teacherSubmitReq.getIdCardNo());
        }

        sysUser.setUsername(teacherSubmitReq.getUsername());
        sysUser.setPhone(teacherSubmitReq.getPhone());
        return sysUser;
    }

    /***
     * 封装老师信息
     * @author liweifan
     * @param: teacherSubmitReq
     * @updateTime 2022/3/23 17:27
     * @return: com.yonge.cooleshow.biz.dal.entity.Teacher
     */
    private Teacher getTeacherDetil(Teacher teacher, TeacherSubmitReq teacherSubmitReq) {
        teacher.setSubjectId(teacherSubmitReq.getSubjectId());
        teacher.setEntryFlag(YesOrNoEnum.NO);
        teacher.setEntryAuthDate(null);
        teacher.setMusicianFlag(YesOrNoEnum.NO);
        teacher.setMusicianDate(null);
        if (StringUtil.isEmpty(teacherSubmitReq.getTeacherType())) {
            return teacher;
        }
        String[] teacherTypes = teacherSubmitReq.getTeacherType().split(",");
        for (String teacherType : teacherTypes) {
            if (TeacherTypeEnum.ENTRY.getCode().equals(teacherType)) {
                teacher.setEntryFlag(YesOrNoEnum.YES);
                teacher.setEntryAuthDate(new Date());
            }
            if (TeacherTypeEnum.MUSICIAN.getCode().equals(teacherType)) {
                teacher.setMusicianFlag(YesOrNoEnum.YES);
                teacher.setMusicianDate(new Date());
            }
        }
        return teacher;
    }

    @Override
    public Integer setSubject(Long id, String subjectIds) {
        return baseMapper.setSubject(id, subjectIds);
    }

    @Override
    public HttpResponseResult<TeacherHomeVo> queryTeacherHome(Long studentId, Long teacherId) {
        TeacherHomeVo data = queryUserInfo(teacherId).getData();
        if (null == data) {
            return HttpResponseResult.failed("未查询到用户信息");
        }
        LiveRoom liveRoom = liveRoomService.getliveingRoomBySpeakerId(teacherId);
        if (null != liveRoom) {
            data.setRoomUid(liveRoom.getRoomUid());
            data.setLiveing(YesOrNoEnum.YES);
        } else {
            data.setLiveing(YesOrNoEnum.NO);
        }

        StudentStar studentStar = studentStarService.getByStudentIdAndTeacherId(studentId, teacherId);
        if (null == studentStar) {
            data.setIsStar(YesOrNoEnum.NO);
        } else {
            data.setIsStar(YesOrNoEnum.YES);
        }
        return HttpResponseResult.succeed(data);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult<TeacherVo> saveTeacherStyle(TeacherDto teacherDto) {
        //修改老师信息
        int i = baseMapper.updateById(teacherDto);
        List<TeacherStyleVideo> styleVideo = teacherDto.getStyleVideo();
        List<TeacherStyleVideo> createList = styleVideo.stream().filter(o -> o.getId() == null)
                .collect(Collectors.toList());

        createList.forEach(o -> o.setUserId(teacherDto.getUserId()));

        List<Long> oldIds = styleVideo.stream().filter(o -> o.getId() != null)
                .map(TeacherStyleVideo::getId).collect(Collectors.toList());
        //删除旧视频
        teacherStyleVideoService.removeByUserIdAndOldIds(teacherDto.getUserId(), oldIds);
        //保存新视频
        teacherStyleVideoService.batchAddStyleVideo(createList);
        return HttpResponseResult.succeed(detail(teacherDto.getUserId()));
    }

    @Override
    public HttpResponseResult<Boolean> addHomeBrowse(Long userId) {
        Integer num = baseMapper.addHomeBrowse(userId);
        return HttpResponseResult.succeed(num > 0);
    }
}