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.biz.dal.enums.*;
import com.yonge.cooleshow.biz.dal.vo.MyFens;
import com.yonge.cooleshow.biz.dal.wordfilter.WordFilter;
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.service.*;
import com.yonge.cooleshow.biz.dal.vo.TeacherAuthEntryRecordVo;
import com.yonge.cooleshow.biz.dal.vo.TeacherHomeVo;
import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.CacheNameEnum;
import com.yonge.cooleshow.common.enums.YesOrNoEnum;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.util.StringUtil;
import com.yonge.toolset.utils.idcard.IdcardInfoExtractor;
import com.yonge.toolset.utils.string.ValueUtil;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
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.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.yonge.cooleshow.biz.dal.constant.LiveRoomConstant.TEACHER_TEMP_LIVE_ROOM;

@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 WordFilter wordFilter;
    @Autowired
    private StudentStarService studentStarService;
    @Autowired
    private UserAccountService userAccountService;
    @Autowired
    private TeacherTotalService totalService;

    @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();
        BeanUtils.copyProperties(teacher,teacherHomeVo);
   
        //身份证号、手机号脱敏
        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 = totalService.getTotalById(userId);

        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());
        teacherHomeVo.setMusicAlbumNum(null == total.getMusicAlbumNum() ? 0 : total.getMusicAlbumNum());
        teacherHomeVo.setMusicSheetNum(null == total.getMusicSheetNum() ? 0 : total.getMusicSheetNum());

        //取直播缓存
        RMap<Long, String> liveMap = redissonClient.getMap(TEACHER_TEMP_LIVE_ROOM);
        String roomUid = liveMap.get(userId);
        if (!StringUtil.isEmpty(roomUid)) {
            teacherHomeVo.setLiveing(YesOrNoEnum.YES);
            teacherHomeVo.setRoomUid(roomUid);
        } else {
            teacherHomeVo.setLiveing(YesOrNoEnum.NO);
        }
        return HttpResponseResult.succeed(teacherHomeVo);
    }

    @Override
    public HttpResponseResult<Boolean> openLive(Long id) {
        TeacherTotal teacherTotal = (TeacherTotal) redissonClient.getBucket(CacheNameEnum.TEACHER_TOTAL.getRedisKey(id)).get();
        if (null == teacherTotal) {
            teacherTotal = new TeacherTotal();
        }

        //开通直播需要粉丝数
        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 (teacherTotal.getFansNum() >= fansNum && teacherTotal.getExpTime() >= overClass) {
            Teacher teacher = new Teacher();
            teacher.setUserId(id);
            teacher.setLiveFlag(YesOrNoEnum.YES);
            teacher.setLiveDate(new Date());
            teacher.setUpdateTime(new Date());
            baseMapper.updateById(teacher);

            // 添加标签
            this.setTeacherTag(id,TeacherTagEnum.LIVE);

            return HttpResponseResult.status(true);
        } else {
            return HttpResponseResult.failed("不满足开通条件");
        }
    }

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


    private HttpResponseResult<Boolean> doCreate(TeacherSubmitReq teacherSubmitReq) throws BizException {
        //更新sys_user
        SysUser sysUser = employeeDao.querySysUserByPhone(teacherSubmitReq.getPhone());
        if (null == sysUser) {
            sysUser = insertSysUser(teacherSubmitReq);
            teacherSubmitReq.setUserId(sysUser.getId());
        } else {
            teacherSubmitReq.setUserId(sysUser.getId());
            updateSysUser(teacherSubmitReq);
        }
        //新增修改老师表
        insertOrUpdateTeacher(teacherSubmitReq);
        return HttpResponseResult.succeed(true);
    }

    private HttpResponseResult<Boolean> doUpdate(TeacherSubmitReq teacherSubmitReq) {
        //更新sys_user
        updateSysUser(teacherSubmitReq);
        //新增修改老师表
        insertOrUpdateTeacher(teacherSubmitReq);
        return HttpResponseResult.succeed(true);
    }

    private SysUser insertSysUser(TeacherSubmitReq teacherSubmitReq) {
        SysUser sysUser = new SysUser();
        sysUser = getUserDetil(sysUser, teacherSubmitReq);
        //初始密码，手机号后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("插入用户信息失败");
        }
        //设置昵称
        sysUser.setUsername("游客" + sysUser.getId());
        employeeDao.updateSysUser(sysUser);
        return sysUser;
    }

    private SysUser updateSysUser(TeacherSubmitReq teacherSubmitReq) {
        //判断手机号
        SysUser sysUser = employeeDao.querySysUserByPhone(teacherSubmitReq.getPhone());
        if (null != sysUser && !teacherSubmitReq.getUserId().equals(sysUser.getId())) {
            throw new BizException("该手机号已经被注册");
        }
        sysUser = employeeDao.querySysUserById(teacherSubmitReq.getUserId());
        if (null == sysUser) {
            throw new BizException("未找到用户");
        }
        sysUser = getUserDetil(sysUser, teacherSubmitReq);
        sysUser.setUpdateTime(new Date());
        employeeDao.updateSysUser(sysUser);
        return sysUser;
    }

    private Teacher insertOrUpdateTeacher(TeacherSubmitReq teacherSubmitReq) {
        Teacher teacher = baseMapper.selectById(teacherSubmitReq.getUserId());
        if (null == teacher) {
            teacher = new Teacher();
            teacher.setUserId(teacherSubmitReq.getUserId());
            teacher = getTeacherDetil(teacher, teacherSubmitReq);
            baseMapper.insert(teacher);

            //插入老师账户表
            UserAccount oldAcc = userAccountService.getById(teacherSubmitReq.getUserId());
            if (null == oldAcc) {
                UserAccount userAccount = new UserAccount();
                userAccount.setUserId(teacherSubmitReq.getUserId());
                userAccountService.save(userAccount);
            }
        } else {
            teacher.setUpdateTime(new Date());
            teacher = getTeacherDetil(teacher, teacherSubmitReq);
            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())
                );
            }
        }

        return teacher;
    }

    /***
     * 封装用户信息
     * @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());
        }
        if (StringUtil.isEmpty(sysUser.getUserType())) {
            sysUser.setUserType("TEACHER");
        } else if (!sysUser.getUserType().contains("TEACHER")) {
            sysUser.setUserType(sysUser.getUserType() + ",TEACHER");
        }
        //设置默认头像
        if(StringUtil.isEmpty(sysUser.getAvatar())){
            String defaultHeard = sysConfigService.findConfigValue(SysConfigConstant.DEFAULT_HEARD);
            sysUser.setAvatar(defaultHeard);
        }

        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) {
        Integer integer = baseMapper.setSubject(id, subjectIds);
        //清除老师声部缓存
        redissonClient.getBucket(CacheNameEnum.TEACHER_SUBJECT_ITEM.getRedisKey(id)).delete();
        return integer;
    }

    @Override
    public HttpResponseResult<TeacherHomeVo> queryTeacherHome(Long studentId, Long teacherId) {
        TeacherHomeVo data = queryUserInfo(teacherId).getData();
        if (null == data) {
            return HttpResponseResult.failed("未查询到用户信息");
        }

        if (null != studentId) {
            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) {
        //校验敏感词
        if (wordFilter.include(teacherDto.getIntroduction(), 3)) {
            throw new BizException("文本包含敏感信息:{}", wordFilter.wordList(teacherDto.getIntroduction()));
        }
        //修改老师信息
        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());
            o.setAuthStatus(AuthStatusEnum.DOING);
            o.setAuditVersion(YesOrNoEnum.NO);
        });

        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);
    }

    @Override
    public List<Subject> querySubjectItem(Long id) {
        List<Subject> subjectList = (List<Subject>) redissonClient.getBucket(CacheNameEnum.TEACHER_SUBJECT_ITEM.getRedisKey(id)).get();
        if (null == subjectList) {
            subjectList = baseMapper.querySubjectItem(id);
            redissonClient.getBucket(CacheNameEnum.TEACHER_SUBJECT_ITEM.getRedisKey(id))
                    .set(subjectList, CacheNameEnum.TEACHER_SUBJECT_ITEM.getDuration().toHours(),
                            TimeUnit.HOURS);
        }
        return subjectList;
    }

    public IPage<MyFens> queryMyFans(IPage<MyFens> page, Long teacherId) {
        List<MyFens> teacherVos = baseMapper.queryMyFans(page, teacherId);
        return page.setRecords(teacherVos);
    }

    @Override
    public void setTeacherTag(Long userId, TeacherTagEnum teacherTagEnum) {
        TeacherVo teacherVo = this.detail(userId);
        if (teacherVo == null) {
            return;
        }
        if (StringUtil.isEmpty(teacherVo.getTag())) {
            teacherVo.setTag(teacherTagEnum.getCode());
        } else  if (teacherVo.getTag().contains(teacherTagEnum.getCode())) {
            return;
        } else {
            teacherVo.setTag(teacherVo.getTag() + "," + teacherTagEnum.getCode());
        }

        this.updateById(teacherVo);
    }

}