package com.inkasso.factoring.common.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.inkasso.adapter.bean.AbstractUser;
import com.inkasso.adapter.exception.ServiceException;
import com.inkasso.adapter.util.CodeUtil;
import com.inkasso.adapter.web.LoginUserHolder;
import com.inkasso.factoring.common.constant.ConstantUtil;
import com.inkasso.factoring.common.service.CommonService;
import com.inkasso.factoring.common.util.VerifyCodeUtil;
import com.inkasso.factoring.common.util.aliyunMail.ShortMessageConstant;
import com.inkasso.factoring.common.util.aliyunMail.ShortMessageUtil;
import com.inkasso.factoring.system.mail.entity.SystemEmail;
import com.inkasso.factoring.system.mail.service.MailService;
import com.inkasso.factoring.system.mail.service.SystemEmailService;
import com.inkasso.factoring.system.user.enums.CodeBusinessTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class CommonServiceImpl implements CommonService {


    private static final String PHONE_BIND_PREFIX = "phoneBind:";

    private static final String PASSWORD_EDIT_PREFIX = "passwordEdit:";

    private static final String EMAIL_BIND_PREFIX = "emailBind:";

    public static final String PASSWORD_RESET_PREFIX = "passwordReset:";

    private static final String REDIS_MARK = ":";


    @Autowired
    private MailService mailService;

    @Autowired
    private SystemEmailService systemEmailService;

    @Autowired
    private RedisTemplate redisTemplate;

    private final String SMS_CODE_PREFIX = "SMS_CODE_PHONE:";

    private final String MAIL_CODE_PREFIX = "MAIL_CODE_EMAIL:";

    @Override
    public void SMSVerification(String phoneNumber, String type) throws Exception {

        String key = null;
        String code = VerifyCodeUtil.createCode(6);
        if (CodeBusinessTypeEnum.PHONE_BIND.getCode().equals(type)) {
            //说明用户是要发送手机验证码
            key = PHONE_BIND_PREFIX + LoginUserHolder.get().getId() + REDIS_MARK + phoneNumber;
        }
        if(CodeBusinessTypeEnum.PASSWORD_RESET.getCode().equals(type)){
            key = PASSWORD_RESET_PREFIX + phoneNumber;
        }
        //密码修改 短信
        if (CodeBusinessTypeEnum.PASSWORD_EDIT.getCode().equals(type)) {
            //如果是 密码修改的短信 则手机号从系统中获取
            phoneNumber = LoginUserHolder.get().getPhone();
            key = PASSWORD_EDIT_PREFIX + LoginUserHolder.get().getId() + REDIS_MARK + phoneNumber;
        }
        //绑定邮箱
        if (CodeBusinessTypeEnum.EMAIL_BIND.getCode().equals(type)) {
            phoneNumber = LoginUserHolder.get().getPhone();
            key = EMAIL_BIND_PREFIX + LoginUserHolder.get().getId() + REDIS_MARK + phoneNumber;
        }
        code = VerifyCodeUtil.createCode(6);
        if (CodeBusinessTypeEnum.OTHER.getCode().equals(type)) {
            key = SMS_CODE_PREFIX + phoneNumber;
            code = code(6);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", code);
        Boolean hasKey = redisTemplate.hasKey(phoneNumber);
        if (hasKey) {
            int count = (int) redisTemplate.opsForValue().get(phoneNumber);
            if (count > 20) {
                throw new ServiceException(CodeUtil.FAIL, "验证码发送过于频繁！");
            } else {
                count ++;
                redisTemplate.opsForValue().set(phoneNumber, count, 1, TimeUnit.DAYS);
            }
        } else {
            redisTemplate.opsForValue().set(phoneNumber, 1, 1, TimeUnit.DAYS);
        }
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        try {
            ShortMessageUtil.sendMessage(phoneNumber,
                    ShortMessageConstant.SEND_PHONE_BIND_TEMPLATE, jsonObject, "长安银科");
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("500", "当天发送短信次数已超出");
        }

//        JSONObject jsonObject = new JSONObject();
//        jsonObject.put("code", code);
//        ShortMessageUtil.sendMessage(phoneNumber, "SMS_464085612", jsonObject, "长安银科");
    }

    @Override
    public boolean verifySMSCode(String phoneNum, String code) {
        String key = SMS_CODE_PREFIX + phoneNum;
        String checkCode = (String) redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(code) && code.equals(checkCode)) {
            redisTemplate.delete(key);
            return true;
        }
        return false;
    }

    @Override
    public void mailVerification(String mail, String type) {

        if (CodeBusinessTypeEnum.EMAIL_BIND.getCode().equals(type)) {
            String code = VerifyCodeUtil.createCode(6);
            String key = EMAIL_BIND_PREFIX + LoginUserHolder.get().getId() + REDIS_MARK + mail;
            redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
            String content = "您正在使用绑定邮箱操作,您的验证码为: " + code;
            mailService.sendSimpleMail(mail, "绑定邮箱验证码", content);
        } else {
            AbstractUser abstractUser = LoginUserHolder.get();
            String key = MAIL_CODE_PREFIX + mail;
            String code = code(6);
            redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
            //构建邮件模板内容
            StringBuilder builder = new StringBuilder();
            builder.append("<!DOCTYPE html>\n" +
                    "<html>\n" +
                    "<head>\n" +
                    "<meta charset=\"utf-8\">\n" +
                    "<title>贸理通验证码</title>\n" +
                    "<style>\n" +
                    ".desc-box {\n" +
                    "margin-top: 20px;\n" +
                    "}\n" +
                    ".desc-box > div {\n" +
                    "margin-bottom: 20px;\n" +
                    "}\n" +
                    ".desc-title {\n" +
                    "margin-left: 40px;\n" +
                    "}\n" +
                    "table,td,th\n" +
                    "{\n" +
                    "border:1px solid black;\n" +
                    "}\n" +
                    "table\n" +
                    "{\n" +
                    "width:100%;\n" +
                    "border: 0px;\n" +
                    "border-collapse:collapse;\n" +
                    "}\n" +
                    "th\n" +
                    "{\n" +
                    "height:50px;\n" +
                    "}\n" +
                    ".table-header\n" +
                    "{\n" +
                    "text-align: center;\n" +
                    "height: 40px;\n" +
                    "font-weight: bold;\n" +
                    "}\n" +
                    ".table-header td {\n" +
                    "}\n" +
                    ".table-body th  {\n" +
                    "height: 30px;\n" +
                    "text-align: center;\n" +
                    "font-weight: normal;\n" +
                    "}\n" +
                    "</style>\n" +
                    "</head>\n" +
                    "<body>\n" +
                    "<div class=\"desc-box\">\n" +
                    "<div>贸理通验证码</div>\n" +
                    "<div class=\"desc-title\">【长安银科】您的验证码为" + code
                    + "，有效期5分钟。请勿泄露!如非您本人操作，请忽略。</div>\n" +
                    "</div>\n" +
                    "</body>\n" +
                    "</html>");
            String subject = "贸理通验证码";
            SystemEmail systemEmail = new SystemEmail();
            systemEmail.setStatus(0);
            systemEmail.setReceiveUser(mail);
            systemEmail.setTitle(subject);
            systemEmail.setContent(builder.toString());
            systemEmail.setSource(ConstantUtil.MAIL_SOURCE_C);
            try {
                systemEmail.setStatus(1);
                mailService.sendHtmlMail(mail, subject, builder.toString());
            } catch (MessagingException e) {
                e.printStackTrace();
            }
            systemEmailService.save(systemEmail);
        }
    }


    @Override
    public boolean verifyMailCode(String mail, String code) {
        String key = MAIL_CODE_PREFIX + mail;
        String checkCode = (String) redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(code) && code.equals(checkCode)) {
            redisTemplate.delete(key);
            return true;
        }
        return false;
    }


    //定义一个方法返回验证码,n代表生成n位数的验证码
    public static String code(int n) {
        //定义一个变量来接生成的字符串
        String code = "";
        Random r = new Random();
        //定义一个for循环来实现n次循环生成n个随机数并整合到一起组成验证码
        for (int i = 0; i < n; i++) {
            //生成一个随机字符：数字、英文大小写字母
            int type = r.nextInt(1);//0 1 2 分别表示数字大小写字母
            switch (type) {
                case 0:
                    //数字
                    code += r.nextInt(10);//0-9
                    break;
                case 1:
                    //小写字母(a 97  z  97+25)
                    char ch = (char) (r.nextInt(26) + 97);
                    code += ch;//code = code +ch
                    break;
                case 2:
                    //大写字母(A 65  Z 65+25)
                    char ch1 = (char) (r.nextInt(26) + 65);
                    code += ch1;//code = code + ch1
                    break;
            }
        }
        //最后返回code值
        return code;
    }
}
