package cn.axzo.msg.center.notices.service.manager;


import cn.axzo.basics.common.constant.ConstStringPool;
import cn.axzo.basics.common.exception.ServiceException;
import cn.axzo.core.constant.RedisNameConstants;
import cn.axzo.msg.center.common.redis.IAxzoJedisManager;
import cn.axzo.msg.center.domain.enums.InsideSmsCodeEnum;
import cn.axzo.msg.center.notices.common.properties.SmsProperties;
import cn.axzo.msg.center.notices.manager.api.dto.request.MnsRequestDto;
import cn.axzo.msg.center.notices.service.api.MessageService;
import cn.axzo.msg.center.notices.service.gateway.SmsGateway;
import cn.axzo.msg.center.notices.service.impl.MnsType;
import cn.axzo.msg.center.notices.service.request.CaptchaParam;
import cn.axzo.msg.center.notices.service.request.SendCodeV2Req;
import cn.axzo.msg.center.notices.service.response.SmsCodeInfoRes;
import cn.azxo.framework.common.utils.LogUtil;
import cn.azxo.framework.common.utils.LogUtil.ErrorLevel;
import cn.azxo.framework.common.utils.LogUtil.ErrorType;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * @author zhangPeng
 * @description
 * @date 2021/1/26 15:15
 */
@Log4j2
@Service
@RefreshScope
public class SmsManager extends BaseManager implements SmsGateway {

  @Resource
  private IAxzoJedisManager iAxzoJedisManager;

  @Resource
  private SmsProperties smsProperties;
  @Resource
  private MessageService messageService;

  @Value("${phone.isSendMnsCode}")
  private boolean isSendMnsCode;

  private static final HashMap<String,String> messageErrMsg = new HashMap<>();
  static {
    messageErrMsg.put("isv.MOBILE_NUMBER_ILLEGAL", "非法手机号");
    messageErrMsg.put("isv.DOMESTIC_NUMBER_NOT_SUPPORTED", "国际/港澳台不支持发送境内号码");
  }

  public static final Integer SUCCESS = 200;

  /**
   * 发送验证码`
   * @param req
   * @return
   */
  public int sendSmsCode(SendCodeV2Req req) {
    sendMnsCode(req.getPhone(), req.getParam(), req.getAppCode(),req.getTemplateNo(), req.getCode(), req.getExpansion());
    log.info("发送验证码 手机号{} -- 参数 {} -- 应用程序code {} -- 模板编号templateCode {}", req.getPhone(), req.getParam(), req.getAppCode(),req.getTemplateNo());
    return req.getCode();
  }

  /**
   * 获取验证码
   *
   * @return
   */
  public Integer getSmsCode(String phoneNumber, String type) {
    Integer code = iAxzoJedisManager.get(RedisNameConstants.SMS_CODE + type + ":" + phoneNumber);
    return code;
  }


  /**
   * 获取验证码过期时间
   *
   * @return
   */
  public Long getSmsCodeSsl(String phoneNumber, String type) {
    Long ssl = iAxzoJedisManager.ssl(RedisNameConstants.SMS_CODE + type + ":" + phoneNumber);
    if (null == ssl || ConstStringPool.PROFILES_EVN.contains(SpringUtil.getActiveProfile())) {
      return 0L;
    }
    return (ssl - (14 * 60L) +30) < 0L ? 0L : ssl - (14 * 60L)+30;
  }

  /**
   * 获取各类验证码
   *
   * @return
   */
  public List<SmsCodeInfoRes> getAllSmsCode(String phoneNumber) {
    List<SmsCodeInfoRes> rets = new ArrayList<>();
    InsideSmsCodeEnum[] smsCodeEnums = InsideSmsCodeEnum.values();
    for (InsideSmsCodeEnum smsCodeEnum : smsCodeEnums) {
      Integer code = iAxzoJedisManager
          .get(RedisNameConstants.SMS_CODE + smsCodeEnum.value + ":" + phoneNumber);
      if (Objects.nonNull(code)) {
        SmsCodeInfoRes smsCodeInfoRes = new SmsCodeInfoRes();
        smsCodeInfoRes.setCode(code);
        smsCodeInfoRes.setType(smsCodeEnum.desc);
        rets.add(smsCodeInfoRes);
      }
    }
    return rets;
  }

  @Deprecated
  public void sendCaptcha(CaptchaParam param) {
    log.info("调用发送验证码：{}", param);
    JSONObject templateParam = new JSONObject();
    templateParam.put("code", param.getCode());
    sendSms(param.getPhones(), smsProperties.getCaptchaTemplate(), templateParam.toJSONString());
  }

  @Deprecated
  public void offlineAutoConfirm(String phoneNumber) {
    JSONObject templateParam = new JSONObject();
    sendSms(phoneNumber, "SMS_216279895", templateParam.toJSONString());
  }

  //发送短信
  @Deprecated
  private void sendSms(String phones, String templateCode, String templateJson) {
    if(phones != ""){
      throw new ServiceException("参数异常");
    }
    DefaultProfile profile = DefaultProfile
        .getProfile(smsProperties.getRegionId(), smsProperties.getAccessKeyId(),
            smsProperties.getAccessSecret());
    IAcsClient client = new DefaultAcsClient(profile);

    CommonRequest request = new CommonRequest();
    request.setSysMethod(MethodType.POST);
    request.setSysDomain("dysmsapi.aliyuncs.com");
    request.setSysVersion("2017-05-25");
    request.setSysAction("SendSms");
    request.putQueryParameter("RegionId", smsProperties.getRegionId());
    request.putQueryParameter("PhoneNumbers", phones);
    request.putQueryParameter("SignName", smsProperties.getSignName());
    request.putQueryParameter("TemplateCode", templateCode);
    request.putQueryParameter("TemplateParam", templateJson);

    String resultJson;
    try {
      CommonResponse response = client.getCommonResponse(request);
      log.info("短信发送结果，httpStatus：{}，data：{}", response.getHttpStatus(), response.getData());
      resultJson = response.getData();
    } catch (Exception e) {
      LogUtil.error(ErrorLevel.P0, ErrorType.ERROR_THIRD_SERVICE,"短信服务异常, phones={}", phones, e);
      throw new ServiceException("短信发送失败");
    }
    // "Code":"OK","Message":"OK","RequestId":"2184201F-BFB3-446B-B1F2-C746B7BF0657","BizId":"197703245997295588^0"
    JSONObject result = JSON.parseObject(resultJson);
    if(!result.getString("Code").equalsIgnoreCase("OK")) {
      log.warn("短信发送失败, phones={}, resultJson={}",phones, resultJson);
      String message = messageErrMsg.get(result.getString("Code"));
      if(message != null && !message.equals("")){
        throw new ServiceException(message);
      }else {
        throw new ServiceException("短信发送失败");
      }
    }
  }

  public void sendMnsCode(String phoneNumber, Map<String, Object> param, String appCode, String templateNo, Integer code, String expansion) {
    if (!isSendMnsCode) {
      return;
    }
    MnsRequestDto request = new MnsRequestDto();
    request.setAppCode(appCode);
    request.setPhoneNo(phoneNumber);
    request.setTemplateNo(templateNo);
    request.setParams(param);
    request.setRequestNo(UUID.randomUUID().toString());
    request.setInternalObj(MnsType.VERIFY_CODE);
    request.setExpansion(expansion);
    messageService.sendMessage(request);
  }
}
