package com.red.circle.other.app.service.user.user;

import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.red.circle.auth.inner.endpoint.AuthClient;
import com.red.circle.common.business.core.constant.SecurityConstant;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.enums.AccountStatusEnum;
import com.red.circle.common.business.enums.ConsoleAccountStatusEnum;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.external.inner.endpoint.message.ImAccountClient;
import com.red.circle.external.inner.endpoint.message.NewsletterClient;
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
import com.red.circle.external.inner.endpoint.message.TrtcClient;
import com.red.circle.external.inner.model.cmd.message.NewsletterResultCmd;
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateCustomizeCmd;
import com.red.circle.external.inner.model.enums.message.NewsletterEvent;
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.infra.database.mongo.service.user.profile.UserRunProfileService;
import com.red.circle.other.inner.endpoint.live.RoomManagerClient;
import com.red.circle.other.inner.endpoint.user.device.RegisterDeviceClient;
import com.red.circle.other.inner.endpoint.user.user.AppUserAccountClient;
import com.red.circle.other.inner.endpoint.user.user.UserOnlineClient;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import com.red.circle.other.inner.model.cmd.user.ApprovalAccountCmd;
import com.red.circle.other.inner.model.cmd.user.ApprovalUserAccountStatusLogCmd;
import com.red.circle.other.inner.model.dto.live.RoomProfileDTO;
import com.red.circle.other.inner.model.dto.user.UserLatestMobileDeviceHistoryDTO;
import com.red.circle.other.inner.model.dto.user.device.ArchiveDeviceDTO;
import com.red.circle.tool.core.date.TimestampUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * 用户数据 服务实现.
 *
 * @author pengliang on 2022/7/21
 */
@Service
@RequiredArgsConstructor
public class AppUserDataViolationServiceImpl implements AppUserDataViolationService {

  private final TrtcClient trtcClient;
  private final RedisService redisService;
  private final ImAccountClient imAccountClient;
  private final UserOnlineClient userOnlineClient;
  private final NewsletterClient newsletterClient;
  private final UserProfileClient userProfileClient;
  private final RoomManagerClient roomManagerClient;
  private final RegisterDeviceClient registerDeviceClient;
  private final AuthClient authClient;
  private final AppUserAccountClient appUserAccountClient;

  @Override
  public void updateAccountStatus(ApprovalAccountCmd param) {
    param.setApprovalUserId(param.getReqUserId());
    processUpdateAccountStatus(param);
  }

  /*public void processUpdateUserRunProfileStatus(ApprovalAccountCmd param) {
    userRunProfileService.updateEntityById(param.getBeApprovalUserId(), param.getAccountStatusEnum().getName());
  }*/

  public void processUpdateAccountStatus(ApprovalAccountCmd param) {

    // 警告
    if (ConsoleAccountStatusEnum.WARNING.eq(param.getAccountStatusEnum())) {

      /*officialNoticeClient.send(
          NoticeExtTemplateCustomizeCmd.builder().toAccount(param.getBeApprovalUserId())
              .noticeType(OfficialNoticeTypeEnum.USER_WARNING)
              .content(param.getDescriptionContent())
              .expand(null)
              .build());*/
    }
    // 冻结
    else if (ConsoleAccountStatusEnum.FREEZE.eq(param.getAccountStatusEnum())) {
      appUserAccountClient.updateAccountFreeze(param.getBeApprovalUserId(), param.getDays());

      ResponseAssert.requiredSuccess(newsletterClient.send(
              new NewsletterResultCmd()
                  .setUserIds(List.of(param.getBeApprovalUserId()))
                  .setEvent(NewsletterEvent.ACCOUNT_FREEZE)
                  .setData(TimestampUtils.nowPlusDays(param.getDays()))
          )
      );
      redisService
          .delete(SecurityConstant.getAccessTokenCacheKeyMd5(param.getBeApprovalUserId()));
    }
    // 封禁
    else if (ConsoleAccountStatusEnum.ARCHIVE.eq(param.getAccountStatusEnum())) {
      ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
          ResponseAssert.requiredSuccess(
              appUserAccountClient.updateAccountStatus(param.getBeApprovalUserId(), AccountStatusEnum.ARCHIVE)));

      ResponseAssert.requiredSuccess(newsletterClient.send(
              new NewsletterResultCmd()
                  .setUserIds(List.of(param.getBeApprovalUserId()))
                  .setEvent(NewsletterEvent.ACCOUNT_ARCHIVE)
          )
      );

      redisService
          .delete(SecurityConstant.getAccessTokenCacheKeyMd5(param.getBeApprovalUserId()));
      authClient.removeToken(param.getBeApprovalUserId());

      imAccountClient.kick(param.getBeApprovalUserId());
    }
    // 封禁+设备
    else if (ConsoleAccountStatusEnum.ARCHIVE_DEVICE.eq(param.getAccountStatusEnum())) {

      ArchiveDeviceDTO cmd = new ArchiveDeviceDTO();
      cmd.setDeviceNo(ResponseAssert.requiredSuccess(
          registerDeviceClient.getImeiByUserId(param.getBeApprovalUserId())));
      cmd.setSysOrigin(ResponseAssert.requiredSuccess(
              userProfileClient.getSysOrigin(param.getBeApprovalUserId()))
          .getSysOrigin());
      registerDeviceClient.addArchiveDevice(cmd);

      // 根据被处理用户的设备ID查询出关联用户并处理
      listRelationUsersByUserId(param.getBeApprovalUserId()).forEach(relationUser -> {

        ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
            ResponseAssert.requiredSuccess(
                appUserAccountClient.updateAccountStatus(relationUser.getUserId(),
                    AccountStatusEnum.ARCHIVE_DEVICE)));

        redisService
            .delete(SecurityConstant.getAccessTokenCacheKeyMd5(relationUser.getUserId()));
        authClient.removeToken(param.getBeApprovalUserId());

        imAccountClient.kick(relationUser.getUserId());

        ResponseAssert.requiredSuccess(newsletterClient.send(
                new NewsletterResultCmd()
                    .setUserIds(List.of(relationUser.getUserId()))
                    .setEvent(NewsletterEvent.ARCHIVE_DEVICE)
            )
        );

        addLog(param, relationUser.getUserId());
      });
      return;
    }
    // 解封账号
    else if (ConsoleAccountStatusEnum.UNTIE_ACOOUNT.eq(param.getAccountStatusEnum())) {
      ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
          ResponseAssert.requiredSuccess(appUserAccountClient
              .updateAccountStatus(param.getBeApprovalUserId(), AccountStatusEnum.NORMAL)));

      ResponseAssert.requiredSuccess(newsletterClient.send(
              new NewsletterResultCmd()
                  .setUserIds(List.of(param.getBeApprovalUserId()))
                  .setEvent(NewsletterEvent.UNTIE_ACOOUNT)
          )
      );
    }
    // 设备解封
    else if (ConsoleAccountStatusEnum.UNTIE_DEVICE.eq(param.getAccountStatusEnum())) {

      ArchiveDeviceDTO cmd = new ArchiveDeviceDTO();
      cmd.setDeviceNo(ResponseAssert.requiredSuccess(
          registerDeviceClient.getImeiByUserId(param.getBeApprovalUserId())));
      cmd.setSysOrigin(ResponseAssert.requiredSuccess(
              userProfileClient.getSysOrigin(param.getBeApprovalUserId()))
          .getSysOrigin());

      registerDeviceClient.removeArchiveDevice(cmd);

      ResponseAssert.requiredSuccess(newsletterClient.send(
              new NewsletterResultCmd()
                  .setUserIds(List.of(param.getBeApprovalUserId()))
                  .setEvent(NewsletterEvent.UNTIE_DEVICE)
          )
      );
    }
    // 设备解封+账户
    else if (ConsoleAccountStatusEnum.UNTIE_DEVICE_AND_ACCOUNT.eq(param.getAccountStatusEnum())) {

      ArchiveDeviceDTO cmd = new ArchiveDeviceDTO();
      cmd.setDeviceNo(ResponseAssert.requiredSuccess(
          registerDeviceClient.getImeiByUserId(param.getBeApprovalUserId())));
      cmd.setSysOrigin(ResponseAssert.requiredSuccess(
              userProfileClient.getSysOrigin(param.getBeApprovalUserId()))
          .getSysOrigin());

      registerDeviceClient.removeArchiveDevice(cmd);

      // 根据被处理用户的设备ID查询出关联用户并处理
      listRelationUsersByUserId(param.getBeApprovalUserId()).forEach(relationUser -> {

        ResponseAssert.isTrue(CommonErrorCode.UPDATE_FAILURE,
            ResponseAssert.requiredSuccess(
                appUserAccountClient.updateAccountStatus(relationUser.getUserId(),
                    AccountStatusEnum.NORMAL)));

        ResponseAssert.requiredSuccess(newsletterClient.send(
                new NewsletterResultCmd()
                    .setUserIds(List.of(relationUser.getUserId()))
                    .setEvent(NewsletterEvent.UNTIE_DEVICE_AND_ACCOUNT)
            )
        );

        addLog(param, relationUser.getUserId());
      });

      return;
    }

    removeTrtcRoom(param);

    addLog(param, param.getBeApprovalUserId());

    userProfileClient.removeRunProfileById(param.getBeApprovalUserId());

  }

  private void removeTrtcRoom(ApprovalAccountCmd param) {
    String sessionId = ResponseAssert.requiredSuccess(
        userOnlineClient.getSessionId(param.getBeApprovalUserId()));
    if (Objects.nonNull(sessionId)) {
      RoomProfileDTO roomProfile = ResponseAssert.requiredSuccess(
          roomManagerClient.getProfileById(Long.valueOf(sessionId)));
      if (Objects.nonNull(roomProfile)) {
        trtcClient.removeUser(
            new TrtcRemoveUserCmd()
                .setRoomId(Long.parseLong(roomProfile.getRoomAccount()))
                .setUserIds(List.of(param.getBeApprovalUserId()))
        );
      }
    }
  }

  /**
   * 记录操作日志
   */
  private void addLog(ApprovalAccountCmd param, Long beApprovalUserId) {

    ResponseAssert.requiredSuccess(appUserAccountClient.saveApprovalLog(
            new ApprovalUserAccountStatusLogCmd()
                .setCreateUser(param.getApprovalUserId())
                .setBeApprovalUser(beApprovalUserId)
                .setDescription(param.getDescriptionContent())
                .setStatus(param.getAccountStatusEnum().name())
        )
    );

    // 删除redis缓存
    userProfileClient.removeCache(beApprovalUserId);
  }

  /**
   * 获得关联设备用户集合
   *
   * @param userId 用户
   * @return 设备集合
   */
  private List<UserLatestMobileDeviceHistoryDTO> listRelationUsersByUserId(Long userId) {

    String imei = ResponseAssert.requiredSuccess(registerDeviceClient.getImeiByUserId(userId));
    if (StringUtils.isBlank(imei)) {
      return Lists.newArrayList();
    }
    SysOriginPlatformEnum sysOrigin = ResponseAssert.requiredSuccess(
        userProfileClient.getSysOrigin(userId));
    return ResponseAssert.requiredSuccess(
        registerDeviceClient.listByImei(imei, sysOrigin.getSysOrigin()));
  }

}
