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

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.framework.core.response.ResponseErrorCode;
import com.red.circle.mq.business.model.event.BadgeOperateEvent;
import com.red.circle.mq.business.model.event.task.TaskApprovalEvent;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.mq.rocket.business.producer.UserMqMessageService;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.cmd.team.DbInviteMessageProcessCmd;
import com.red.circle.other.app.util.OfficialNoticeUtils;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.gateway.user.ability.RegisterDeviceGateway;
import com.red.circle.other.infra.database.mongo.entity.team.bd.BdInviteAgentMessage;
import com.red.circle.other.infra.database.mongo.entity.team.bd.MessageInviteGroup;
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.bd.BdInviteAgentMessageService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamBillCycleService;
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.BusinessDevelopmentBaseInfo;
import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentTeam;
import com.red.circle.other.infra.database.rds.service.sys.AdministratorService;
import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentBaseInfoService;
import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentTeamService;
import com.red.circle.other.infra.database.rds.service.team.UserHistoryIdentityService;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import com.red.circle.other.inner.enums.material.BadgeKeyEnum;
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.cmd.team.TeamBillCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamContact;
import com.red.circle.other.inner.model.dto.agency.agency.TeamCounter;
import com.red.circle.other.inner.model.dto.agency.agency.TeamCountry;
import com.red.circle.other.inner.model.dto.agency.agency.TeamSetting;
import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.collection.MapBuilder;
import com.red.circle.tool.core.date.LocalDateTimeUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 处理bd邀请消息.
 *
 * @author pengliang on 2022/10/11
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class BdInviteMessageProcessExe {

  private final TeamMemberService teamMemberService;
  private final UserProfileGateway userProfileGateway;
  private final TeamProfileService teamProfileService;
  private final RegisterDeviceGateway registerDeviceGateway;
  private final TeamBillCycleService teamBillCycleService;
  private final UserProfileAppConvertor userProfileAppConvertor;
  private final UserHistoryIdentityService userHistoryIdentityService;
  private final BdInviteAgentMessageService bdInviteAgentMessageService;
  private final BusinessDevelopmentTeamService businessDevelopmentTeamService;
  private final BusinessDevelopmentBaseInfoService businessDevelopmentBaseInfoService;
  private final UserMqMessageService userMqMessageService;
  private final AdministratorService administratorService;
  private final TaskMqMessage taskMqMessage;

  public void execute(DbInviteMessageProcessCmd cmd) {

    ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, cmd.getStatus() > 0);

    BdInviteAgentMessage message = bdInviteAgentMessageService.getById(cmd.getId());
    ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE, message.getStatus() == 0);
    ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, message);

    ResponseAssert.isTrue(CommonErrorCode.NOT_FOUND_RECORD_INFO,
        Objects.equals(message.getGroup(), MessageInviteGroup.BD_INVITE_TEAM.name()) ||
            StringUtils.isBlank(message.getGroup()));

    ResponseAssert.isFalse(TeamErrorCode.USER_IS_ALREADY_A_ANCHOR,
        teamMemberService.existsMember(cmd.requiredReqUserId()));

    ResponseAssert.isTrue(CommonErrorCode.INSUFFICIENT_PERMISSION,
        Objects.equals(message.getInviteUserId(), cmd.requiredReqUserId()));
    ResponseAssert.isTrue(TeamErrorCode.MESSAGE_PROCESSED, Objects.equals(message.getStatus(), 0));
    // 6014 用户正在申请加入其他代理
    ResponseAssert.isFalse(TeamErrorCode.USER_APPLY_JOIN_OTHER_AGENT,
        teamMemberService.existsMember(cmd.requiredReqUserId()));
    ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE,
        bdInviteAgentMessageService.updateStatus(cmd.getId(), message.getStatus(),
            cmd.getStatus(), MessageInviteGroup.BD_INVITE_TEAM.name()));

    if (Objects.equals(cmd.getStatus(), 1)) {
      Long teamId = createTeam(cmd, message);

      // 主播设备指纹校验
      Boolean hasAnchorWithSameDevice = registerDeviceGateway.checkDeviceFingerprintHasAnchor(
          message.getInviteUserId());
      ResponseAssert.isFalse(TeamErrorCode.DEVICE_FINGERPRINT_USED_BY_AGENCY, hasAnchorWithSameDevice);

      businessDevelopmentTeamService.save(new BusinessDevelopmentTeam()
          .setSysOrigin(message.getSysOrigin())
          .setAgentId(message.getInviteUserId())
          .setUserId(message.getUserId())
          .setTeamId(teamId)
      );

      businessDevelopmentBaseInfoService.incrMemberCount(Set.of(message.getUserId()));

      // 发送管理员任务消息
      sendAdminTaskMessage(message.getUserId());

      userMqMessageService.sendBadgeOperateEvent(message.getInviteUserId(), BadgeKeyEnum.AGENCY.name(), BadgeOperateEvent.OperationType.WEAR.name());
      userMqMessageService.sendBadgeOperateEvent(message.getInviteUserId(), BadgeKeyEnum.HOST.name(), BadgeOperateEvent.OperationType.WEAR.name());

      sendMessage(message, OfficialNoticeTypeEnum.AGREE_BD_INVITE_AGENT);
      return;
    }

    sendMessage(message, OfficialNoticeTypeEnum.REFUSE_BD_INVITE_AGENT);
  }

    private void sendAdminTaskMessage(Long userId) {
        boolean admin = administratorService.existsAdmin(userId);
        if (admin) {
            taskMqMessage.sendTask(TaskApprovalEvent.builder()
                    .taskId(15)
                    .userId(userId)
                    .day(LocalDateTimeUtils.nowFormat("yyyy-MM-dd"))
                    .build());
        }
    }


  private Long createTeam(DbInviteMessageProcessCmd cmd, BdInviteAgentMessage message) {
    BusinessDevelopmentBaseInfo bdBaseInfo = businessDevelopmentBaseInfoService.getByUserId(
        message.getUserId());
    ResponseAssert.notNull(TeamErrorCode.USER_IS_NOT_BD, bdBaseInfo);

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

    UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
        userProfileGateway.getByUserId(message.getInviteUserId()));
    TeamProfile teamProfile = new TeamProfile()
        .setId(IdWorkerUtils.getId())
        .setRegion(bdBaseInfo.getRegion())
        .setSysOrigin(cmd.requireReqSysOrigin())
        .setOwnUserId(userProfile.getId())
        .setRemarks(CollectionUtils.newArrayList())
        .setStatus(TeamStatus.AVAILABLE)
        .setSetting(new TeamSetting()
            .setMaxMember(1000)
        )
        .setCountry(new TeamCountry()
            .setCountryId(userProfile.getCountryId())
            .setCountryCode(userProfile.getCountryCode())
            .setCountryName(userProfile.getCountryName())
        )
        .setCounter(new TeamCounter()
            .setMemberQuantity(1L)
            .setAdminQuantity(0L)
        )
        .setContacts(
            StringUtils.isNotBlank(cmd.getContact())
                ? List.of(
                new TeamContact()
                    .setContactId(IdWorkerUtils.getIdStr())
                    .setType("OTHER")
                    .setContact(cmd.getContact())
                    .setRemarks("")
                    .setCreateBackUser(0L)
                    .setCreateTime(TimestampUtils.now())
            ) : CollectionUtils.newArrayList()
        )
        .setCreateTime(TimestampUtils.now())
        .setUpdateTime(TimestampUtils.now())
        .setCreateUser(cmd.requiredReqUserId())
        .setCreateUserOrigin(OperationUserOrigin.APP.getValue())
        .setUpdateUser(cmd.requiredReqUserId())
        .setUpdateUserOrigin(OperationUserOrigin.APP.getValue());
    teamProfileService.create(teamProfile);

    // 初始化账单
    teamBillCycleService.createIfAbsent(
        new TeamBillCmd()
            .setSysOrigin(teamProfile.getSysOrigin())
            .setTeamId(teamProfile.getId())
            .setRegion(teamProfile.getRegion())
            .setOperationTime(TimestampUtils.now())
            .setOperationBackUser(teamProfile.getCreateUser())
    );

    teamMemberService.addMember(new TeamMember()
        .setSortId(IdWorkerUtils.getId())
        .setSysOrigin(teamProfile.getSysOrigin())
        .setMemberId(userProfile.getId())
        .setTeamId(teamProfile.getId())
        .setRole(TeamMemberRole.OWN)
        .setRemarks("")
        .setCreateTime(TimestampUtils.now())
        .setCreateUserOrigin(1)
        .setUpdateTime(TimestampUtils.now())
        .setUpdateUserOrigin(1)
        .setActiveTime(TimestampUtils.now())
    );

    userHistoryIdentityService.saveHost(userProfile.getId());

    return teamProfile.getId();
  }

  private void sendMessage(BdInviteAgentMessage message, OfficialNoticeTypeEnum noticeTypeEnum) {
    UserProfileDTO userProfile = userProfileAppConvertor.toUserProfileDTO(
        userProfileGateway.getByUserId(message.getInviteUserId()));
    ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfile);
    /*officialNoticeClient.send(
        NoticeExtTemplateTypeCmd.builder()
            .toAccount(message.getUserId())
            .templateParam(OfficialNoticeUtils.buildUserProfile(userProfile))
            .noticeType(noticeTypeEnum)
            .build()
    );*/
  }

}
