package com.red.circle.other.app.listener;

import com.alibaba.fastjson.JSON;
import com.red.circle.common.business.core.enums.ApprovalStatusEnum;
import com.red.circle.common.business.core.enums.DataApprovalTypeEnum;
import com.red.circle.component.mq.MessageEventProcess;
import com.red.circle.component.mq.MessageEventProcessDescribe;
import com.red.circle.component.mq.config.RocketMqMessageListener;
import com.red.circle.component.mq.service.Action;
import com.red.circle.component.mq.service.ConsumerMessage;
import com.red.circle.component.mq.service.MessageListener;
import com.red.circle.external.inner.endpoint.censor.CensorImageClient;
import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient;
import com.red.circle.external.inner.endpoint.oss.OssServiceClient;
import com.red.circle.external.inner.model.dto.CensorImageResponseDTO;
import com.red.circle.external.inner.model.dto.CensorSuggestion;
import com.red.circle.mq.business.model.event.approval.CensorContent;
import com.red.circle.mq.business.model.event.approval.CensorProfileEvent;
import com.red.circle.mq.rocket.business.streams.CensorProfileSink;
import com.red.circle.other.app.common.room.DynamicCommon;
import com.red.circle.other.domain.enums.PhotoAuditStatus;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.convertor.user.UserProfileInfraConvertor;
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.mongo.service.user.profile.UserRunProfileService;
import com.red.circle.other.infra.database.rds.entity.approval.ApprovalUserViolationHistory;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicPicture;
import com.red.circle.other.infra.database.rds.entity.user.user.BaseInfo;
import com.red.circle.other.infra.database.rds.service.approval.ApprovalUserSettingDataService;
import com.red.circle.other.infra.database.rds.service.approval.ApprovalUserViolationHistoryService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicPictureService;
import com.red.circle.other.infra.database.rds.service.user.user.BaseInfoService;
import com.red.circle.other.inner.enums.config.EnumConfigKey;
import com.red.circle.other.inner.enums.other.PhotoCensorStatusEnum;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author pengliang
 * @since 2019/11/19 22:07
 */
@Slf4j
@RocketMqMessageListener(groupId = CensorProfileSink.INPUT, tag = CensorProfileSink.TAG)
@RequiredArgsConstructor
public class CensorProfileListener implements MessageListener {

  private final String tag = "资料安全鉴定";
  private final DynamicCommon dynamicCommon;
  private final OssServiceClient ossServiceClient;
  private final CensorImageClient censorImageClient;
  private final UserProfileGateway userProfileGateway;
  private final MessageEventProcess messageEventProcess;
  private final OfficialNoticeClient officialNoticeClient;
  private final DynamicPictureService dynamicPictureService;
  private final EnumConfigCacheService enumConfigCacheService;
  private final RoomProfileManagerService roomProfileManagerService;
  private final ApprovalUserSettingDataService approvalUserSettingDataService;
  private final ApprovalUserViolationHistoryService approvalUserViolationHistoryService;
  private final UserRunProfileService userRunProfileService;
  private final BaseInfoService baseInfoService;
  private final UserProfileInfraConvertor userProfileInfraConvertor;

  @Override
  public Action consume(ConsumerMessage message) {
    return messageEventProcess.consume(
        MessageEventProcessDescribe.builder()
            .logTag(tag)
            .consumeMsgTimeoutMinute(10)
            .repeatConsumeMinute(10)
            .repeatConsumeTag("CensorProfile")
            .checkConsumeTag(CensorProfileSink.TAG)
            .message(message)
            .build(),
        CensorProfileEvent.class,
        this::execute);
  }

  private void execute(CensorProfileEvent eventBody) {
    log.warn("eventBody{}", eventBody);
    log.warn("eventBody{}", eventBody.getContents());
    if (!eventBody.requiredParamNone()) {
      log.warn("[{}]审核参数错误，必须参数存在空值", tag);
      return;
    }

    if (!eventBody.isImageType()) {
      log.warn("[{}]审类型非图片类型", tag);
      return;
    }

    if (eventBody.checkUserAvatar()) {
      avatarCensor(eventBody);
      return;
    }

    if (eventBody.checkRoomAvatar()) {
      roomAvatarCensor(eventBody);
      return;
    }

    if (eventBody.checkDynamicContent()) {
      dynamicImageCensor(eventBody);
      return;
    }

    if (eventBody.checkBackgroundPhoto()) {
      batchPhotoCensor(eventBody, DataApprovalTypeEnum.BACKGROUND_PHOTO);
      return;
    }

    if (eventBody.checkPersonalPhoto()) {
      batchPhotoCensor(eventBody, DataApprovalTypeEnum.PERSONAL_PHOTO);
    }
  }

  private void dynamicImageCensor(CensorProfileEvent censorProfileEvent) {

    AtomicReference<Boolean> isViolation = new AtomicReference<>(Boolean.FALSE);

    List<DynamicPicture> pictures = censorProfileEvent.getContents().stream()
        .map(violationContent -> {
          DynamicPicture picture = new DynamicPicture();
          picture.setId(violationContent.getId());
          picture.setDynamicId(censorProfileEvent.dynamicId());
          picture.setResourceUrl(violationContent.getContent());

          try {
            CensorImageResponseDTO response = censorImageClient.auditing(
                violationContent.compression300Content()).getBody();

            picture.setLabelNames(response.formatLabelString());
            if (response.checkBlock()) {
              picture.setViolation(PhotoCensorStatusEnum.VIOLATION.name());
              isViolation.set(Boolean.TRUE);
            } else if (response.checkPass()) {
              picture.setViolation(PhotoCensorStatusEnum.NORMAL.name());
            } else {
              picture.setViolation(PhotoCensorStatusEnum.SUSPECTED.name());
            }
            return picture;
          } catch (Exception ex) {
            // 如果调用失败进入人工审核
            picture.setLabelNames("鉴定服务调用异常");
            picture.setViolation(PhotoCensorStatusEnum.SUSPECTED.name());
            return picture;
          }


        }).collect(Collectors.toList());

    if (Boolean.TRUE.equals(isViolation.get())) {

      //删除动态与好友动态
//      dynamicCommon.systemDeleteDynamic(censorProfileEvent.dynamicId());

      // 机器审核违规则删除这条动态全部图片
      for (DynamicPicture picture : pictures) {
        if (PhotoCensorStatusEnum.VIOLATION.name().equals(picture.getViolation())) {
          ossServiceClient.remove(picture.getResourceUrl());
        }
      }
    }

    if (CollectionUtils.isEmpty(pictures)) {
      log.warn("审核结果 dynamicImageCensor 为空");
      return;
    }

    //修改动态图片列表图片状态与机器打分
    dynamicPictureService.updateBatchById(pictures);
  }


  String ossFile = "https://dev.file.momooline.com/";
  String ossAccess = "https://media.haiyihy.com/";

  private void roomAvatarCensor(CensorProfileEvent param) {
    CensorContent censorContent = param.getContents().get(0);
    try {
      imsRoomImageClient(param, censorContent);
    } catch (Exception ex) {
      try {
        imsRoomImageClient(param, censorContent);
      } catch (Exception e) {
        // 如果调用失败进入人工审核
        roomAvatarViolationHandle(param.getUserId(), censorContent.getContent(),
            "鉴定服务调用异常");
      }
    }

  }

  private void imsRoomImageClient(CensorProfileEvent param, CensorContent censorContent) {
    String imgUrl = censorContent.compression300Content().replaceAll(ossFile, ossAccess);
    log.warn("imgUrl，{}", imgUrl);
    CensorImageResponseDTO response = censorImageClient.auditing(imgUrl).getBody();
    log.warn("response{}", response);

    String avatarLabelNames = response.formatLabelString();
    if (response.checkBlock()) {
      roomAvatarViolationHandle(param.getUserId(), censorContent.getContent(),
          avatarLabelNames);
      ossServiceClient.remove(censorContent.getContent());
      return;
    }

    approvalUserSettingDataService.updateApprovalStatusMachineLabel(param.getUserId(),
        Objects.equals(response.getSuggestion(), CensorSuggestion.Pass) ? ApprovalStatusEnum.PASS
            : ApprovalStatusEnum.PENDING,
        DataApprovalTypeEnum.ROOM_AVATAR, avatarLabelNames);
  }

  private void roomAvatarViolationHandle(Long userId, String content, String avatarLabelNames) {
    // 刷新审批标签
    approvalUserSettingDataService
        .updateApprovalStatusMachineLabel(userId, ApprovalStatusEnum.NOT_PASS,
            DataApprovalTypeEnum.ROOM_AVATAR, avatarLabelNames);
    // 替换违规头像
    roomProfileManagerService.updateRoomCoverByUserId(userId, StringUtils.EMPTY);

    // 记录审批历史
    ApprovalUserViolationHistory approvalHistory = new ApprovalUserViolationHistory()
        .setUserId(userId)
        .setViolationType(DataApprovalTypeEnum.ROOM_AVATAR.name())
        .setLabelNames(avatarLabelNames)
        .setApprovalResult(ApprovalStatusEnum.NOT_PASS.name())
        .setContentId(userId)
        .setContent(content)
        .setDescription("机器审核");
    approvalHistory.setCreateUser(0L);
    approvalHistory.setUpdateUser(0L);
    approvalHistory.setCreateTime(TimestampUtils.now());
    approvalUserViolationHistoryService.save(approvalHistory);
  }


  private void avatarCensor(CensorProfileEvent param) {
    CensorContent censorContent = param.getContents().get(0);

    try {
      CensorImageResponseDTO response = censorImageClient.auditing(censorContent.compression300Content()).getBody();

      String avatarLabelNames = response.formatLabelString();

      if (Objects.equals(response.getSuggestion(), CensorSuggestion.Block)) {
        userAvatarApprovalNotPassHandle(param, censorContent.getContent(), avatarLabelNames);
        ossServiceClient.remove(censorContent.getContent());
      } else if (Objects.equals(response.getSuggestion(), CensorSuggestion.Pass)) {
        approvalUserSettingDataService.updateApprovalStatusMachineLabel(param.getUserId(), ApprovalStatusEnum.PASS,
                DataApprovalTypeEnum.AVATAR, avatarLabelNames);
      } else {
        approvalUserSettingDataService.updateApprovalStatusMachineLabel(param.getUserId(), ApprovalStatusEnum.PENDING,
                DataApprovalTypeEnum.AVATAR, avatarLabelNames);
      }
    } catch (Exception ex) {
      // 如果调用失败进入人工审核
      approvalUserSettingDataService.updateApprovalStatusMachineLabel(param.getUserId(), ApprovalStatusEnum.PENDING,
              DataApprovalTypeEnum.AVATAR, "鉴定服务调用异常");
    }
  }

  private void batchPhotoCensor(CensorProfileEvent param, DataApprovalTypeEnum approvalType) {
    if (CollectionUtils.isEmpty(param.getContents())) {
      return;
    }

    UserProfile userProfile = userProfileGateway.getByUserId(param.getUserId());
    if (userProfile == null) {
      log.warn("用户不存在: {}", param.getUserId());
      return;
    }

    for (CensorContent censorContent : param.getContents()) {
      try {
        CensorImageResponseDTO response = censorImageClient.auditing(
            censorContent.compression300Content()).getBody();

        String labelNames = response.formatLabelString();

        if (response.checkBlock()) {
          // 审核不通过，记录违规
          photoViolationHandle(param.getUserId(), censorContent.getContent(), labelNames, approvalType);
          // 更新MongoDB中图片状态
          updatePhotoStatus(param.getUserId(), censorContent.getContent(), 
              PhotoAuditStatus.REJECTED.getCode(), labelNames, approvalType);
        } else if (response.checkPass()) {
          // 审核通过
          approvalUserSettingDataService.updateApprovalStatusMachineLabel(
              param.getUserId(), ApprovalStatusEnum.PASS, approvalType, labelNames);
          // 更新MongoDB中图片状态
          updatePhotoStatus(param.getUserId(), censorContent.getContent(), 
              PhotoAuditStatus.APPROVED.getCode(), null, approvalType);
        } else {
          // 待人工审核
          approvalUserSettingDataService.updateApprovalStatusMachineLabel(
              param.getUserId(), ApprovalStatusEnum.PENDING, approvalType, labelNames);
        }
      } catch (Exception ex) {
        log.error("图片审核异常: userId={}, url={}", param.getUserId(), 
            censorContent.getContent(), ex);
        // 调用失败进入人工审核
        approvalUserSettingDataService.updateApprovalStatusMachineLabel(
            param.getUserId(), ApprovalStatusEnum.PENDING, approvalType, "鉴定服务调用异常");
      }
    }
  }

  private void updatePhotoStatus(Long userId, String photoUrl, Integer status, 
      String rejectReason, DataApprovalTypeEnum approvalType) {
    // 更新 MongoDB
    if (DataApprovalTypeEnum.BACKGROUND_PHOTO.equals(approvalType)) {
      userRunProfileService.updateBackgroundPhotoStatus(userId, photoUrl, status, rejectReason);
    } else if (DataApprovalTypeEnum.PERSONAL_PHOTO.equals(approvalType)) {
      userRunProfileService.updatePersonalPhotoStatus(userId, photoUrl, status, rejectReason);
    }
    
    // 同步更新 MySQL
    try {
      UserProfile userProfile = userProfileGateway.getByUserId(userId);
      if (userProfile == null) {
        return;
      }
      
      BaseInfo baseInfo = new BaseInfo();
      baseInfo.setId(userId);
      
      if (DataApprovalTypeEnum.BACKGROUND_PHOTO.equals(approvalType) 
          && CollectionUtils.isNotEmpty(userProfile.getBackgroundPhotos())) {
        // 更新列表中图片状态
        userProfile.getBackgroundPhotos().stream()
            .filter(photo -> photo.getUrl().equals(photoUrl))
            .findFirst()
            .ifPresent(photo -> {
              photo.setStatus(status);
              photo.setRejectReason(rejectReason);
            });
        baseInfo.setBackgroundPhoto(JSON.toJSONString(userProfile.getBackgroundPhotos()));
        baseInfoService.updateSelectiveById(baseInfo);
      } else if (DataApprovalTypeEnum.PERSONAL_PHOTO.equals(approvalType) 
          && CollectionUtils.isNotEmpty(userProfile.getPersonalPhotos())) {
        // 更新列表中图片状态
        userProfile.getPersonalPhotos().stream()
            .filter(photo -> photo.getUrl().equals(photoUrl))
            .findFirst()
            .ifPresent(photo -> {
              photo.setStatus(status);
              photo.setRejectReason(rejectReason);
            });
        baseInfo.setPersonalPhoto(JSON.toJSONString(userProfile.getPersonalPhotos()));
        baseInfoService.updateSelectiveById(baseInfo);
      }
    } catch (Exception e) {
      log.error("更新MySQL图片状态失败: userId={}, photoUrl={}", userId, photoUrl, e);
    }
  }

  private void photoViolationHandle(Long userId, String content, String labelNames, 
      DataApprovalTypeEnum approvalType) {
    // 刷新审批标签
    approvalUserSettingDataService.updateApprovalStatusMachineLabel(
        userId, ApprovalStatusEnum.NOT_PASS, approvalType, labelNames);

    // 记录审批历史
    ApprovalUserViolationHistory approvalHistory = new ApprovalUserViolationHistory()
        .setUserId(userId)
        .setViolationType(approvalType.name())
        .setLabelNames(labelNames)
        .setApprovalResult(ApprovalStatusEnum.NOT_PASS.name())
        .setContentId(userId)
        .setContent(content)
        .setDescription("机器审核");
    approvalHistory.setCreateUser(0L);
    approvalHistory.setUpdateUser(0L);
    approvalHistory.setCreateTime(TimestampUtils.now());
    approvalUserViolationHistoryService.save(approvalHistory);
  }

  private void userAvatarApprovalNotPassHandle(CensorProfileEvent param, String content,
      String avatarLabelNames) {
    // 更新审批状态
    approvalUserSettingDataService
        .updateApprovalStatusMachineLabel(param.getUserId(),
            ApprovalStatusEnum.NOT_PASS,
            param.getApprovalType(),
            avatarLabelNames);

    // 处理违规
    UserProfile userProfile = userProfileGateway.getByUserId(param.getUserId());

    userProfileGateway.updateUserAvatar(param.getUserId(),
        enumConfigCacheService.getValue(EnumConfigKey.VIOLATION_PICTURE,
            userProfile.getOriginSys()));
//    officialNoticeClient.send(param.getUserId(), OfficialNoticeTypeEnum.AVATAR_VIOLATION);

    // 保存审批记录
    ApprovalUserViolationHistory approvalUserViolationHistory = new ApprovalUserViolationHistory()
        .setUserId(param.getUserId())
        .setViolationType(DataApprovalTypeEnum.AVATAR.name())
        .setLabelNames(avatarLabelNames)
        .setApprovalResult(ApprovalStatusEnum.NOT_PASS.name())
        .setContentId(param.getUserId())
        .setContent(content)
        .setDescription("机器审核");
    approvalUserViolationHistory.setCreateUser(0L);
    approvalUserViolationHistory.setUpdateUser(0L);
    approvalUserViolationHistory.setCreateTime(TimestampUtils.now());
    approvalUserViolationHistoryService.save(approvalUserViolationHistory);
  }

}
