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

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.family.ApplyJoinFamilyCmd;
import com.red.circle.other.infra.common.family.FamilyCommon;
import com.red.circle.other.infra.database.rds.entity.family.FamilyMessage;
import com.red.circle.other.infra.database.rds.service.family.FamilyMemberInfoService;
import com.red.circle.other.infra.database.rds.service.family.FamilyMessageService;
import com.red.circle.other.infra.enums.family.FamilyMsgTypeEnum;
import com.red.circle.other.inner.asserts.DynamicErrorCode;
import com.red.circle.other.inner.asserts.FamilyErrorCode;
import com.red.circle.other.inner.model.dto.famliy.FamilyDetailsDTO;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 申请加入家族.
 * </p>
 *
 * @author pengshigang
 * @since 2021-07-26
 */
@Component
@RequiredArgsConstructor
public class ApplyJoinFamilyExe {

  private final RedisService redisService;
  private final FamilyCommon familyCommon;
  private final FamilyMessageService familyMessageService;
  private final FamilyMemberInfoService familyMemberInfoService;


  public void execute(ApplyJoinFamilyCmd cmd) {

    ResponseAssert.isFalse(FamilyErrorCode.THERE_ARE_FAMILIES_ERROR, getExistFamilyByUserId(cmd));

    ResponseAssert.isTrue(FamilyErrorCode.NOT_EXIST_FAMILY_INFO_DATA, isExistFamilyById(cmd));

    ResponseAssert.isFalse(FamilyErrorCode.REPEAT_APPLICATION, getExistApplyingMsg(cmd));

    FamilyDetailsDTO levelCacheCO = getFamilyLevel(cmd);

    Integer familyMemberCount = getFamilyMemberCount(levelCacheCO);

    ResponseAssert
        .isTrue(FamilyErrorCode.FAMILY_MEMBER_MAX, levelCacheCO.getMaxMember() > familyMemberCount);

    // 防止重复触发
    ResponseAssert.isTrue(DynamicErrorCode.REPEATED_SUBMIT, redisService.setIfAbsent(
        "APPLY_JOIN_FAMILY_:" + cmd.getReqUserId() + ":" + cmd.getFamilyId(), 40,
        TimeUnit.SECONDS));

    saveMsg(cmd);

  }

  private void saveMsg(ApplyJoinFamilyCmd cmd) {
    familyMessageService.save(new FamilyMessage()
        .setFamilyId(cmd.getFamilyId())
        .setSenderUser(cmd.getReqUserId())
        .setSysOrigin(cmd.getReqSysOrigin().getOrigin())
        .setStatus(Boolean.FALSE)
        .setContent(FamilyMsgTypeEnum.JOIN_FAMILY.getDescription())
        .setType(FamilyMsgTypeEnum.JOIN_FAMILY.name())
    );
  }

  private Integer getFamilyMemberCount(FamilyDetailsDTO levelCacheCO) {
    return familyMemberInfoService.getFamilyMemberCount(levelCacheCO.getFamilyId());
  }

  private FamilyDetailsDTO getFamilyLevel(ApplyJoinFamilyCmd cmd) {
    return familyCommon.getFamilyDetails(cmd.getReqSysOrigin().getOrigin(), cmd.getFamilyId());
  }

  private Boolean getExistApplyingMsg(ApplyJoinFamilyCmd cmd) {
    ResponseAssert.notNull(CommonErrorCode.DATA_ERROR, cmd.getFamilyId());
    ResponseAssert.notNull(CommonErrorCode.DATA_ERROR, cmd.getReqUserId());
    return familyMessageService.isExistApplyingMsg(cmd.getFamilyId(), cmd.getReqUserId());
  }

  private Boolean getExistFamilyByUserId(ApplyJoinFamilyCmd cmd) {
    return familyCommon.isExistFamilyByUserId(cmd.getReqUserId());
  }

  private Boolean isExistFamilyById(ApplyJoinFamilyCmd cmd) {
    return familyCommon.isExistFamilyById(cmd.getFamilyId());
  }

}
