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

import com.alibaba.cloud.commons.lang.StringUtils;
import com.red.circle.common.business.enums.OperationUserOrigin;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.cmd.team.TeamUserApplyCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamApplicationProcess;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamApplicationProcessService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.infra.database.rds.entity.team.TeamTerminationFeeRecord;
import com.red.circle.other.infra.database.rds.service.team.TeamTerminationFeeRecordService;
import com.red.circle.other.inner.asserts.user.UserRelationErrorCode;
import com.red.circle.other.inner.enums.config.EnumConfigKey;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.other.inner.model.dto.user.reigon.HostApplyQuitTeamCheckDTO;
import com.red.circle.other.inner.asserts.team.TeamErrorCode;
import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus;
import com.red.circle.other.inner.enums.team.TeamAppProcessReason;
import com.red.circle.other.inner.enums.team.TeamApplicationProcessStatus;
import com.red.circle.other.inner.enums.team.TeamApplicationType;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.error.WalletErrorCode;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 用户申请退出团队.
 *
 * @author pengshigang on 2022/12/20
 */
@Component
@RequiredArgsConstructor
public class TeamUserApplyQuitExe {

  private final WalletGoldClient walletGoldClient;
  private final UserRegionGateway userRegionGateway;
  private final TeamMemberService teamMemberService;
  private final UserProfileGateway userProfileGateway;
  private final TeamHandleUserApplyExe teamHandleUserApplyExe;
  private final TeamProfileService teamProfileService;
  private final UserProfileAppConvertor userProfileAppConvertor;
  private final TeamApplicationProcessService teamApplicationProcessService;
  private final TeamTerminationFeeRecordService teamTerminationFeeRecordService;
  private final EnumConfigCacheService enumConfigCacheService;

  public String execute(TeamUserApplyCmd cmd) {

      // 校验日期和白名单
      checkWhiteAndDate(cmd);

    UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
        userProfileGateway.getByUserId(cmd.getReqUserId()));
    ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, userProfile);

    TeamProfile teamProfile = teamProfileService.getById(cmd.getTeamId());
    ResponseAssert.notNull(TeamErrorCode.TEAM_NOT_FOUND, teamProfile);

    TeamMember teamMember = teamMemberService.getByMemberId(userProfile.getId());
    ResponseAssert.notNull(TeamErrorCode.TEAM_NOT_FOUND, teamMember);
    ResponseAssert.isTrue(TeamErrorCode.TEAM_NOT_FOUND,
        Objects.equals(teamMember.getTeamId(), teamProfile.getId()));

    ResponseAssert.isFalse(UserRelationErrorCode.EXIST_OR_REPEAT_APPLY_ERROR,
        teamApplicationProcessService.existWaitByUserId(userProfile.getId()));

    Long messageId = IdWorkerUtils.getId();

    checkAndPaymentTerminationFee(cmd, messageId);

    teamApplicationProcessService.add(new TeamApplicationProcess()
        .setId(messageId)
        .setSysOrigin(teamProfile.getSysOrigin())
        .setType(TeamApplicationType.TEAM)
        .setReason(TeamAppProcessReason.QUIT)
        .setAssociateId(teamProfile.getId())
//        .setStatus(Objects.equals(teamProfile.getStatus(), TeamStatus.CLOSE)
//            ? TeamApplicationProcessStatus.AGREE : TeamApplicationProcessStatus.WAIT)
        .setStatus(TeamApplicationProcessStatus.AGREE)
        .setCreateTime(TimestampUtils.now())
        .setCreateUser(cmd.getReqUserId())
        .setCreateUserOrigin(OperationUserOrigin.APP.getValue())
        .setExpiredTime(TimestampUtils.nowPlusDays(60))
    );
    teamHandleUserApplyExe.deleteHost(teamApplicationProcessService.getById(messageId), teamMember, teamProfile.getSysOrigin(), cmd.getReqUserId());
    return Objects.toString(messageId);
  }

    private void checkWhiteAndDate(TeamUserApplyCmd cmd) {
        String value = enumConfigCacheService.getValue(EnumConfigKey.QUIT_TEAM_WHITELIST, cmd.requireReqSysOrigin());
        if (StringUtils.isNotBlank(value)) {
            String[] split = value.split(",");
            boolean contains = Arrays.stream(split).toList().contains(String.valueOf(cmd.getReqUserId()));
            if (contains) {
                return;
            }
        }

        // 校验退出日期：只有每月1号和16号可以退出
        LocalDate now = ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
        int dayOfMonth = now.getDayOfMonth();
        ResponseAssert.isTrue(TeamErrorCode.QUIT_DATE_INVALID, dayOfMonth == 1 || dayOfMonth == 16);
    }

  private void checkAndPaymentTerminationFee(TeamUserApplyCmd cmd, Long messageId) {

    HostApplyQuitTeamCheckDTO hostApplyQuitTeamCheckDTO = userRegionGateway.getHostApplyQuitTeamCheckByUserId(
        cmd.getReqUserId());
    if (Objects.isNull(hostApplyQuitTeamCheckDTO) || Boolean.FALSE.equals(
        hostApplyQuitTeamCheckDTO.getAllowQuit())) {
      return;
    }

    Long terminationFee = hostApplyQuitTeamCheckDTO.getQuitAmount();
    if (terminationFee <= 0) {
      return;
    }

    ResponseAssert.isTrue(WalletErrorCode.INSUFFICIENT_BALANCE,
        ResponseAssert.requiredSuccess(
            walletGoldClient.getBalance(cmd.requiredReqUserId())
        ).getDollarAmount().longValue() >= terminationFee);

    WalletReceiptResDTO walletReceiptRes = ResponseAssert.requiredSuccess(
        walletGoldClient.changeBalance(
            GoldReceiptCmd.builder()
                .appExpenditure()
                .userId(cmd.getReqUserId())
                .sysOrigin(cmd.requireReqSysOrigin())
                .eventId(Objects.toString(messageId))
                .amount(BigDecimal.valueOf(terminationFee))
                .origin(GoldOrigin.HOST_TERMINATION_FEE)
                .originDescribe(GoldOrigin.HOST_TERMINATION_FEE.getDesc())
                .remark("")
                .closeDelayAsset()
                .opUserId(cmd.getReqUserId())
                .build()));

    ResponseAssert.notNull(WalletErrorCode.DEDUCTION_FAILED, walletReceiptRes);

    TeamTerminationFeeRecord terminationFeeRecord = new TeamTerminationFeeRecord();
    terminationFeeRecord.setId(messageId);
    terminationFeeRecord.setSysOrigin(cmd.requireReqSysOrigin());
    terminationFeeRecord.setTerminationFee(BigDecimal.valueOf(terminationFee));
    terminationFeeRecord.setHostUserId(cmd.getReqUserId());
    terminationFeeRecord.setHostRunningWaterId(walletReceiptRes.getAssetRecordId());
    terminationFeeRecord.setCreateTime(TimestampUtils.now());
    terminationFeeRecord.setCreateUser(cmd.getReqUserId());
    teamTerminationFeeRecordService.save(terminationFeeRecord);

  }


}
