package com.shining.cloud.serviceImpl.user;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.njcn.enums.app.MessageEnum;
import com.njcn.enums.app.UserCodeEnum;
import com.njcn.enums.app.UserLevelEnum;
import com.njcn.mapper.app.AppInfoSetMapper;
import com.njcn.mapper.app.AppSendMsgMapper;
import com.njcn.mapper.user.AppUserMapper;
import com.njcn.mapper.user.SecretKeyMapper;
import com.njcn.mapper.user.UserMapper;
import com.njcn.pojo.app.AppInfoSet;
import com.njcn.pojo.app.AppSendMsg;
import com.njcn.pojo.commons.RedisDB;
import com.njcn.pojo.user.AppUser;
import com.njcn.pojo.user.SecretKey;
import com.njcn.sso.pojo.user.User;
import com.njcn.utils.AESUtil;
import com.njcn.utils.MD5;
import com.njcn.utils.PubUtils;
import com.njcn.utils.SM.SM4Utils;
import com.njcn.utils.redis.JedisManager;
import com.shining.cloud.enums.AliMsgResponseEnum;
import com.shining.cloud.pojo.common.SmsConstant;
import com.shining.cloud.pojo.user.MessageResult;
import com.shining.cloud.pojo.user.UserResult;
import com.shining.cloud.service.user.AppUserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AccountException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import scala.App;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author hongawen
 * @date: 2019/10/17 11:37
 */
@Service
public class AppUserServiceImpl implements AppUserService {

    private static final Logger logger = LoggerFactory.getLogger(AppUserServiceImpl.class);

    @Resource
    private AppUserMapper appUserMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private JedisManager jedisManager;

    @Resource
    private AppInfoSetMapper appInfoSetMapper;

    @Resource
    private AppSendMsgMapper appSendMsgMapper;

    @Resource
    private SecretKeyMapper secretKeyMapper;


    /**
     * 手机号注册账户
     *
     * @param phone   手机号
     * @param devcode 设备ID
     */
    @Override
    public UserResult register(String phone, String code, String devcode) {
        UserResult userResult = new UserResult();
        judgeCode(phone, code, devcode);
        //先根据手机号查询是否已被注册
        AppUser appUser = new AppUser();
        appUser.setPhone(phone);
        appUser = appUserMapper.selectOne(appUser);
        //暂时取消排重
        if (null != appUser) {
            throw new AccountException(UserCodeEnum.REGIST_PHONE_FAIL.getMsg());
            //执行更新操作
//            appUser.setLoginErrorTimes(0);
//            appUser.setLoginTime(new Date());
//            appUser.setPsdValidity(appUser.getLoginTime());
//            appUser.setRegisterTime(appUser.getLoginTime());
//            appUser.setUserLevel("1");
//            appUser.setDevCode(devcode);
//            appUser.setState(1);
//            try {
//                appUserMapper.updateByPrimaryKey(appUser);
//                userResult.setUserId(appUser.getUserIndex());
//                userResult.setRoleName(UserLevelEnum.getMsgByCode(appUser.getUserLevel()));
//                userResult.setPhone(appUser.getPhone());
//                userResult.setRoleCode(appUser.getUserLevel());
//                userResult.setUserName(StringUtils.isEmpty(appUser.getName())?null:appUser.getName());
//            } catch (Exception e) {
//                logger.error("注册异常" + e.toString());
//                throw new AccountException(UserCodeEnum.REGIST_FAIL.getMsg());
//            }
        } else {
            appUser = new AppUser();
            appUser.setUserIndex(UUID.randomUUID().toString());
            appUser.setPhone(phone);
            appUser.setLoginErrorTimes(0);
            appUser.setLoginTime(new Date());
            appUser.setPsdValidity(appUser.getLoginTime());
            appUser.setRegisterTime(appUser.getLoginTime());
            appUser.setUserLevel("1");
            appUser.setDevCode(devcode);
            logger.info("插入手机id：" + devcode);
            appUser.setReferralCode("DUCxda");
            appUser.setState(1);
            //消息默认配置
            AppInfoSet appInfoSet = new AppInfoSet();
            appInfoSet.setUserIndex(appUser.getUserIndex());
            appInfoSet.setDeviceInfo(1);
            appInfoSet.setEventInfo(1);
            appInfoSet.setSystemInfo(1);
            appInfoSet.setTargetInfo(1);
            try {
                appUserMapper.insert(appUser);
                appInfoSetMapper.insert(appInfoSet);
                userResult.setUserId(appUser.getUserIndex());
                userResult.setRoleName(UserLevelEnum.getMsgByCode(appUser.getUserLevel()));
            } catch (Exception e) {
                logger.error("注册异常" + e.toString());
                throw new AccountException(UserCodeEnum.REGIST_FAIL.getMsg());
            }
            userResult.setPhone(appUser.getPhone());
            userResult.setRoleCode(appUser.getUserLevel());
            userResult.setUserName(StringUtils.isEmpty(appUser.getName()) ? null : appUser.getName());
        }
        return userResult;
    }

    private void judgeCode(String phone, String code, String devcode) {
        String key = phone + devcode;
        String redisCode = jedisManager.getValueByKey(RedisDB.CODE_DB, key);
        if (StringUtils.isEmpty(redisCode) || !code.equalsIgnoreCase(redisCode)) {
            throw new AccountException(UserCodeEnum.CODE_ERROR.getMsg());
        } else {
            //存在且正确的验证，用完即删
            jedisManager.deleteByKey(RedisDB.CODE_DB, key);
        }
    }

    /**
     * app用户设置密码
     *
     * @param userId   用户索引
     * @param devCode  设备ID
     * @param password 新密码
     */
    @Override
    public void setPsd(String userId, String devCode, String password) throws Exception {
        //查看是否存在该用户
        AppUser appUser = new AppUser();
        appUser.setUserIndex(userId);
        appUser = appUserMapper.selectOne(appUser);
        if (null == appUser) {
            throw new AccountException(UserCodeEnum.NO_USER.getMsg());
        } else {
            String appPwd = AESUtil.aesPKCS5PaddingEncrypt(password);
            appUser.setPassword(appPwd);
            appUser.setDevCode(devCode);
            logger.info("更新手机id：" + devCode);
            appUserMapper.updateByPrimaryKey(appUser);

        }
    }

    /**
     * 修改主用户的密码
     *
     * @param userIndex 用户索引
     * @param password  新密码
     */
    private void modifyWebPwd(String userIndex, String password) {
        User user = new User();
        user.setUserIndex(userIndex);
        user = userMapper.selectOne(user);
        if (user == null) {
            throw new AccountException(UserCodeEnum.NO_MAIN_USER.getMsg());
        }
        SecretKey secretKey1 = new SecretKey();
        secretKey1.setUserIndex(user.getUserIndex());
        secretKey1 = secretKeyMapper.selectOne(secretKey1);
        if (secretKey1 == null) {
            throw new AccountException(UserCodeEnum.NO_USER_SETTING.getMsg());
        }
        String secretkey;
        String strsm4;
        String strpwd;
        try {
            secretkey = PubUtils.GetSecretKey();
            SM4Utils sm4 = new SM4Utils(secretkey);
            strsm4 = sm4.encryptData_ECB(password);
            strpwd = sm4.encryptData_ECB(strsm4 + secretkey);
        } catch (Exception ex) {
            throw new AccountException("用户密码国密加密失败");
        }

        user.setPassword(strpwd);
        user.setPsdvalidity(new Date());
        user.setLoginTime(user.getPsdvalidity());
        user.setState(1);
        secretKey1.setSecretKey(secretkey);
        secretKey1.setStandBy(strsm4);
        //更新用户
        userMapper.updateByPrimaryKeyBySql(user);
        secretKeyMapper.updateByPrimaryKey(secretKey1);
    }

    /**
     * 忘记密码--重置密码
     *
     * @param phone    手机号
     * @param code     验证码
     * @param password 新密码
     * @param devCode  设备ID
     */
    @Override
    public void resetPsd(String phone, String code, String password, String devCode) throws Exception {
        AppUser appUser = new AppUser();
        appUser.setPhone(phone);
        appUser = appUserMapper.selectOne(appUser);
        if (null == appUser) {
            throw new AccountException(UserCodeEnum.NO_USER.getMsg());
        } else {
            judgeCode(phone, code, devCode);
            String strpwd = AESUtil.aesPKCS5PaddingEncrypt(password);
            appUser.setPassword(strpwd);
            appUser.setDevCode(devCode);
            logger.info("更新手机id：" + devCode);
            appUserMapper.updateByPrimaryKey(appUser);
            //如果是主用户，还需要更新pqs_user表的用户密码
            if (appUser.getUserLevel().equalsIgnoreCase(UserLevelEnum.HOST_USER.getCode())) {
                modifyWebPwd(appUser.getUserIndex(), password);
            }
        }
    }

    /**
     * 修改密码
     *
     * @param userId   用户id
     * @param password 新密码
     * @param devCode  设备id
     */
    @Override
    public void modifyPsd(String userId, String phone, String code, String password, String devCode) throws Exception {
        AppUser appUser = new AppUser();
        appUser.setUserIndex(userId);
        appUser = appUserMapper.selectOne(appUser);
        if (null == appUser) {
            throw new AccountException(UserCodeEnum.NO_USER.getMsg());
        } else {
            judgeCode(phone, code, devCode);
            String strpwd = AESUtil.aesPKCS5PaddingEncrypt(password);
            appUser.setPassword(strpwd);
            appUser.setDevCode(devCode);
            logger.info("更新手机id：" + devCode);
            appUserMapper.updateByPrimaryKey(appUser);
            //如果是主用户，还需要更新pqs_user表的用户密码
            if (appUser.getUserLevel().equalsIgnoreCase(UserLevelEnum.HOST_USER.getCode())) {
                modifyWebPwd(appUser.getUserIndex(), password);
            }
        }
    }


    /**
     * 升级权限
     *
     * @param userId       用户id
     * @param referralCode 推荐码
     * @param devCode      设备ID
     */
    @Override
    public UserResult roleUpdate(String userId, String referralCode, String devCode) {
        UserResult userResult = new UserResult();
        //判断推荐码是否非法
        User user = new User();
        user.setReferralCode(referralCode);
        try {
            user = userMapper.selectOne(user);
            if (null == user) {
                throw new AccountException(UserCodeEnum.REFERRAL_CODE_ERROR.getMsg());
            } else {
                AppUser appUser = new AppUser();
                appUser.setUserIndex(userId);
                appUser = appUserMapper.selectOne(appUser);
                if (null == appUser) {
                    throw new AccountException(UserCodeEnum.NO_USER.getMsg());
                } else {
                    appUser.setUserLevel("2");
                    appUser.setDevCode(devCode);
                    logger.info("更新手机id：" + devCode);
                    appUser.setReferralCode(referralCode);
                    appUserMapper.updateByPrimaryKey(appUser);
                    userResult.setRoleCode("2");
                    userResult.setRoleName(UserLevelEnum.getMsgByCode(appUser.getUserLevel()));
                }
            }
        } catch (Exception e) {
            throw new AccountException(UserCodeEnum.REFERRAL_CODE_ERROR.getMsg());
        }
        return userResult;
    }

    /**
     * 发送短信
     *
     * @param phone   手机号
     * @param devCode 设备ID
     * @param type    短信类型
     */
    @Override
    public void setMessage(String phone, String devCode, String type) {
        String msgTemplate;
        switch (type) {
            case "0":
                msgTemplate = MessageEnum.getTemplateByCode(0);
                break;
            case "1":
                msgTemplate = MessageEnum.getTemplateByCode(1);
                break;
            case "2":
                msgTemplate = MessageEnum.getTemplateByCode(2);
                break;
            case "3":
                msgTemplate = MessageEnum.getTemplateByCode(3);
                break;
            case "4":
                msgTemplate = MessageEnum.getTemplateByCode(4);
                break;
            case "5":
                msgTemplate = MessageEnum.getTemplateByCode(5);
                break;
            default:
                throw new AccountException(UserCodeEnum.CODE_TYPE_ERROR.getMsg());
        }
        //type为4，账号替换为新手机号
        if (!msgTemplate.equalsIgnoreCase(MessageEnum.REGISTER.getTemplateCode())) {
            AppUser appUser = new AppUser();
            if ("4".equalsIgnoreCase(type)) {
                //注册，无需判断手机号与设备的匹配
                appUser.setPhone(phone);
                appUser = appUserMapper.selectOne(appUser);
                if (appUser != null) {
                    throw new AccountException(UserCodeEnum.REGIST_PHONE_FAIL.getMsg());
                }
            } else {
                appUser.setPhone(phone);
                appUser = appUserMapper.selectOne(appUser);
                if (null == appUser) {
                    throw new AccountException(UserCodeEnum.NO_USER.getMsg());
                } else {
                    appUser.setDevCode(devCode);
                    logger.info("更新手机id：" + devCode);
                    appUserMapper.updateByPrimaryKey(appUser);
                }
            }
        }
        //开始执行短信发送
        try {
            //设置超时时间-可自行调整
            System.setProperty(SmsConstant.DEFAULT_CONNECT_TIME_OUT, "10000");
            System.setProperty(SmsConstant.DEFAULT_READ_TIME_OUT, "10000");
            IClientProfile profile = DefaultProfile.getProfile(SmsConstant.LOCATION, SmsConstant.ACCESS_KEY_ID, SmsConstant.ACCESS_KEY_SECRET);
            DefaultProfile.addEndpoint(SmsConstant.LOCATION, SmsConstant.LOCATION, SmsConstant.PRODUCT, SmsConstant.DOMAIN);
            IAcsClient acsClient = new DefaultAcsClient(profile);
            SendSmsRequest request = new SendSmsRequest();
            request.setMethod(MethodType.POST);
            request.setPhoneNumbers(phone);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName(SmsConstant.SGIN);
            //必填:短信模板-可在短信控制台中找到，发送国际/港澳台消息时，请使用国际/港澳台短信模版
            request.setTemplateCode(msgTemplate);
            String vCode = getMessageCode();
            String code = "{\"code\":\"" + vCode + "\"}";
            request.setTemplateParam(code);
            //请求失败这里会抛ClientException异常
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
            String key = phone + devCode;
            if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
                //成功发送短信验证码后，保存进redis
                jedisManager.saveValueByKey(RedisDB.CODE_DB, key, vCode, RedisDB.CODE_DB_TIME);
            } else {
                if (Objects.nonNull(AliMsgResponseEnum.getAliMsgEnum(sendSmsResponse.getCode()))) {
                    //判断短信接口的回执是否在黑名单内，如果在则以后该手机号直接屏蔽
                    jedisManager.saveValueByKey(RedisDB.CODE_DB, RedisDB.SMS_PHONE.concat(phone), AliMsgResponseEnum.MOBILE_IN_BLACK.getMsg(), -1);
                }
                throw new AccountException(UserCodeEnum.SEND_CODE_FAIL.getMsg());
            }
            AppSendMsg appSendMsg = new AppSendMsg();
            appSendMsg.setPhone(phone);
            appSendMsg.setMessage(vCode);
            appSendMsg.setSendTime(new Date());
            appSendMsg.setSendStatus(sendSmsResponse.getCode() == null ? "无状态" : sendSmsResponse.getCode());
            appSendMsgMapper.insert(appSendMsg);
        } catch (Exception e) {
            logger.error("发送短信异常：" + e);
            throw new AccountException(UserCodeEnum.SEND_CODE_FAIL.getMsg());
        }
    }

    /**
     * 重新绑定手机号码
     *
     * @param userId   用户索引
     * @param phoneNew 新手机号
     * @param devCode  设备ID
     */
    @Override
    public void rebindPhone(String userId, String phoneNew, String devCode, String code) {
        //先判断新号码是否已经被注册过
        AppUser tempAppUser = new AppUser();
        tempAppUser.setPhone(phoneNew);
        tempAppUser = appUserMapper.selectOne(tempAppUser);
        if (null != tempAppUser) {
            throw new AccountException(UserCodeEnum.REGIST_PHONE_FAIL.getMsg());
        }
        judgeCode(phoneNew, code, devCode);
        AppUser appUser = new AppUser();
        appUser.setUserIndex(userId);
        appUser = appUserMapper.selectOne(appUser);
        if (null == appUser) {
            throw new AccountException(UserCodeEnum.NO_USER.getMsg());
        }
        //执行更新手机号
        try {
            appUser.setPhone(phoneNew);
            appUser.setDevCode(devCode);
            logger.info("更新手机id：" + devCode);
            appUserMapper.updateByPrimaryKey(appUser);
            //如果是主用户，还需要更新pqs_user表的用户手机
            if (appUser.getUserLevel().equalsIgnoreCase(UserLevelEnum.HOST_USER.getCode())) {
                User user = new User();
                user.setUserIndex(appUser.getUserIndex());
                user = userMapper.selectOne(user);
                if (null == user) {
                    throw new AccountException(UserCodeEnum.NO_MAIN_USER.getMsg());
                } else {
                    user.setPhone(phoneNew);
                    userMapper.updateByPrimaryKeyBySql(user);
                }
            }
        } catch (Exception e) {
            logger.error("更新手机号异常" + e.toString());
            throw new AccountException(UserCodeEnum.REST_PHONE_FAIL.getMsg());
        }
    }

    /**
     * 用户消息配置
     *
     * @param userId     用户索引
     * @param eventInfo  暂态消息模块
     * @param targetInfo 稳态消息模块
     * @param deviceInfo 终端消息模块
     * @param systemInfo 系统消息模块
     */
    @Override
    public void msgSet(String userId, String eventInfo, String targetInfo, String deviceInfo, String systemInfo) {
        //先判断有没有该用户，再判断有没有消息配置数据
        AppUser appUser = new AppUser();
        appUser.setUserIndex(userId);
        appUser = appUserMapper.selectOne(appUser);
        if (null == appUser) {
            throw new AccountException(UserCodeEnum.NO_USER.getMsg());
        }
        AppInfoSet appInfoSet = new AppInfoSet();
        appInfoSet.setUserIndex(userId);
        appInfoSet = appInfoSetMapper.selectOne(appInfoSet);
        if (null == appInfoSet) {
            throw new AccountException(UserCodeEnum.NO_APPINFOSET.getMsg());
        }
        try {
            appInfoSet.setTargetInfo(Integer.parseInt(targetInfo));
            appInfoSet.setEventInfo(Integer.parseInt(eventInfo));
            appInfoSet.setSystemInfo(Integer.parseInt(systemInfo));
            appInfoSet.setDeviceInfo(Integer.parseInt(deviceInfo));
            appInfoSetMapper.updateByPrimaryKey(appInfoSet);
        } catch (Exception e) {
            logger.error("用户设置消息失败，异常：" + e.toString());
            throw new AccountException(UserCodeEnum.SET_INFO_FAIL.getMsg());
        }
    }

    /**
     * 获用户取消息配置
     *
     * @param userId  用户ID
     * @param devCode 设备id
     */
    @Override
    public MessageResult getMsg(String userId, String devCode) {
        MessageResult messageResult = new MessageResult();
        AppUser appUser = new AppUser();
        appUser.setUserIndex(userId);
        appUser = appUserMapper.selectOne(appUser);
        if (null == appUser) {
            throw new AccountException(UserCodeEnum.NO_USER.getMsg());
        } else {
            appUser.setDevCode(devCode);
            logger.info("更新手机id：" + devCode);
            appUserMapper.updateByPrimaryKey(appUser);
            AppInfoSet appInfoSet = new AppInfoSet();
            appInfoSet.setUserIndex(userId);
            appInfoSet = appInfoSetMapper.selectOne(appInfoSet);
            if (null == appInfoSet) {
                throw new AccountException(UserCodeEnum.NO_APPINFOSET.getMsg());
            } else {
                messageResult.setPhone(appUser.getPhone());
                messageResult.setDeviceInfo(appInfoSet.getDeviceInfo());
                messageResult.setEventInfo(appInfoSet.getEventInfo());
                messageResult.setSystemInfo(appInfoSet.getSystemInfo());
                messageResult.setTargetInfo(appInfoSet.getTargetInfo());
            }
        }
        return messageResult;
    }

    /**
     * 验证旧手机号码的验证码
     *
     * @param phone
     * @param devCode
     * @param code
     */
    @Override
    public void comfirmCode(String phone, String devCode, String code) {
        judgeCode(phone, code, devCode);
    }


    /**
     * 自定义获取验证码，固定为字母和数字的组合
     */
    private String getMessageCode() {
        String result = "";
        char[] numbers = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        //填充数字
        for (int i = 0; i < 6; i++) {
            int numberIndex = new Random().nextInt(10);
            result = result + numbers[numberIndex];
        }
        return result;
    }

}


