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

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.FamilyRemoveUserCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.common.family.FamilyCommon;
import com.red.circle.other.infra.common.family.FamilyNewsRecorder;
import com.red.circle.other.infra.database.rds.entity.family.FamilyMemberInfo;
import com.red.circle.other.infra.database.rds.service.family.FamilyMemberInfoService;
import com.red.circle.other.infra.enums.family.FamilyNewsTypeEnum;
import java.util.Objects;
import java.util.Optional;

import com.red.circle.other.inner.asserts.FamilyErrorCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 移除家族用户.
 * </p>
 *
 * @author pengshigang
 * @since 2021-07-21
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class FamilyRemoveUserExe {

  private final FamilyCommon familyCommon;
  private final FamilyNewsRecorder familyNewsRecorder;
  private final UserProfileGateway userProfileGateway;
  private final FamilyMemberInfoService familyMemberInfoService;

  public void execute(FamilyRemoveUserCmd cmd) {

    FamilyMemberInfo member = getRemovedPersonMember(cmd);
    ResponseAssert.notNull(FamilyErrorCode.USER_NOT_FOUND, member);

    Boolean isExistFamily = getExistFamilyByUserId(cmd);
    ResponseAssert.isTrue(FamilyErrorCode.USER_NOT_FOUND, isExistFamily);

    FamilyMemberInfo manageMember = getOperatorMember(cmd);
    ResponseAssert.notNull(FamilyErrorCode.USER_NOT_FOUND, manageMember);

    ResponseAssert.isFalse(CommonErrorCode.INSUFFICIENT_PERMISSION,
            Objects.equals(member.getMemberUserId(), manageMember.getMemberUserId()));

    if (isAdmin(manageMember)) {
      removeUserAndRecordNews(member, manageMember, cmd, FamilyNewsTypeEnum.MEMBER_KICKED_ADMIN);
      return;
    }

    if (isAllowUpdate(manageMember, member)) {
      removeUserAndRecordNews(member, manageMember, cmd, FamilyNewsTypeEnum.MEMBER_KICKED_MANAGE);
      return;
    }

    ResponseAssert.failure(CommonErrorCode.INSUFFICIENT_PERMISSION);

  }

  private void removeUserAndRecordNews(FamilyMemberInfo member, FamilyMemberInfo operator, FamilyRemoveUserCmd cmd,
                                       FamilyNewsTypeEnum newsType) {
    UserProfile userProfile = userProfileGateway.getByUserId(member.getMemberUserId());
    String targetNickname = Optional.ofNullable(userProfile).map(UserProfile::getUserNickname).orElse(null);

    familyCommon.removeFamilyUser(member);

    familyNewsRecorder.recordAndUpdateNotice(
        cmd.getReqSysOrigin().getOrigin(),
        operator.getFamilyId(),
            newsType,
        operator.getMemberUserId(),
        null,
        member.getMemberUserId(),
        targetNickname
    );
  }

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

  private boolean isAdmin(FamilyMemberInfo manageMember) {
    return familyCommon.isAdmin(manageMember.getMemberRole());
  }

  private boolean isAllowUpdate(FamilyMemberInfo manageMember, FamilyMemberInfo member) {
    return familyCommon.isManage(manageMember.getMemberRole()) && familyCommon
        .isMember(member.getMemberRole());
  }


  private FamilyMemberInfo getRemovedPersonMember(FamilyRemoveUserCmd cmd) {
    return familyMemberInfoService
        .geMemberByMemberId(cmd.getRemoveMemberId());
  }

  private FamilyMemberInfo getOperatorMember(FamilyRemoveUserCmd cmd) {
    return familyMemberInfoService.getFamilyMemberByUserId(cmd.getReqUserId());
  }


}
