package com.red.circle.external.infra.common;

import com.red.circle.component.redis.service.RedisService;
import com.red.circle.component.sms.SmsChannelEnum;
import com.red.circle.component.sms.SmsChannelTemplate;
import com.red.circle.component.sms.SmsService;
import com.red.circle.component.sms.aliyun.AliYunSmsTemplateEnum;
import com.red.circle.external.infra.database.redis.key.SmsKeys;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.PhoneErrorCode;
import com.red.circle.framework.web.props.EnvProperties;
import com.red.circle.tool.core.num.NumUtils;
import com.red.circle.tool.core.phone.PhoneNumberUtils;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 手机相关服务.
 *
 * @author pengliang on 2021/3/25
 */
@Component
@RequiredArgsConstructor
public class PhoneSms {

  private final SmsService smsService;
  private final RedisService redisService;
  private final EnvProperties envProperties;

  /**
   * 发送验证码.
   */
  public void sendCode(Integer phonePrefix, String phoneNumber) {

    // 手机号码错误
    ResponseAssert.isTrue(PhoneErrorCode.CELLPHONE_ERROR,
        PhoneNumberUtils.isValidNumber(phonePrefix, phoneNumber));

    String code = NumUtils.getRandomNumberString(4);

    // 重复发送验证码
    ResponseAssert.isTrue(PhoneErrorCode.REPEATED_SENDING_CODE,
        redisService
            .setIfAbsent(smsCodeKey(phonePrefix, phoneNumber),
                code, 1, TimeUnit.MINUTES));

    smsService.send(SmsChannelTemplate.builder()
            .channel(SmsChannelEnum.AliYun)
            .template(AliYunSmsTemplateEnum.VERIFICATION_CODE)
            .build()
            .putTemplateParam("code", code),
        phonePrefix,
        phoneNumber);
  }

  /**
   * 检查验证码.
   *
   * @return true 通过，false 不通过
   */
  public boolean checkCode(Integer phonePrefix, String phoneNumber, String code) {
    if (!envProperties.isProd()) {
      return Boolean.TRUE;
    }

    return PhoneNumberUtils
        .isValidNumber(phonePrefix, phoneNumber)
        && redisService.equals(smsCodeKey(phonePrefix, phoneNumber), code);
  }

  private String smsCodeKey(Integer phonePrefix, String phoneNumber) {
    return SmsKeys.CODE.getKey(phonePrefix, phoneNumber);
  }

}
