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


import com.red.circle.component.redis.service.RedisService;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.dto.cmd.user.user.AccountBindUserAuthTypeCmd;
import com.red.circle.other.infra.database.rds.entity.user.user.AccountAuth;
import com.red.circle.other.infra.database.rds.entity.user.user.AuthType;
import com.red.circle.other.infra.database.rds.entity.user.user.PasswordLog;
import com.red.circle.other.infra.database.rds.service.user.user.AccountAuthService;
import com.red.circle.other.infra.database.rds.service.user.user.AuthTypeService;
import com.red.circle.other.infra.database.rds.service.user.user.PasswordLogService;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import com.red.circle.other.inner.enums.user.AuthTypeEnum;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.red.circle.tool.core.collection.CollectionUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

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

  private final AuthTypeService authTypeService;
  private final AccountAuthService accountAuthService;
  private final PasswordLogService passwordLogService;

  public void execute(AccountBindUserAuthTypeCmd cmd) {
    AuthType authType = authTypeService.getAuthInfo(
        AuthTypeEnum.ACCOUNT.name(),
        cmd.requiredReqUserIdStr()
    );

    // 4032 已被绑定
    ResponseAssert.isNull(UserErrorCode.ALREADY_USED, authType);

    AccountAuth accountAuth = accountAuthService.getByUserId(cmd.requiredReqUserId());

    ResponseAssert.isNull(UserErrorCode.ALREADY_USED, accountAuth);
    //4061 密码不符合规则
    ResponseAssert.isTrue(UserErrorCode.ACCOUNT_PASSWORD_NOT_COMPLY_WITH_RULES,
        validatePassword(cmd.getPwd()));

    accountAuthService.saveAccountAuth(new AccountAuth()
        .setUserId(cmd.requiredReqUserId())
        .setPwd(cmd.getPwd())
        .setDel(Boolean.FALSE)
    );

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

  public void accountUpdate(AccountBindUserAuthTypeCmd cmd) {
    //4061 密码不符合规则
    ResponseAssert.isTrue(UserErrorCode.ACCOUNT_PASSWORD_NOT_COMPLY_WITH_RULES, validatePassword(cmd.getPwd()));

    AccountAuth accountAuth = accountAuthService.getByPassword(cmd.getOldPwd(), cmd.getReqUserId());
    ResponseAssert.notNull(UserErrorCode.PASSWORD_NOT_MATCH, accountAuth);

    ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE, accountAuthService.deleteById(accountAuth.getId()));
    authTypeService.deleteAuthType(cmd.getReqUserId(), AuthTypeEnum.ACCOUNT.name());

    accountAuthService.saveAccountAuth(new AccountAuth()
      .setUserId(cmd.requiredReqUserId())
      .setPwd(cmd.getPwd())
      .setDel(Boolean.FALSE));

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

    passwordLogService.save(PasswordLog.builder()
        .businessType("ACCOUNT_PASSWORD")
        .operateType("UPDATE_PASSWORD")
        .userId(cmd.getReqUserId())
        .sysOrigin(cmd.requireReqSysOrigin())
        .pwd(cmd.getPwd())
        .imei(cmd.getReqImei())
        .build());
  }


  private AuthType toAuthType(Long userId, AccountBindUserAuthTypeCmd cmd) {
    AuthType authType = new AuthType();
    authType.setUserId(userId);
    authType.setType(AuthTypeEnum.ACCOUNT.name());
    authType.setOpenId(cmd.requiredReqUserIdStr());
    authType.setDel(Boolean.FALSE);
    return authType;
  }

  private boolean validatePassword(String password) {
    // 使用正则表达式检查密码是否符合要求
    // 密码必须包含至少字母（大小写）、数字
    String regex = "^(?=.*[a-zA-Z])(?=.*\\d).{8,16}$";

    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(password);

    return matcher.matches();
  }

}
