package com.red.circle.other.app.command.user;

import com.red.circle.external.inner.endpoint.message.SmsClient;
import com.red.circle.external.inner.model.cmd.message.SendSmsCmd;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.PhoneErrorCode;
import com.red.circle.framework.core.response.ResponseErrorCode;
import com.red.circle.framework.web.util.ValidatorUtils;
import com.red.circle.tool.core.phone.PhoneNumberUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.other.app.dto.cmd.user.user.BindUserAuthTypeCmd;
import com.red.circle.other.infra.database.rds.entity.user.user.AuthType;
import com.red.circle.other.infra.database.rds.entity.user.user.MobileAuth;
import com.red.circle.other.infra.database.rds.service.user.user.AuthTypeService;
import com.red.circle.other.infra.database.rds.service.user.user.MobileAuthService;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import com.red.circle.other.inner.model.cmd.user.account.MobileAuthCmd;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 绑定用户认证.
 *
 * @author pengliang on 2021/5/11
 */
@Component
@RequiredArgsConstructor
public class BindUserAuthTypeCmdExe {

  private final SmsClient smsClient;
  private final AuthTypeService authTypeService;
  private final MobileAuthService mobileAuthService;

  public void execute(BindUserAuthTypeCmd cmd) {
    // 请求参数错误
    if (StringUtils.isBlank(cmd.getActualOpenId())) {
      ResponseAssert
          .failure(ResponseErrorCode.REQUEST_PARAMETER_ERROR, "openId is not blank.");
    }

    AuthType authType = authTypeService.getAuthInfo(cmd.getActualOpenId());

    // 已被绑定
    ResponseAssert.isNull(UserErrorCode.ALREADY_USED, authType);
    ResponseAssert.isFalse(UserErrorCode.ALREADY_USED,
        authTypeService.existsAuthType(cmd.requiredReqUserId(), cmd.getType()));

    if (cmd.isTypeMobile()) {
      MobileAuthCmd mobile = cmd.getMobile();
      // 1012 验证码不匹配
      ResponseAssert.isTrue(PhoneErrorCode.VERIFICATION_CODE_NOT_MATCH,
          StringUtils.isNotBlank(mobile.getCode()));

      ResponseAssert.requiredSuccess(smsClient.checkCode(new SendSmsCmd()
              .setPhonePrefix(mobile.getPhonePrefix())
              .setPhoneNumber(mobile.getPhoneNumber())
              .setCode(mobile.getCode())
          )
      );
    }

    if (cmd.isTypeMobile()) {
      mobileCheck(cmd.getMobile());
      MobileAuthCmd mobileAuthCmd = cmd.getMobile();
      mobileAuthService.saveMobileAuth(new MobileAuth()
          .setUserId(cmd.requiredReqUserId())
          .setPhonePrefix(mobileAuthCmd.getPhonePrefix())
          .setPhoneNumber(mobileAuthCmd.getPhoneNumber())
          .setPwd(mobileAuthCmd.getPwd())
          .setDel(Boolean.FALSE)
      );
    }

    authTypeService.save(toAuthType(cmd.requiredReqUserId(), cmd));
  }

  private void mobileCheck(MobileAuthCmd mobileCmd) {
    // 请求参数错误
    if (Objects.isNull(mobileCmd) || !ValidatorUtils.validateFastPass(mobileCmd)) {
      ResponseAssert
          .failure(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
              "mobile is null Or required parameter is empty");
    }

    // 手机号码错误
    ResponseAssert.isTrue(PhoneErrorCode.CELLPHONE_ERROR,
        PhoneNumberUtils.isValidNumber(mobileCmd.getPhonePrefix(),
            Objects.toString(mobileCmd.getPhoneNumber())));
  }

  private AuthType toAuthType(Long userId, BindUserAuthTypeCmd cmd) {
    AuthType authType = new AuthType();
    authType.setUserId(userId);
    authType.setType(cmd.getType().name());
    authType.setOpenId(cmd.getActualOpenId());
    authType.setDel(Boolean.FALSE);
    return authType;
  }

}
