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

import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.enums.OperationUserOrigin;
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateTypeCmd;
import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
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.DbInviteAgentCmd;
import com.red.circle.other.app.dto.cmd.team.DbLeaderInviteBdCmd;
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.RegisterDeviceGateway;
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.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.service.team.BusinessDevelopmentBaseInfoService;
import com.red.circle.other.infra.database.rds.service.user.device.LatestMobileDeviceService;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
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.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.collection.CollectionUtils;
import com.red.circle.tool.core.collection.MapBuilder;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 用户申请加入团队.
 *
 * @author pengshigang on 2022/12/20
 */
@Component
@RequiredArgsConstructor
public class TeamUserApplyJoinExe {

  private final WalletGoldClient walletGoldClient;
  private final UserRegionGateway userRegionGateway;
  private final UserProfileGateway userProfileGateway;
  private final TeamMemberService teamMemberService;
  private final TeamProfileService teamProfileService;
  private final UserProfileAppConvertor userProfileAppConvertor;
  private final LatestMobileDeviceService latestMobileDeviceService;
  private final TeamApplicationProcessService teamApplicationProcessService;
  private final BusinessDevelopmentBaseInfoService businessDevelopmentBaseInfoService;
  private final RegisterDeviceGateway registerDeviceGateway;
  private final EnumConfigCacheService enumConfigCacheService;

  public String execute(TeamUserApplyCmd cmd) {

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

    ResponseAssert
        .isNull(TeamErrorCode.JOINED_TEAM, teamMemberService.getByMemberId(userProfile.getId()));

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

    ResponseAssert.isTrue(TeamErrorCode.THE_TEAM_IS_FULL, teamProfile.checkAllowJoinTeam());

    ResponseAssert.isTrue(TeamErrorCode.TEAM_NOT_FOUND, Objects.equals(teamProfile.getStatus(),
        TeamStatus.AVAILABLE));

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

    ResponseAssert.isFalse(TeamErrorCode.JOINED_TEAM,
        teamMemberService.existsMember(userProfile.getId()));

//    ResponseAssert.isFalse(TeamErrorCode.USER_IS_ALREADY_A_BD,
//        businessDevelopmentBaseInfoService.checkBD(userProfile.getId()));

    // 主播设备指纹校验
    Boolean hasAnchorWithSameDevice = registerDeviceGateway.checkDeviceFingerprintHasAnchor(
        cmd.getReqUserId());
    ResponseAssert.isFalse(TeamErrorCode.DEVICE_FINGERPRINT_USED_BY_ANCHOR, hasAnchorWithSameDevice);


    // ResponseAssert.isTrue(TeamErrorCode.JOIN_RESTRICTIONS, checkJoinLimit(cmd));

    checkApply(cmd, teamProfile);

    Long messageId = IdWorkerUtils.getId();
    teamApplicationProcessService.add(new TeamApplicationProcess()
        .setId(messageId)
        .setSysOrigin(teamProfile.getSysOrigin())
        .setType(TeamApplicationType.TEAM)
        .setReason(TeamAppProcessReason.JOIN)
        .setAssociateId(teamProfile.getId())
        .setStatus(TeamApplicationProcessStatus.WAIT)
        .setCreateTime(TimestampUtils.now())
        .setCreateUser(cmd.getReqUserId())
        .setCreateUserOrigin(OperationUserOrigin.APP.getValue())
        .setExpiredTime(TimestampUtils.nowPlusDays(60))
    );

    sendMessage(cmd, teamProfile);

    return Objects.toString(messageId);
  }

  private void checkApply(TeamUserApplyCmd cmd, TeamProfile teamProfile) {

    // 申请人与团队区域不一致或者申请人金币多余100则不允许申请
    if (Boolean.TRUE.equals(Objects.equals(userRegionGateway.getRegionId(cmd.getReqUserId()), teamProfile.getRegion()))) {
      return;
    }

    if (ResponseAssert.requiredSuccess(walletGoldClient.getBalance(cmd.getReqUserId()))
        .getDollarAmount().longValue() < 100) {
      return;
    }

    ResponseAssert.failure(TeamErrorCode.NOT_AUTHORIZED_TO_JOIN);
  }

  /**
   * 加入限制： 20230401, 刘占洋需求（同一个设备的账户只能加入同一个代理）
   */
  private boolean checkJoinLimit(TeamUserApplyCmd cmd) {

    String imei = latestMobileDeviceService.getImeiByUserId(cmd.getReqUserId());

    ResponseAssert.isTrue(CommonErrorCode.DEVICE_UNAVAILABLE, StringUtils.isNotBlank(imei));

    List<Long> userIds = latestMobileDeviceService.listUserIdByImei(
        cmd.getReqImei(), cmd.requireReqSysOrigin());

    if (CollectionUtils.isEmpty(userIds)) {
      return true;
    }

    Set<Long> otherUserIds = userIds.stream()
        .filter(userId -> !Objects.equals(cmd.getReqUserId(), userId)).collect(
            Collectors.toSet());

    if (CollectionUtils.isEmpty(otherUserIds)) {
      return true;
    }

    List<Long> teamIds = teamMemberService.listTeamIdByMemberIds(otherUserIds);
    if (CollectionUtils.isEmpty(teamIds)) {
      return true;
    }
    return teamIds.contains(cmd.getTeamId());
  }

  private void sendMessage(TeamUserApplyCmd cmd, TeamProfile teamProfile) {
    UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
            userProfileGateway.getByUserId(cmd.requiredReqUserId())
    );
    ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfile);
    String h5Url = enumConfigCacheService.getValue(EnumConfigKey.H5_DOMAIN_BASE_URL_V2,
            cmd.requireReqSysOrigin());

    if (StringUtils.isBlank(h5Url)) {
      return;
    }
    String path = null;
    if (Objects.equals(cmd.requireReqSysOriginEnum(), SysOriginPlatformEnum.TARAB)) {
      path = "/team-tarab";
    }
    if (Objects.equals(cmd.requireReqSysOriginEnum(), SysOriginPlatformEnum.YOLO)) {
      cmd.setUrl("/anchor_agent_yolo");
      if (StringUtils.isNotBlank(cmd.getUrl())){
        path = cmd.getUrl();
      }
    }
    if (StringUtils.isBlank(path)) {
      return;
    }
    /*officialNoticeClient.send(NoticeExtTemplateTypeCmd.builder()
            .toAccount(teamProfile.getOwnUserId())
            .noticeType(OfficialNoticeTypeEnum.USER_SEND_APPLY_TEAM)
            .templateParam(MapBuilder.builder()
                    .put("userProfile", String.format("%s(%s)", userProfile.getUserNickname(),
                            userProfile.actualAccount()))
                    .build())
            .expand(h5Url + path)
            .build()
    );*/
  }

}
