package com.red.circle.other.infra.database.mongo.service.team;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.red.circle.other.infra.database.mongo.dto.team.TeamBillMemberTarget;
import com.red.circle.other.infra.database.mongo.dto.team.TeamBillPolicyType;
import com.red.circle.other.infra.database.mongo.dto.team.TeamPolicy;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyManager;
import com.red.circle.other.infra.database.mongo.entity.user.region.SysRegionConfig;
import com.red.circle.other.infra.database.rds.entity.team.BillDiamondBalance;
import com.red.circle.other.inner.enums.team.TeamMemberTargetIndex;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.num.NumUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author pengliang on 2022/12/16
 */
public final class TeamBillCycleUtils {

  private static final Logger log = LoggerFactory.getLogger(TeamBillCycleUtils.class);

  /**
   * 团队周期数.
   */
  public static Long calculatorBillCycle(Long billCycle) {
    return Objects.isNull(billCycle) || billCycle <= 0 ? 1 : billCycle;
  }

  /**
   * 账单开始时间.
   */
  public static Integer nowStartDateNumber() {
    return ZonedDateTimeAsiaRiyadhUtils.nowDateToInt();
  }

  /**
   * 计算出账时间-沙特时区跟目标计算统一.
   * <p>
   * 创建账单（billType=WEEK）： 创建日期 2022-12-15， 周日18
   * <p>
   * 出账日（billType=WEEK,billCycle=1）：2022-12-15 ~ 2022-12-18
   * <p>
   * 出账日（billType=WEEK,billCycle=2）：2022-12-15 ~ 2022-12-25
   * <p>
   * 依次类推
   */
  @Deprecated
  public static Integer nowOutDateNumber(TeamBillPolicyType billType, Long billCycle) {
    Long plusBillCycle = calculatorBillCycle(billCycle);
    if (Objects.equals(billType, TeamBillPolicyType.MONTH)) {
      return ZonedDateTimeAsiaRiyadhUtils.getLastDayOfMonthToInt(
          ZonedDateTimeAsiaRiyadhUtils.now().plusMonths(plusBillCycle - 1));
    }

    if (Objects.equals(billType, TeamBillPolicyType.WEEK)) {
      return ZonedDateTimeAsiaRiyadhUtils.getWeekSunday(
          ZonedDateTimeAsiaRiyadhUtils.now().plusWeeks(plusBillCycle - 1));
    }
    throw new IllegalArgumentException("billType notRange.");
  }

  /**
   * 账单开始时间.
   * <p>
   * 月：下个月第一天
   * <p>
   * 周：下周第一天
   */
  @Deprecated
  public static Integer nextStartDateNumber(TeamBillPolicyType billType, Long billCycle) {
    Long plusBillCycle = calculatorBillCycle(billCycle);
    if (Objects.equals(billType, TeamBillPolicyType.MONTH)) {
      return ZonedDateTimeAsiaRiyadhUtils.getFirstDayOfMonthToInt(
          ZonedDateTimeAsiaRiyadhUtils.now().plusMonths(plusBillCycle));
    }
    if (Objects.equals(billType, TeamBillPolicyType.WEEK)) {
      return ZonedDateTimeAsiaRiyadhUtils.getWeekMonday(
          ZonedDateTimeAsiaRiyadhUtils.now().plusWeeks(plusBillCycle));
    }
    throw new IllegalArgumentException("billType notRange.");
  }

  /**
   * 计算出账时间-沙特时区跟目标计算统一.
   * <p>
   * 创建账单（billType=WEEK）： 创建日期 2022-12-15， 周日18
   * <p>
   * 出账日（billType=WEEK,billCycle=1）：2022-12-19 ~ 2022-12-25
   * <p>
   * 出账日（billType=WEEK,billCycle=2）：2022-12-26 ~ 2023-01-01
   * <p>
   * 依次类推
   */
  @Deprecated
  public static Integer nextOutDateNumber(TeamBillPolicyType billType, Long billCycle) {
    Long plusBillCycle = calculatorBillCycle(billCycle);
    if (Objects.equals(billType, TeamBillPolicyType.MONTH)) {
      return ZonedDateTimeAsiaRiyadhUtils.getLastDayOfMonthToInt(
          ZonedDateTimeAsiaRiyadhUtils.now().plusMonths(plusBillCycle * 2 - 1)
      );
    }

    if (Objects.equals(billType, TeamBillPolicyType.WEEK)) {
      return ZonedDateTimeAsiaRiyadhUtils.getWeekSunday(
          ZonedDateTimeAsiaRiyadhUtils.now().plusWeeks(plusBillCycle * 2 - 1)
      );
    }
    throw new IllegalArgumentException("billType notRange.");
  }

  /**
   * 计算成员工作情况.
   */
  public static TeamBillMemberTarget calculatorPolicyTarget(TeamMemberTarget target,
      TeamPolicyManager policy) {

    if (Objects.isNull(target)) {
      throw new IllegalArgumentException("target is null.");
    }
    return calculatorPolicyTarget(List.of(target), policy).get(0);
  }

  /**
   * 计算有效天数
   * 规则：每日在线时长 >= 120分钟算作有效一天
   *
   * @param target 成员目标数据
   * @return 有效天数
   */
  private static Integer calculateEffectiveDay(TeamMemberTarget target) {
    if (target == null || target.getDailyTargets() == null) {
      return 0;
    }

    // 统计每日在线时长 >= 120分钟的天数
    int effectiveDayCount = 0;
    for (Object dailyData : target.getDailyTargets()) {
      // 假设dailyData是包含ownOnlineTime和otherOnlineTime的对象
      Long dailyOnlineTime = getDailyTotalOnlineTime(dailyData);
      if (dailyOnlineTime != null && dailyOnlineTime >= 120) {
        effectiveDayCount++;
      }
    }

    return effectiveDayCount;
  }

  /**
   * 获取每日总在线时长
   * 根据您的MongoDB数据结构，需要累加ownOnlineTime和otherOnlineTime
   */
  private static Long getDailyTotalOnlineTime(Object dailyData) {
    try {
      JSONObject jsonObject = (JSONObject) JSON.toJSON(dailyData);
      Long ownOnlineTime = NumUtils.isNullDefaultZero(jsonObject.getLong("ownOnlineTime"));
      Long otherOnlineTime = NumUtils.isNullDefaultZero(jsonObject.getLong("otherOnlineTime"));
      return ownOnlineTime + otherOnlineTime;
    } catch (Exception e) {
      return 0L;
    }
  }

  /**
   * 计算成员工作情况.
   */
  public static List<TeamBillMemberTarget> calculatorPolicyTarget(List<TeamMemberTarget> targets,
      TeamPolicyManager policy) {

    if (CollectionUtils.isEmpty(targets)) {
      return Lists.newArrayList();
    }

    List<TeamPolicy> teamPolicies = Objects.nonNull(policy)
        ? policy.getPolicy().stream()
        .sorted(Comparator.comparing(TeamPolicy::getLevel, Comparator.reverseOrder()))
        .collect(Collectors.toList())
        : Lists.newArrayList();

    return targets.stream().map(target -> {
      long targetTimeHours = target.sumAllTargetTime() / 60;
      Long acceptGiftValue = target.sumAcceptGiftValue();
      Integer effectiveDay = calculateEffectiveDay(target);

      TeamBillMemberTarget resultTarget = new TeamBillMemberTarget()
          .setTargetId(target.getTimeId())
          .setSysOrigin(target.getSysOrigin())
          .setUserId(target.getUserId())
          .setAcceptGiftValue(target.sumAcceptGiftValue())
          .setGiveGiftValue(target.sumGiveGiftValue())
          .setRoomValue(target.sumRoomValue())
          .setOnlineTime(target.sumAllTargetTime())
          .setMemberSalary(BigDecimal.ZERO)
          .setOwnSalary(BigDecimal.ZERO)
          .setTotalSalary(BigDecimal.ZERO)
          .setSatisfyLevel(Boolean.FALSE);

      for (TeamPolicy teamPolicy : teamPolicies) {
        Long policyOnlineTimeHours = NumUtils.isNullDefaultZero(teamPolicy.getOnlineTime());
        Long policyGiftValue = NumUtils.isNullDefaultZero(teamPolicy.getTarget());

        // 礼物流水不满足条件
        if (acceptGiftValue < policyGiftValue) {
          continue;
        }

        // 完全满足条件：在线时长、礼物流水、有效天数都达标
        Integer policyEffectiveDay = NumUtils.isNullDefaultZero(teamPolicy.getEffectiveDay());
        if (targetTimeHours >= policyOnlineTimeHours && effectiveDay >= policyEffectiveDay) {
          resultTarget.setMemberSalary(teamPolicy.getMemberSalary());
          resultTarget.setOwnSalary(teamPolicy.getOwnSalary());
          resultTarget.setTotalSalary(teamPolicy.getTotalSalary());
        } else {
          resultTarget.setMemberSalary(teamPolicy.getMemberSalary().multiply(new BigDecimal("0.9")).setScale(2, RoundingMode.DOWN));
          resultTarget.setTotalSalary(teamPolicy.getMemberSalary().multiply(new BigDecimal("0.9")).setScale(2, RoundingMode.DOWN));
        }

        resultTarget.setLevel(teamPolicy.getLevel());
        resultTarget.setSatisfyLevel(Boolean.TRUE);
        resultTarget.setPropsRewards(teamPolicy.getPropsRewards());
        return resultTarget;
      }
      return resultTarget;
    }).filter(Objects::nonNull).collect(Collectors.toList());
  }

  /**
   * 计算成员工作情况-钻石政策.
   */
  public static TeamBillMemberTarget calculatorPolicyDiamondTarget(TeamMemberTarget target,
      TeamPolicyManager policy, BigDecimal consumptionPoints) {

    if (Objects.isNull(target)) {
      throw new IllegalArgumentException("target is null.");
    }
    return calculatorPolicyDiamondTarget(List.of(target), policy, consumptionPoints).get(0);
  }

  /**
   * 计算成员日工作情况-钻石政策.
   */
  public static List<TeamBillMemberTarget> calculatorPolicyDiamondDayTarget(
          List<TeamMemberTarget> targets,
          TeamPolicyManager policy) {

    if (CollectionUtils.isEmpty(targets)) {
      return Lists.newArrayList();
    }

    List<TeamPolicy> teamPolicies = Objects.nonNull(policy)
            ? policy.getPolicy().stream()
            .sorted(Comparator.comparing(TeamPolicy::getLevel, Comparator.reverseOrder()))
            .collect(Collectors.toList())
            : Lists.newArrayList();

    return targets.stream().map(target -> {
      log.warn("日账单：" + ZonedDateTimeAsiaRiyadhUtils.nowDateToInt());
      log.warn("target：" + target);
      TeamMemberTargetIndex teamMemberTargetIndex =
              target.getDailyTargets().stream()
                      .filter(item -> item.getDateNumber().equals(ZonedDateTimeAsiaRiyadhUtils.nowDateToInt())).findFirst().orElse(new TeamMemberTargetIndex());

      log.warn("日账单：" + teamMemberTargetIndex);
      Long acceptGiftValue = teamMemberTargetIndex.getAcceptGiftValue();
      TeamBillMemberTarget resultTarget = new TeamBillMemberTarget()
              .setTargetId(target.getTimeId())
              .setSysOrigin(target.getSysOrigin())
              .setUserId(target.getUserId())
              .setAcceptGiftValue(teamMemberTargetIndex.getAcceptGiftValue())
              .setGiveGiftValue(teamMemberTargetIndex.getGiveGiftValue())
              .setRoomValue(teamMemberTargetIndex.getRoomValue())
              .setOnlineTime(teamMemberTargetIndex.getOtherOnlineTime())
              .setMemberSalary(BigDecimal.ZERO)
              .setOwnSalary(BigDecimal.ZERO)
              .setRedeemedSalary(BigDecimal.ZERO)
              .setSurplusSalary(BigDecimal.ZERO)
              .setTotalSalary(BigDecimal.ZERO)
              .setSatisfyLevel(Boolean.FALSE);
      if (Objects.isNull(teamMemberTargetIndex.getAcceptGiftValue())) {
        // 日礼物空代表未收到
        return resultTarget;
      }
      for (TeamPolicy teamPolicy : teamPolicies) {
        Long policyGiftValue = NumUtils.isNullDefaultZero(teamPolicy.getTarget());
        if (acceptGiftValue >= policyGiftValue) {
          BigDecimal multiple = BigDecimal.valueOf(acceptGiftValue)
                  .divide(BigDecimal.valueOf(policyGiftValue), 4, RoundingMode.DOWN);
          BigDecimal memberSalary = teamPolicy.getMemberSalary().multiply(multiple).setScale(2, RoundingMode.DOWN);
          BigDecimal ownSalary = teamPolicy.getOwnSalary().multiply(multiple).setScale(2, RoundingMode.DOWN);
          BigDecimal totalSalary = memberSalary.add(ownSalary);
          resultTarget.setMemberSalary(memberSalary);
          resultTarget.setOwnSalary(ownSalary);
          resultTarget.setTotalSalary(totalSalary);
          resultTarget.setLevel(teamPolicy.getLevel());
          resultTarget.setSatisfyLevel(Boolean.TRUE);
          resultTarget.setPropsRewards(teamPolicy.getPropsRewards());
          resultTarget.setPolicyType(policy.getPolicyType());
          return resultTarget;
        }
      }
      return resultTarget;
    }).filter(Objects::nonNull).collect(Collectors.toList());
  }

  /**
   * 计算成员工作情况-钻石政策.
   */
  public static List<TeamBillMemberTarget> calculatorPolicyDiamondTarget(
      List<TeamMemberTarget> targets,
      TeamPolicyManager policy) {

    if (CollectionUtils.isEmpty(targets)) {
      return Lists.newArrayList();
    }

    List<TeamPolicy> teamPolicies = Objects.nonNull(policy)
        ? policy.getPolicy().stream()
        .sorted(Comparator.comparing(TeamPolicy::getLevel, Comparator.reverseOrder()))
        .collect(Collectors.toList())
        : Lists.newArrayList();

    return targets.stream().map(target -> {
      long targetTimeHours = target.sumAllTargetTime() / 60;
      Long acceptGiftValue = target.sumAcceptGiftValue();
      target.getBillBelong(); // 查询账单信息
      TeamBillMemberTarget resultTarget = new TeamBillMemberTarget()
          .setTargetId(target.getTimeId())
          .setSysOrigin(target.getSysOrigin())
          .setUserId(target.getUserId())
          .setAcceptGiftValue(target.sumAcceptGiftValue())
          .setGiveGiftValue(target.sumGiveGiftValue())
          .setRoomValue(target.sumRoomValue())
          .setOnlineTime(target.sumAllTargetTime())
          .setMemberSalary(BigDecimal.ZERO)
          .setOwnSalary(BigDecimal.ZERO)
          .setRedeemedSalary(BigDecimal.ZERO)
          .setSurplusSalary(BigDecimal.ZERO)
          .setTotalSalary(BigDecimal.ZERO)
          .setSatisfyLevel(Boolean.FALSE);

      for (TeamPolicy teamPolicy : teamPolicies) {
        Long policyOnlineTimeHours = NumUtils.isNullDefaultZero(teamPolicy.getOnlineTime());
        Long policyGiftValue = NumUtils.isNullDefaultZero(teamPolicy.getTarget());
        if (acceptGiftValue >= policyGiftValue) {
          BigDecimal multiple = BigDecimal.valueOf(acceptGiftValue)
              .divide(BigDecimal.valueOf(policyGiftValue), 4, RoundingMode.DOWN);
          BigDecimal memberSalary = teamPolicy.getMemberSalary().multiply(multiple).setScale(0, RoundingMode.DOWN);
          BigDecimal ownSalary = teamPolicy.getOwnSalary().multiply(multiple).setScale(0, RoundingMode.DOWN);
          BigDecimal totalSalary = memberSalary.add(ownSalary);
          resultTarget.setMemberSalary(memberSalary);
          resultTarget.setOwnSalary(ownSalary);
          resultTarget.setTotalSalary(totalSalary);
          resultTarget.setLevel(teamPolicy.getLevel());
          resultTarget.setSatisfyLevel(Boolean.TRUE);
          resultTarget.setPropsRewards(teamPolicy.getPropsRewards());
          resultTarget.setPolicyType(policy.getPolicyType());
          return resultTarget;
        }
      }
      return resultTarget;
    }).filter(Objects::nonNull).collect(Collectors.toList());
  }

  /**
   * 计算成员工作情况-钻石政策.
   */
  public static List<TeamBillMemberTarget> calculatorPolicyDiamondTarget(
          List<TeamMemberTarget> targets,
          TeamPolicyManager policy, BigDecimal consumptionPoints) {

    if (CollectionUtils.isEmpty(targets)) {
      return Lists.newArrayList();
    }

    List<TeamPolicy> teamPolicies = Objects.nonNull(policy)
            ? policy.getPolicy().stream()
            .sorted(Comparator.comparing(TeamPolicy::getLevel, Comparator.reverseOrder()))
            .collect(Collectors.toList())
            : Lists.newArrayList();

    return targets.stream().map(target -> {
      long targetTimeHours = target.sumAllTargetTime() / 60;
      Long acceptGiftValue = target.sumAcceptGiftValue();
      target.getBillBelong(); // 查询账单信息
      TeamBillMemberTarget resultTarget = new TeamBillMemberTarget()
              .setTargetId(target.getTimeId())
              .setSysOrigin(target.getSysOrigin())
              .setUserId(target.getUserId())
              .setAcceptGiftValue(target.sumAcceptGiftValue())
              .setGiveGiftValue(target.sumGiveGiftValue())
              .setRoomValue(target.sumRoomValue())
              .setOnlineTime(target.sumAllTargetTime())
              .setMemberSalary(BigDecimal.ZERO)
              .setOwnSalary(BigDecimal.ZERO)
              .setRedeemedSalary(consumptionPoints)
              .setSurplusSalary(BigDecimal.ZERO)
              .setTotalSalary(BigDecimal.ZERO)
              .setSatisfyLevel(Boolean.FALSE);

      for (TeamPolicy teamPolicy : teamPolicies) {
        Long policyOnlineTimeHours = NumUtils.isNullDefaultZero(teamPolicy.getOnlineTime());
        Long policyGiftValue = NumUtils.isNullDefaultZero(teamPolicy.getTarget());
        if (acceptGiftValue >= policyGiftValue) {
          BigDecimal multiple = BigDecimal.valueOf(acceptGiftValue)
                  .divide(BigDecimal.valueOf(policyGiftValue), 4, RoundingMode.DOWN);
          BigDecimal memberSalary = teamPolicy.getMemberSalary().multiply(multiple).setScale(0, RoundingMode.DOWN);
          BigDecimal ownSalary = teamPolicy.getOwnSalary().multiply(multiple).setScale(0, RoundingMode.DOWN);
          BigDecimal totalSalary = memberSalary.add(ownSalary);
          // 用户剩余工资=用户工资-用户已兑换工资
          BigDecimal surplusSalary = memberSalary.subtract(resultTarget.getRedeemedSalary());

          resultTarget.setSurplusSalary(surplusSalary);
          resultTarget.setMemberSalary(memberSalary);
          resultTarget.setOwnSalary(ownSalary);
          resultTarget.setTotalSalary(totalSalary);
          resultTarget.setLevel(teamPolicy.getLevel());
          resultTarget.setSatisfyLevel(Boolean.TRUE);
          resultTarget.setPropsRewards(teamPolicy.getPropsRewards());
          resultTarget.setPolicyType(policy.getPolicyType());
          return resultTarget;
        }
      }
      return resultTarget;
    }).filter(Objects::nonNull).collect(Collectors.toList());
  }


  public static Integer getCalcBillBelong() {
    LocalDate now = ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
    return calculateCurrentBillBelong(now);
  }

  /**
   * 计算当前账期的 billBelong
   * 规则：
   * - 1-15号：当前账期是本月1号（20251001）
   * - 16-月末：当前账期是本月16号（20251016）
   */
  private static Integer calculateCurrentBillBelong(LocalDate now) {
    int day = now.getDayOfMonth();
    LocalDate billDate;

    if (day < 16) {
      // 当前是上半月，账期开始日期是本月1号
      billDate = now.withDayOfMonth(1);
    } else {
      // 当前是下半月，账期开始日期是本月16号
      billDate = now.withDayOfMonth(16);
    }

    return Integer.parseInt(billDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
  }

  /**
   * 解析 billBelong 为日期范围.
   * 兼容两种格式：
   * 1. 旧格式（6位）：202510 表示整月 (2025年10月)
   * 2. 新格式（8位）：20251001 或 20251016 表示半月周期
   *
   * @param billBelong 账单归属
   * @return 日期范围数组 [startDate, endDate]，格式：yyyy.MM.dd
   */
  public static String[] parseBillBelongToDateRange(Integer billBelong) {
    if (billBelong == null) {
      return new String[]{"", ""};
    }

    String billBelongStr = String.valueOf(billBelong);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd");

    // 判断是旧格式（6位）还是新格式（8位）
    if (billBelongStr.length() == 6) {
      // 旧格式：202510 表示整月
      int year = Integer.parseInt(billBelongStr.substring(0, 4));
      int month = Integer.parseInt(billBelongStr.substring(4, 6));

      YearMonth yearMonth = YearMonth.of(year, month);
      LocalDate startDate = yearMonth.atDay(1);
      LocalDate endDate = yearMonth.atEndOfMonth();

      return new String[]{
          startDate.format(formatter),
          endDate.format(formatter)
      };
    } else if (billBelongStr.length() == 8) {
      // 新格式：20251001 或 20251016 表示半月周期
      int year = Integer.parseInt(billBelongStr.substring(0, 4));
      int month = Integer.parseInt(billBelongStr.substring(4, 6));
      int day = Integer.parseInt(billBelongStr.substring(6, 8));

      LocalDate startDate = LocalDate.of(year, month, day);
      LocalDate endDate;

      if (day == 1) {
        // 1-15号的账单周期
        endDate = LocalDate.of(year, month, 15);
      } else {
        // 16-月末的账单周期
        endDate = startDate.withDayOfMonth(startDate.lengthOfMonth());
      }

      return new String[]{
          startDate.format(formatter),
          endDate.format(formatter)
      };
    } else {
      // 格式不正确，返回空字符串
      return new String[]{"", ""};
    }
  }

  public static String parseBillBelongToDateRangeStr(Integer billBelong) {
    String[] strings = parseBillBelongToDateRange(billBelong);
    return strings[0] + "-" + strings[1];
  }

}
