package com.jxy.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.jxy.auth.entity.EmailCodeEntity;
import com.jxy.auth.entity.GetEmailCodeEntity;
import com.jxy.auth.service.MailService;
import com.jxy.common.core.RedisTransKey;
import com.jxy.common.core.Result.R;
import com.jxy.common.core.constant.SecurityConstants;
import com.jxy.common.core.utils.CodeUtils;
import com.jxy.common.core.utils.StringUtils;
import com.jxy.common.redis.service.RedisService;
import com.jxy.system.api.RemoteUserService;
import com.jxy.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Description TODO
 * @Date 2022/11/18 15:08
 * @Author 杜懿
 */
@Service
public class MaliServiceImpl implements MailService {
    /**
     * 注入邮件工具类
     */
    @Autowired
    private JavaMailSenderImpl javaMailSender;

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private RedisService redisService;

    @Value("${spring.mail.username}")
    private String sendMailer;

    /**
     * 检测邮件信息类
     * @param to
     * @param subject
     * @param text
     */
    private void checkMail(String to,String subject,String text){
        if(StringUtils.isEmpty(to)){
            throw new RuntimeException("邮件收信人不能为空");
        }
        if(StringUtils.isEmpty(subject)){
            throw new RuntimeException("邮件主题不能为空");
        }
        if(StringUtils.isEmpty(text)){
            throw new RuntimeException("邮件内容不能为空");
        }
    }

    /**
     * 发送纯文本邮件
     * @param to
     * @param subject
     * @param text
     */
    @Override
    public void sendTextMailMessage(String to,String subject,String text){

        try {
            //true 代表支持复杂的类型
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(),true);
            //邮件发信人
            mimeMessageHelper.setFrom(sendMailer);
            //邮件收信人  1或多个
            mimeMessageHelper.setTo(to.split(","));
            //邮件主题
            mimeMessageHelper.setSubject(subject);
            //邮件内容
            mimeMessageHelper.setText(text);
            //邮件发送时间
            mimeMessageHelper.setSentDate(new Date());

            //发送邮件
            javaMailSender.send(mimeMessageHelper.getMimeMessage());
            //System.out.println("发送邮件成功："+sendMailer+"->"+to);

        } catch (Exception e) {
            e.printStackTrace();
            //System.out.println("发送邮件失败："+e.getMessage());
        }
    }


    /**
     * 发送html邮件
     * @param to
     * @param subject
     * @param content
     */
    @Override
    public void sendHtmlMailMessage(String to,String subject,String content){

        content="<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head>\n" +
                "<meta charset=\"utf-8\">\n" +
                "<title>邮件</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "\t<h3>这是一封HTML邮件！</h3>\n" +
                "</body>\n" +
                "</html>";
        try {
            //true 代表支持复杂的类型
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(),true);
            //邮件发信人
            mimeMessageHelper.setFrom(sendMailer);
            //邮件收信人  1或多个
            mimeMessageHelper.setTo(to.split(","));
            //邮件主题
            mimeMessageHelper.setSubject(subject);
            //邮件内容   true 代表支持html
            mimeMessageHelper.setText(content,true);
            //邮件发送时间
            mimeMessageHelper.setSentDate(new Date());

            //发送邮件
            javaMailSender.send(mimeMessageHelper.getMimeMessage());
            System.out.println("发送邮件成功："+sendMailer+"->"+to);

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("发送邮件失败："+e.getMessage());
        }
    }

    /**
     * 发送带附件的邮件
     * @param to      邮件收信人
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param filePath 附件路径
     */
    @Override
    public void sendAttachmentMailMessage(String to,String subject,String content,String filePath){
        try {
            //true 代表支持复杂的类型
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(),true);
            //邮件发信人
            mimeMessageHelper.setFrom(sendMailer);
            //邮件收信人  1或多个
            mimeMessageHelper.setTo(to.split(","));
            //邮件主题
            mimeMessageHelper.setSubject(subject);
            //邮件内容   true 代表支持html
            mimeMessageHelper.setText(content,true);
            //邮件发送时间
            mimeMessageHelper.setSentDate(new Date());
            //添加邮件附件
            FileSystemResource file = new FileSystemResource(new File(filePath));
            String fileName = file.getFilename();
            mimeMessageHelper.addAttachment(fileName, file);

            //发送邮件
            javaMailSender.send(mimeMessageHelper.getMimeMessage());
            //System.out.println("发送邮件成功："+sendMailer+"->"+to);

        } catch (Exception e) {
            e.printStackTrace();
            //System.out.println("发送邮件失败："+e.getMessage());
        }
    }

    /**
     * 发送账号注册邮箱验证码
     * @param to
     * @param code
     */
    @Override
    public void sendCodeMailMessage(String to, String code) {
        String subject = "账号注册，邮箱验证码";
        String text = "注册验证码10分钟内有效:\n\t"+code;
        sendTextMailMessage(to,subject,text);
    }



    @Override
    public void sendResetPwdMailMessage(String to, String code) {
        String subject = "账号重置密码，邮箱验证码";
        String text = "您正在重置密码，如果不是您本人操作，请忽略。验证码10分钟内有效:\n\t"+code;
        sendTextMailMessage(to,subject,text);
    }

    @Override
    public R<?> emailCode(GetEmailCodeEntity entity) {
        String email = entity.getEmail();
        String username = entity.getUserName();

        if(StringUtils.isNull(email)){
            return R.fail(601,"邮箱不能为空");
        }
        if(StringUtils.isNull(username)){
            return R.fail(602,"用户名不能为空");
        }

        //判断用户是不是恶意刷邮箱，在规定时间内进行的
        if (redisService.hasKey(RedisTransKey.getEmailKey(email))) {
            Object o = redisService.getCacheObject(RedisTransKey.getEmailKey(email));//user:emailCode:email

            EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
            if (emailCodeEntity.getTimes() > 4) {
                return R.fail("请求次数过多，请10分钟后再试,(同一用户10分钟内只能请求4次)");
            } else {

                String emailCode = CodeUtils.creatCode(6);
                emailCodeEntity.setEmailCode(emailCode);
                emailCodeEntity.setUserName(username);

                //if(!email.equals(emailCodeEntity.getEmail())){
                //    //email与缓存中所存邮箱不同 则请求次数重置为1
                //    emailCodeEntity.setTimes(1);
                //}else {
                //    emailCodeEntity.setTimes(emailCodeEntity.getTimes() + 1);
                //}

                emailCodeEntity.setTimes(emailCodeEntity.getTimes() + 1);
                long overTime = redisService.getExpire(RedisTransKey.setEmailKey(email));
                redisService.setCacheObject(RedisTransKey.setEmailKey(email), emailCodeEntity, overTime, TimeUnit.SECONDS
                );
                sendCodeMailMessage(email, emailCodeEntity.getEmailCode());
            }
        } else {
            R<LoginUser> userByName = remoteUserService.getUserInfo(username, SecurityConstants.INNER);

            R<LoginUser> userByEmail = remoteUserService.getUserInfo(email, SecurityConstants.INNER);

            if (userByName.getData() != null) {
                return R.fail(603,"用户名"+username+"已被注册");
            } else if(userByEmail.getData() !=null){

                return R.fail(604,"邮箱"+email+"已被注册");
            } else {
                String emailCode = CodeUtils.creatCode(6);
                // 最多允许用户在10分钟内发送2次的邮箱验证
                // 0s倒计时后用户可以再发送验证码，但是间隔在10分钟内只能再发送1次
                EmailCodeEntity emailCodeEntity = new EmailCodeEntity(
                        username  , email, emailCode,1
                );
                //设置失效时间10分钟
                redisService.setCacheObject(RedisTransKey.getEmailKey(email), emailCodeEntity,
                        10L, TimeUnit.MINUTES
                );
                sendCodeMailMessage(email, emailCodeEntity.getEmailCode());
            }
        }
        return R.success("请求成功，验证码已经发送至用户邮箱");

    }

    @Override
    public R<?> AddCreditCode(GetEmailCodeEntity entity) {
        String email = entity.getEmail();
        String username = entity.getUserName();

        if(StringUtils.isNull(email)){
            return R.fail(601,"邮箱不能为空");
        }
        if(StringUtils.isNull(username)){
            return R.fail(602,"用户名不能为空");
        }

        //判断用户是不是恶意刷邮箱，在规定时间内进行的
        if (redisService.hasKey(RedisTransKey.getAddCreditEmailKey(email))) {
            long t1 = System.currentTimeMillis();
            Object o = redisService.getCacheObject(RedisTransKey.getAddCreditEmailKey(email));//user:addCreditEmailCode:email

            com.jxy.system.api.entity.EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), com.jxy.system.api.entity.EmailCodeEntity.class);
            if (emailCodeEntity.getTimes() > 4) {
                return R.fail("请求次数过多，请10分钟后再试,(同一用户10分钟内只能请求4次)");
            } else {

                String emailCode = CodeUtils.creatCode(6);
                emailCodeEntity.setEmailCode(emailCode);
                emailCodeEntity.setUserName(username);


                emailCodeEntity.setTimes(emailCodeEntity.getTimes() + 1);
                long overTime = redisService.getExpire(RedisTransKey.getAddCreditEmailKey(email));
                redisService.setCacheObject(RedisTransKey.setAddCreditEmailKey(email), emailCodeEntity, overTime, TimeUnit.SECONDS
                );
                sendCodeMailMessage(email, emailCodeEntity.getEmailCode());
            }
            long t2 = System.currentTimeMillis();
            System.out.println("处理业务1耗时"+(t2-t1));
        } else {
            long t1 = System.currentTimeMillis();
            String emailCode = CodeUtils.creatCode(6);
                // 最多允许用户在10分钟内发送2次的邮箱验证
                // 0s倒计时后用户可以再发送验证码，但是间隔在10分钟内只能再发送1次
            com.jxy.system.api.entity.EmailCodeEntity emailCodeEntity = new com.jxy.system.api.entity.EmailCodeEntity     (
                        username  , email, emailCode,1
                );
                //设置失效时间10分钟
                redisService.setCacheObject(RedisTransKey.getAddCreditEmailKey(email), emailCodeEntity,
                        10L, TimeUnit.MINUTES
                );
                String subject = "用户提现邮箱验证码";
                String text = "提现验证码,10分钟内有效:\n\t"+emailCodeEntity.getEmailCode();
            long t2 = System.currentTimeMillis();
            System.out.println("处理业务2耗时"+(t2-t1));
                sendTextMailMessage(email,subject,text);
            long t3 = System.currentTimeMillis();
            System.out.println("发送邮箱耗时"+(t3-t2));
        }
        return R.success("请求成功，验证码已经发送至用户邮箱");

    }

    @Override
    public R<?> resetPwdCode(GetEmailCodeEntity entity) {

        String email = entity.getEmail();
        //通过邮箱获取用户
        R<LoginUser> userByEmail = remoteUserService.getUserInfo(email, SecurityConstants.INNER);

        if(StringUtils.isNull(userByEmail.getData())){
            return R.fail("邮箱"+email+"未被注册，请检查邮箱是否正确");
        }

        String username = userByEmail.getData().getUsername();

        //判断用户是不是恶意刷邮箱，在规定时间内进行的
        if (redisService.hasKey(RedisTransKey.getResetPwdKey(email))) {

            Object o = redisService.getCacheObject(RedisTransKey.getResetPwdKey(email));//user:restPwdCode:email

            EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
            if (emailCodeEntity.getTimes() >= 5) {
                return R.fail("请求次数过多，请10分钟后再试");
            } else {
                //这里就不去判断两次绑定的邮箱是不是一样的了，不排除第一次输入错了邮箱的情况
                String emailCode = CodeUtils.creatCode(6);
                emailCodeEntity.setEmailCode(emailCode);
                emailCodeEntity.setTimes(emailCodeEntity.getTimes() + 1);
                long overTime = redisService.getExpire(RedisTransKey.getResetPwdKey(email));
                redisService.setCacheObject(RedisTransKey.getResetPwdKey(email), emailCodeEntity, overTime, TimeUnit.SECONDS
                );
                sendResetPwdMailMessage(email, emailCodeEntity.getEmailCode());
            }
        } else {
            String emailCode = CodeUtils.creatCode(6);
            // 最多允许用户在10分钟内发送2次的邮箱验证
            // 0s倒计时后用户可以再发送验证码，但是间隔在10分钟内只能再发送1次
            EmailCodeEntity emailCodeEntity = new EmailCodeEntity(
                    username  , email, emailCode,1
            );
            //设置失效时间10分钟
            redisService.setCacheObject(RedisTransKey.getResetPwdKey(email), emailCodeEntity,
                    10L, TimeUnit.MINUTES
            );
            sendResetPwdMailMessage(email, emailCodeEntity.getEmailCode());
        }
        return R.success("请求成功，重置密码验证码已经发送至用户邮箱");

    }
}
