package com.red.circle.live.app.listener.agora;

import com.red.circle.component.redis.service.RedisService;
import com.red.circle.live.app.listener.agora.callback.AgoraChannelBase;
import com.red.circle.live.app.listener.agora.callback.AgoraChannelUserJoin;
import com.red.circle.live.app.listener.agora.callback.AgoraChannelUserLeave;
import com.red.circle.live.app.listener.agora.callback.AgoraChannelUserRoleChange;
import com.red.circle.live.app.listener.agora.callback.AgoraChannelWebhook;
import com.red.circle.live.app.listener.agora.callback.AgoraChannelWebhookListener;
import com.red.circle.live.app.service.AgoraMicStateCleanupService;
import com.red.circle.other.inner.endpoint.live.RoomManagerClient;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import com.red.circle.other.inner.model.dto.live.RoomProfileDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.parse.DataTypeUtils;
import com.red.circle.tool.core.regex.RegexConstant;
import com.red.circle.tool.core.text.StringUtils;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 声网监听实现.
 *
 * @author pengliang on 2023/12/29
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AgoraChannelWebhookImplListener implements AgoraChannelWebhookListener {

  private final RedisService redisService;
  private final UserProfileClient userProfileClient;
  private final RoomManagerClient roomManagerClient;
  private final AgoraMicStateCleanupService agoraMicStateCleanupService;

  @Override
  public void channelCreate(AgoraChannelWebhook webhook, AgoraChannelBase body) {

  }

  @Override
  public void channelDestroy(AgoraChannelWebhook webhook, AgoraChannelBase body) {
    Long roomId = getRoomId(body);
    if (Objects.isNull(roomId) || !checkProcess(webhook, body)) {
      return;
    }
    agoraMicStateCleanupService.cleanupRoom(roomId, "agora channel destroy");
  }

  @Override
  public void broadcasterJoinChannel(AgoraChannelWebhook webhook, AgoraChannelUserJoin body) {

//    UserRoomProfile userRoomProfile = getUserRoomProfile(webhook, body, body.getUid());
//
//    if (Objects.isNull(userRoomProfile)) {
//      return;
//    }
//
//    liveMicCommon.onlineUserNoticeJoin(userRoomProfile.getRoomProfile().getId(),
//        userRoomProfile.getUserProfile().getId());
  }

  @Override
  public void broadcasterLeaveChannel(AgoraChannelWebhook webhook, AgoraChannelUserLeave body) {
    leaveChannelProcess(webhook, body, body.getUid(), "agora broadcaster leave");
  }


  @Override
  public void audienceJoinChannel(AgoraChannelWebhook webhook, AgoraChannelUserJoin body) {

  }

  @Override
  public void audienceLeaveChannel(AgoraChannelWebhook webhook, AgoraChannelUserLeave body) {
    leaveChannelProcess(webhook, body, body.getUid(), "agora audience leave");
  }

  @Override
  public void clientRoleChangeToBroadcaster(AgoraChannelWebhook webhook,
      AgoraChannelUserRoleChange body) {

  }

  @Override
  public void clientRoleChangeToAudience(AgoraChannelWebhook webhook,
      AgoraChannelUserRoleChange body) {
    leaveChannelProcess(webhook, body, body.getUid(), "agora role change to audience");
  }

  private void leaveChannelProcess(AgoraChannelWebhook webhook, AgoraChannelBase body, Long uid,
      String reason) {
    UserRoomProfile userRoomProfile = getUserRoomProfile(webhook, body, uid);
    if (Objects.isNull(userRoomProfile)) {
      return;
    }

    agoraMicStateCleanupService.cleanupUser(
        userRoomProfile.getRoomProfile().getId(),
        userRoomProfile.getUserProfile().getId(),
        reason
    );
  }

  private Long getRoomId(AgoraChannelBase body) {
    if (Objects.isNull(body) || StringUtils.isBlank(body.getChannelName())
        || !body.getChannelName().matches(RegexConstant.NUMBER)) {
      log.warn("错误的声网频道名称: {}", Objects.nonNull(body) ? body.getChannelName() : null);
      return null;
    }
    return DataTypeUtils.toLong(body.getChannelName());
  }

  private UserRoomProfile getUserRoomProfile(AgoraChannelWebhook webhook, AgoraChannelBase body,
      Long uid) {
    Long roomId = getRoomId(body);
    if (Objects.isNull(roomId) || roomId <= 0 || Objects.isNull(uid)) {
      return null;
    }

    if (!checkProcess(webhook, body)) {
      return null;
    }

    RoomProfileDTO roomProfile = roomManagerClient.getById(roomId).getBody();
    if (Objects.isNull(roomProfile)) {
      return null;
    }

    UserProfileDTO userProfile = userProfileClient.getByAccount(roomProfile.getSysOrigin(),
        Objects.toString(uid)).getBody();
    if (Objects.isNull(userProfile)) {
      log.warn("声网回调未找到用户 roomId={}, uid={}", roomId, uid);
      return null;
    }

    return new UserRoomProfile()
        .setRoomProfile(roomProfile)
        .setUserProfile(userProfile);
  }

  /**
   * true 未处理, false 已处理.
   */
  private boolean checkProcess(AgoraChannelWebhook webhook, AgoraChannelBase body) {
    if (Objects.isNull(webhook)) {
      return false;
    }
    String uniqueKey = StringUtils.isNotBlank(webhook.getNoticeId())
        ? webhook.getNoticeId()
        : webhook.getEventType() + ":" + (Objects.nonNull(body) ? body.getTs() : webhook.getNotifyMs());
    return redisService.setIfAbsent("AGORA:" + uniqueKey, 1, 1, TimeUnit.MINUTES);
  }


  @Data
  @Accessors(chain = true)
  class UserRoomProfile {

    private UserProfileDTO userProfile;
    private RoomProfileDTO roomProfile;

  }

}
