package com.ruoyi.web.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BindStatus;
import com.ruoyi.common.enums.UserRegStatus;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.NumberUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.dz.domain.DzCards;
import com.ruoyi.dz.service.IDzCardsService;
import com.ruoyi.enums.CardDistributeStatus;
import com.ruoyi.enums.CardStatus;
import com.ruoyi.enums.UserTypeEnum;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.learn.domain.LearnStudent;
import com.ruoyi.learn.mapper.LearnStudentMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.web.domain.CardUserBody;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.ValidationException;
import java.text.ParseException;
import java.util.List;

/**
 * 注册校验方法
 *
 * @author ruoyi
 */
@Component
public class SysRegisterService
{
    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IDzCardsService cardsService;

    @Autowired
    private TokenService tokenService;
    @Autowired
    private LearnStudentMapper learnStudentMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private LearnTeacherService learnTeacherService;

    /**
     * 注册
     */
    @Transactional(rollbackFor = Exception.class)
    public String register(RegisterBody registerBody, LoginUser loginUser)
    {
        String username = registerBody.getUsername(), mobile = registerBody.getMobile(), password = registerBody.getPassword();
        DzCards upCard = null;
        SysUser upUser = new SysUser();
        upUser.setPhonenumber(mobile);
        if(null == loginUser) { // 手机注册或卡注册
            if (StringUtils.isBlank(mobile)) {
                return "手机号不能为空";
            }
            if(StringUtils.isNotBlank(username)) { // 卡注册
                DzCards exist = cardsService.selectDzCardsByCardNo(username);
                if (StringUtils.isNull(exist)) {
                    return "卡号密码不正确";
                }
                if(StringUtils.isBlank(password) || !password.equals(exist.getPassword())) {
                    return "卡号密码不正确";
                }
                upCard = new DzCards();
                upCard.setCardId(exist.getCardId());
                upCard.setStatus(exist.getStatus());
                upCard.setDistributeStatus(exist.getDistributeStatus());
                upCard.setDays(exist.getDays());
            } else {
                username = mobile;
                password = "123456";
                registerBody.setUsername(username); // TODO 带回去重登陆
                registerBody.setPassword(password); // TODO 带回去重登陆
            }
            upUser.setWxOpenId(registerBody.getOpenId());
            upUser.setPassword2(SecurityUtils.encryptPassword2(password));
            upUser.setPassword(SecurityUtils.encryptPassword(password));
            upUser.setPwdUpdateDate(DateUtils.getNowDate());
        } else {// 注册用户完善 不能改手机, 不能改邀请码
            DzCards exist = cardsService.selectDzCardsByCardNo(username);
            if(null == exist) {
                throw new BaseException("卡号不存在: " + username);
            }
            username = exist.getCardNo();
            upCard = new DzCards();
            upCard.setCardId(exist.getCardId());
            upCard.setStatus(exist.getStatus());
            upCard.setDistributeStatus(exist.getDistributeStatus());
            upCard.setDays(exist.getDays());
            upUser.setUserId(loginUser.getUserId());
            upUser.setBindStatus(loginUser.getUser().getBindStatus());
        }
        upUser.setUserName(username);
        if (StringUtils.isEmpty(username)) {
            return "用户名不能为空";
        }
        else if (StringUtils.isEmpty(password))
        {
            return "用户密码不能为空";
        }
        else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            return "账户长度必须在2到20个字符之间";
        }
        else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            return "密码长度必须在5到20个字符之间";
        }
        else if (!userService.checkUserNameUnique(upUser))
        {
            return "保存用户'" + username + "'失败，注册卡号已存在";
        }
        else if (!userService.checkPhoneUnique(upUser))
        {
            return "保存用户'" + username + "'失败，注册手机已存在" + mobile;
        }
        saveInfo(upUser, upCard, registerBody); // 注册或完善后刷新登陆信息
        if(null != loginUser) {
            BeanUtils.copyProperties(userService.selectUserById(loginUser.getUserId()), loginUser.getUser(), "password");
            if(null != upCard.getCardId()) {
                BeanUtils.copyProperties(cardsService.selectDzCardsByCardId(upCard.getCardId()), loginUser.getCard());
            }
            tokenService.refreshToken(loginUser);
        }
        return "";
    }

    @Transactional(rollbackFor = Exception.class)
    public void improve(CardUserBody cardUserBody) {
        DzCards card = cardsService.selectDzCardsByCardId(cardUserBody.getCardId());
        if(null == card) {
            throw new ValidationException("卡用户不存在");
        }
        List<SysUser> sysUserList = sysUserMapper.selectUserByCardIds(Lists.newArrayList(card.getCardId()));
        if(CollectionUtils.isEmpty(sysUserList)) {
            throw new ValidationException("卡用户不存在");
        }
        SysUser dbUser = sysUserList.get(0);
        Long userId = dbUser.getUserId();
        SysUser upUser = new SysUser();
        upUser.setUserId(userId);
        upUser.setNickName(cardUserBody.getNickName());
        upUser.setLocation(cardUserBody.getLocation());
        upUser.setExamType(cardUserBody.getExamType());
        upUser.setEndYear(cardUserBody.getEndYear());
        upUser.setScores(cardUserBody.getScores());
        upUser.setSchoolId(cardUserBody.getSchoolId());
        upUser.setClassId(cardUserBody.getClassId());
        upUser.setPhonenumber(cardUserBody.getMobile());
        //如果手机号有修改，校验userName为手机号时也要跟着一起修改
        if(null!=dbUser.getPhonenumber()&&!dbUser.getPhonenumber().equals(cardUserBody.getMobile().trim())) {
            if (dbUser.getPhonenumber().equalsIgnoreCase(dbUser.getUserName())){
                upUser.setUserName(cardUserBody.getMobile().trim());
            }
        }
        upUser.setExamMajor(cardUserBody.getExamMajor());
        upUser.setExamMajorName(cardUserBody.getExamMajorName());
        if (!userService.checkPhoneUnique(upUser)) {
            throw new ValidationException("保存用户'" + upUser.getNickName() + "'失败，注册手机已存在" + cardUserBody.getMobile());
        }
        JSONArray directList = cardUserBody.getDirectionStudy();
        if (null != directList && !directList.isEmpty()) {
            JSONObject directed = directList.getJSONObject(0);
            Long planId = directed.getLongValue("majorId");
            Long universityId = directed.getLongValue("universityId");
            directed.put("notice", learnTeacherService.updateDirected(userId, universityId, planId));
            cardUserBody.getDirectionStudy().set(0, directed);
            upUser.setDirectedStudy(cardUserBody.getDirectionStudy().toJSONString());
        }
        DzCards upCard = new DzCards();
        upCard.setCardId(card.getCardId());
        upCard.setSchoolId(cardUserBody.getSchoolId());
        upCard.setClassId(cardUserBody.getClassId());
        upCard.setCampusId(cardUserBody.getCampusSchoolId());
        upCard.setCampusClassId(cardUserBody.getCampusClassId());
        upCard.setOutDate(cardUserBody.getOutDate());
        userService.updateUserInfo(upUser);
        cardsService.updateDzCards(upCard);

        LearnStudent upStudent = new LearnStudent();
        upStudent.setStudentId(upUser.getUserId());
        if(NumberUtils.isPositive(upCard.getCampusClassId())) {
            upStudent.setClassId(upCard.getCampusClassId());
        } else if(null == card.getCampusClassId()) {
            upStudent.setClassId(upCard.getClassId());
        }
        upStudent.setSchoolId(upCard.getSchoolId());
        upStudent.setCampusId(upCard.getCampusId());
        learnStudentMapper.updateLearnStudent(upStudent);
        /**LearnStudent learnStudent = learnStudentMapper.selectLearnStudentByStudentId(userId);
        if (null!=learnStudent){
            learnStudent.setStudentName(register.getNickName());

        }**/
    }

    private void saveInfo(SysUser user, DzCards card, RegisterBody register) {
        register.setCampusSchoolId(null);
        register.setCampusClassId(null);
        user.setNickName(register.getNickName());
        user.setLocation(register.getLocation());
        user.setExamType(register.getExamType());
        user.setExamMajor(register.getExamMajor());
        user.setEndYear(register.getEndYear());
        user.setScores(register.getScores());
        user.setSchoolId(register.getSchoolId());
        user.setClassId(register.getClassId());

        if(null == card) { // 手机注册时 无卡
            user.setInviteCode(register.getInviteCode()); //
            user.setRegStatus(UserRegStatus.User);
        } else {
            card.setEndYear(register.getEndYear());
            card.setYear(register.getEndYear() - 3);
            card.setSchoolId(register.getSchoolId());
            card.setClassId(register.getClassId());

            if(null == user.getCardId() || !user.getCardId().equals(card.getCardId()) || BindStatus.Pend.code().equals(user.getBindStatus())) { // 未绑定或换绑时激活卡
                if(!CardDistributeStatus.Assign.getVal().equals(card.getDistributeStatus()) || !CardStatus.Free.getVal().equals(card.getStatus())) {
                    throw new RuntimeException("无效卡");
                }
                if(BindStatus.Pend.code().equals(user.getBindStatus())) {
                    user.setBindStatus(BindStatus.Bind.code());
                }
                user.setEvalCounts("{\"1\":3,\"2\":3,\"3\":3,\"4\":3,\"9\":3,\"11\":10,\"0\":0}");
                user.setCardId(card.getCardId());
                user.setRegStatus(UserRegStatus.Student);
                card.setStatus(CardStatus.Active.getVal());
                card.setActiveTime(DateUtils.getNowDate());
                if(null != card.getDays()) {
                    card.setOutDate(DateUtils.addDays(card.getActiveTime(), card.getDays()));
                }
            }
            try {
                if(null == card.getDays()) {
                    card.setOutDate(DateUtils.parseDate(register.getEndYear() + "-04-30", "yyyy-MM-dd"));
                }
                card.setDays(null);
            } catch (ParseException e) {
                throw new RuntimeException("saveInfo 日期错误", e);
            }
        }
        if(null == user.getUserId()) {
            user.setUserType(UserTypeEnum.Card.getVal());
            userService.insertUser(user);
            LearnStudent upStudent = new LearnStudent();
            upStudent.setStudentId(user.getUserId());
            if(null == card || null == card.getCampusClassId()) {
                upStudent.setClassId(user.getClassId());
            } else {
                upStudent.setClassId(card.getCampusClassId());
            }
            upStudent.setSchoolId(user.getSchoolId());
            upStudent.setCampusId(register.getCampusSchoolId());
            learnStudentMapper.insertLearnStudent(upStudent);
        } else {
            LearnStudent upStudent = new LearnStudent();
            upStudent.setStudentId(user.getUserId());
            upStudent.setSchoolId(user.getSchoolId());
            if(null == card || null == card.getCampusClassId()) {
                upStudent.setClassId(user.getClassId());
            }
            learnStudentMapper.updateLearnStudent(upStudent);
            userService.updateUser(user);
        }
        if(null != card) {
            cardsService.updateDzCards(card);
        }
    }

    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
    public void validateCaptcha(String username, String code, String uuid)
    {
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
        String captcha = redisCache.getCacheObject(verifyKey);
        redisCache.deleteObject(verifyKey);
        if (captcha == null)
        {
            throw new CaptchaExpireException();
        }
        if (!code.equalsIgnoreCase(captcha))
        {
            throw new CaptchaException();
        }
    }

    public void validateSmsCaptcha(String mobile, String code, String uuid) {

    }
}
