package com.red.circle.other.infra.common.team;

import com.red.circle.component.redis.service.RedisService;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTargetService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.inner.model.dto.agency.agency.TeamTargetBillRes;
import com.red.circle.other.inner.enums.team.TeamMemberTargetIndex;
import com.red.circle.other.inner.enums.team.TeamMemberTargetStatus;
import com.red.circle.tool.core.date.DateFormatConstant;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.func.VoidCallable;
import com.red.circle.tool.core.func.VoidConsumer;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import static com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils.getCalcBillBelong;

/**
 * 房间主播管理.
 *
 * @author pengliang on 2021/5/31
 */
@Component
@RequiredArgsConstructor
public class TeamTargetCommon {

  private final RedisService redisService;
  private final UserRegionGateway userRegionGateway;
  private final TeamMemberService teamMemberService;
  private final TeamProfileService teamProfileService;
  private final TeamMemberTargetService teamMemberTargetService;

  /**
   * 累计直播时间.
   */
  public void incrementBroadcastTime(Long userId) {
    appendAnchorTarget(userId, () -> {

      teamMemberTargetService.incrOwnOnlineTime(userId, 1);

//      TeamMember teamMember = teamMemberService.getByMemberId(userId);
//      if (Objects.nonNull(teamMember)) {
//        teamSalaryMqMessage.sendSalaryCount(Set.of(teamMember.getTeamId()));
//      }

    });
  }

  /**
   * 累计其他房间时长.
   */
  public void incrementOtherTime(Long userId) {

    appendAnchorTarget(userId, () -> {

      teamMemberTargetService.incrOtherOnlineTime(userId, 1);

//      TeamMember teamMember = teamMemberService.getByMemberId(userId);
//      if (Objects.nonNull(teamMember)) {
//        teamSalaryMqMessage.sendSalaryCount(Set.of(teamMember.getTeamId()));
//      }
    });
  }

  /**
   * 礼物流水.
   *
   * @param userId   用户lid
   * @param quantity 数量
   */
  public TeamTargetBillRes incrementGiftValue(Long userId, BigDecimal quantity) {

    return appendAnchorTarget(userId, () -> TeamTargetBillRes.of((long)
            ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt(),
        teamMemberTargetService.incrAcceptGiftValue(userId, quantity.longValue())));
  }

  /**
   * 个人房间流水.
   *
   * @param userId   用户lid
   * @param quantity 数量
   */
  public void incrementRoomValue(Long userId, BigDecimal quantity) {
    appendAnchorTarget(userId,
        () -> teamMemberTargetService.incrRoomValue(userId, quantity.longValue()));
  }

  /**
   * 发送礼物数量.
   *
   * @param userId   用户lid
   * @param quantity 数量
   */
  public void incrementSendGiftQuantity(Long userId, BigDecimal quantity) {
    appendAnchorTarget(userId,
        () -> teamMemberTargetService.incrGiveGiftValue(userId, quantity.longValue()));
  }

  private void appendAnchorTarget(Long userId, VoidConsumer consumer) {
    appendAnchorTarget(userId, () -> {
      consumer.accept();
      return null;
    });
  }

  /**
   * 创建成员目标单据业务.
   */
  private TeamTargetBillRes appendAnchorTarget(Long userId,
      VoidCallable<TeamTargetBillRes> consumer) {

    TeamMember teamMember = teamMemberService.getByMemberId(userId);
    if (Objects.isNull(teamMember)) {
      return TeamTargetBillRes.of((long) getCalcBillBelong(),
          Boolean.FALSE);
    }

    // 成员目标单据不存在
    if (Boolean.FALSE.equals(existsBillTarget(userId))) {

      // 上锁
      String key = "CREATE_MEMBER_TARGET:" + teamMember.getTeamId() + "_" + userId;
      if (Boolean.TRUE.equals(redisService.lock(key, 5))) {

        // 单据创建完成立刻解锁
        teamMemberTargetService.createMemberTarget(builderTeamMemberTarget(teamMember));
        redisService.unlock(key);
        return consumer.apply();
      }

      // 锁定期间进来的数据一律当做不是主播处理
      return TeamTargetBillRes.of((long) getCalcBillBelong(),
          Boolean.FALSE);
    }

    // 创建成员每日目标单据
    teamMemberTargetService
        .createDailyWorkTarget(userId, getCalcBillBelong());

    return consumer.apply();
  }

  private TeamMemberTarget builderTeamMemberTarget(TeamMember teamMember) {

    return new TeamMemberTarget()
        .setTimeId(IdWorkerUtils.getId())
        .setSysOrigin(teamMember.getSysOrigin())
        .setTeamId(teamMember.getTeamId())
        .setBillBelong(getCalcBillBelong())
        .setBillTitle(getCalcBillBelong().toString())
        .setUserId(teamMember.getMemberId())
        .setStatus(Boolean.TRUE.equals(getOpenDailyAutoSalary(teamMember))
            ? TeamMemberTargetStatus.AUTO : TeamMemberTargetStatus.NOT_RECORDED)
        .setDailyTargets(List.of(
            new TeamMemberTargetIndex()
                .setOwnOnlineTime(0L)
                .setOtherOnlineTime(0L)
                .setAcceptGiftValue(0L)
                .setGiveGiftValue(0L)
                .setRoomValue(0L)
                .setDateNumber(ZonedDateTimeAsiaRiyadhUtils.nowDateToInt())
                .setCreateTime(TimestampUtils.now())
                .setUpdateTime(TimestampUtils.now())
        ))
        .setCreateTime(TimestampUtils.now())
        .setUpdateTime(TimestampUtils.now());
  }

  private Boolean existsBillTarget(Long userId) {

    return teamMemberTargetService
        .existsBillTarget(userId, getCalcBillBelong());
  }

  private Boolean getOpenDailyAutoSalary(TeamMember teamMember) {

    TeamProfile teamProfile = teamProfileService.getById(teamMember.getTeamId());
    if (Objects.isNull(teamProfile)) {
      return Boolean.FALSE;
    }

    return userRegionGateway
        .checkOpenDailyAutoSalary(teamProfile.getRegion(), teamProfile.getSysOrigin());
  }


  private String checkCreateKey(TeamMember teamMember) {
    return "CT:" +
        teamMember.getTeamId() +
        "_" +
        teamMember.getMemberId() +
        "_" +
        ZonedDateTimeAsiaRiyadhUtils.nowDateToInt();
  }


}
