package com.ruoyi.system.service;

import com.alibaba.fastjson2.JSONObject;
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.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.VerifyCodeUtils;
import com.ruoyi.enums.SmsTypeEnum;
import com.ruoyi.system.domain.SysSmsBlacklist;
import com.ruoyi.system.domain.SysSmsLog;
import com.ruoyi.system.mapper.SysSmsLogMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class ShortMessageService {
    private Log logger = LogFactory.getLog(ShortMessageService.class);

    @Value("${aliyun.sms.accessKeyId}")
    private String accessKeyId ;
    @Value("${aliyun.sms.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyun.sms.defaultConnectTimeout}")
    private String defaultConnectTimeout ;
    @Value("${aliyun.sms.defaultReadTimeout}")
    private String defaultReadTimeout;
    @Value("${aliyun.sms.signName}")
    private String signName;
    @Value("${aliyun.sms.duration}")
    private Integer duration;

    @Value("${aliyun.sms.templateCode}")
    private String templateCode;
    @Value("${aliyun.sms.ecardTemplateCode}")
    private String ecardTemplateCode;
//    @Value("${aliyun.sms.template.validateIdentity}")
//    private String templateCodeAccount;

    //产品名称:云通信短信API产品,开发者无需替换
    private static final String product = "Dysmsapi";
    //产品域名,开发者无需替换
    private static final String domain = "dysmsapi.aliyuncs.com";

    @Autowired
    private SysSmsLogMapper smsLogMapper;
    @Autowired
    private ISysSmsBlacklistService smsBlacklistService;
    @Autowired
    private ISysConfigService configService;

    /**
     * 短信类型 SmsTypeEnum
     */
    public AjaxResult sendVerifyCode(SmsTypeEnum smsType, String mobileNo) {
        SysSmsLog smsLog = new SysSmsLog();
        smsLog.setType(smsType.getType());
        smsLog.setPhoneNo(mobileNo);
        smsLog.setCreateTime(new Date());
        smsLog.setUpdateTime(new Date());
        if (configService.isSmsVerifyCodeMock()) {
            smsLog.setCode("1234");
            smsLog.setMessage("模拟发送信息！");
            smsLog.setStatus(1);
            smsLogMapper.insertSysSmsLog(smsLog);
            return AjaxResult.success("发送成功");
        }
        if(!checkFrequently(mobileNo)){
            throw new BaseException("短信发送频繁");
        }
        String code = VerifyCodeUtils.captchaNumber(4);
        smsLog.setCode(code);

        Map<String, String> templateParamMap = new HashMap<String, String>();
        templateParamMap.put("code", code);

        String smsSignName = configService.getConfigValueByKey("sys.sms.signName", signName);
        String smsTemplateCode = configService.getConfigValueByKey("sys.sms.templateCode", templateCode);
        String templateParam = JSONObject.toJSONString(templateParamMap);
        SendSmsResponse sendSmsResponse = sendTemplate(mobileNo, smsSignName, smsTemplateCode, templateParam);
        smsLog.setMessage(templateCode + ":" + templateParam + "，短信发送返回信息：" + JSONObject.toJSONString(sendSmsResponse));
        smsLog.setStatus((sendSmsResponse != null && sendSmsResponse.getCode().equals("OK")) ? 1 : 0);
        smsLogMapper.insertSysSmsLog(smsLog);
        if (sendSmsResponse != null && sendSmsResponse.getCode().equals("OK")) {
            return AjaxResult.success("发送成功");
        } else if (sendSmsResponse != null) {
            throw new BaseException(sendSmsResponse.getMessage());
        }
        return AjaxResult.error("发送失败");
    }

    private SendSmsResponse sendTemplate(String mobileNo, String signName, String templateCode, String templateParam) {
        //可自助调整超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", defaultConnectTimeout);
        System.setProperty("sun.net.client.defaultReadTimeout", defaultReadTimeout);
        SendSmsResponse sendSmsResponse = null;
        try{
            //初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);

            //组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            //必填:待发送手机号
            request.setPhoneNumbers(mobileNo);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName(signName);
            //必填:短信模板-可在短信控制台中找到
            request.setTemplateCode(templateCode);
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            request.setTemplateParam(templateParam);
            //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
            //request.setSmsUpExtendCode("90997");
            //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
            //request.setOutId("yourOutId");
            //hint 此处可能会抛出异常，注意catch
            sendSmsResponse = acsClient.getAcsResponse(request);
        }catch(Exception e){
            logger.error("ShortMessageService sendSms",e);        //throw new BusinessException("短信发送异常",StatusCodeConstant.rule_error);
            sendSmsResponse = new SendSmsResponse();
            sendSmsResponse.setCode("FAIL");
            sendSmsResponse.setMessage(e.getMessage());
        }
        return sendSmsResponse;
    }

    /**
     * 验证短信验证码是否有效
     * @param phoneNo
     * @param code
     * @return
     */
    public boolean checkCode(String phoneNo, String code) {
        if (StringUtils.isEmpty(phoneNo) || StringUtils.isEmpty(code)) {
            throw new BaseException("短信验证缺少手机号码或者验证码");
        }
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, -duration);
        SysSmsLog smsLog = new SysSmsLog();
        smsLog.setPhoneNo(phoneNo);
//        smsLog.setStatus(0);
        smsLog.setCreateTime(calendar.getTime());
        List<SysSmsLog> list = smsLogMapper.checkCode(smsLog);
        if (!CollectionUtils.isEmpty(list)) {
            //处理验证码已使用
            SysSmsLog smsLogCheck = list.get(0);
            Boolean isSuccess = code.equals(smsLogCheck.getCode()) ? true : false;
            if (isSuccess) {
                //发送成功时将此条code置为已使用,一条记录仅能使用一次
                smsLogCheck.setIsUsed(1);
                smsLogMapper.updateSysSmsLog(smsLogCheck);
            }
            return isSuccess;
        } else {
            throw new BaseException("验证码已失效，请重新发送！");
        }
    }

    /**
     * 检查短信发送是否频繁 一小时最多5次
     * @param phoneNumber
     * @return
     */
    public boolean checkFrequently(String phoneNumber){
        int count = smsLogMapper.getCountLastHour(phoneNumber);
        if (count >= 5) {
            //手机号加入黑名单
            SysSmsBlacklist insert = new SysSmsBlacklist();
            insert.setPhoneNo(phoneNumber);
            if (!CollectionUtils.isEmpty(smsBlacklistService.selectSysSmsBlacklistList(insert))) {
                return false;
            }
            smsBlacklistService.insertSysSmsBlacklist(insert);
            return false;
        }
        return true;
    }

    /**
     * 是否为黑名单
     * @param phonenumber
     * @return
     */
    public Boolean isBlacklist(String phonenumber){
        SysSmsBlacklist insert = new SysSmsBlacklist();
        insert.setPhoneNo(phonenumber);
        if(!CollectionUtils.isEmpty(smsBlacklistService.selectSysSmsBlacklistList(insert))){
            return true;
        }
        return false;
    }
}
