package com.red.circle.common.business.core.level;

import com.red.circle.tool.core.num.NumConstant;
import com.red.circle.tool.core.num.NumUtils;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;

/**
 * 等级计算.
 *
 * @author pengliang on 2021/12/14
 */
@Slf4j
public class LevelCalculation {

  private final Long goldLowPrice;
  private final Integer levelSpacing;

  public LevelCalculation(final long goldLowPrice) {
    this.goldLowPrice = goldLowPrice;
    this.levelSpacing = 10;
  }

  public static void main(String[] args) {
    LevelCalculation levelCalculation = new LevelCalculation(1000);
    // 测试新版等级计算
    System.out.println("\n=== 新版等级计算测试 ===");
    levelCalculation.testNewLevelCalculation();
  }
  
  /**
   * 测试新版等级计算方法
   */
  public void testNewLevelCalculation() {
    // 测试用户等级计算
    System.out.println("=== 用户等级测试 ===");
    Long[] testGolds = {0L, 2500L, 7500L, 1090650L, 2520000L};
    
    for (Long gold : testGolds) {
      UserLevelExperience result = getLevelV2(gold);
      log.info("消费金币: {}, 当前用户等级: {}, 当前经验: {}, 下一级还需: {}", 
               gold, result.getLevel(), result.getThatExperience(), result.getNextExperience());
    }

    // 测试财富等级计算
    System.out.println("\n=== 财富等级测试 ===");
    Long[] testWealthGolds = {0L, 10000L, 243450L, 1370000L, 6820000L};
    
    for (Long gold : testWealthGolds) {
      UserLevelExperience result = getWealthLevel(gold);
      log.info("消费金币: {}, 当前财富等级: {}, 当前经验: {}, 下一级还需: {}", 
               gold, result.getLevel(), result.getThatExperience(), result.getNextExperience());
    }
  }

  public UserLevelExperience getLevel(Long experience) {
    return calculationLevel(experience);
  }

  /**
   * 新版等级计算方法 - 基于新的用户等级配置
   */
  public UserLevelExperience getLevelV2(Long experience) {
    return calculationLevelV2(experience, NewLevelConfigEnums.values());
  }

  /**
   * 财富等级计算方法
   */
  public UserLevelExperience getWealthLevel(Long experience) {
    return calculationLevelV2(experience, WealthLevelConfigEnums.values());
  }

  private UserLevelExperience calculationLevel(Long consumeGold) {
    if (Objects.isNull(consumeGold)) {
      return getLevelOneToTen(0L);
    }
    if (consumeGold <= WealthCharismaLevelEnums.one_TO_ten.getConsumeGold(goldLowPrice)) {
      return getLevelOneToTen(consumeGold);
    }

    WealthCharismaLevelEnums[] wealthCharismaLevels = WealthCharismaLevelEnums.values();
    int len = wealthCharismaLevels.length;
    for (int index = 1; index < len; index++) {
      WealthCharismaLevelEnums perv = wealthCharismaLevels[index - 1];
      WealthCharismaLevelEnums that = wealthCharismaLevels[index];
      if (consumeGold > that.getConsumeGold(goldLowPrice)) {
        continue;
      }
      long stepExperience = (that.getConsumeGold(goldLowPrice) - perv.getConsumeGold(goldLowPrice)) / levelSpacing;
      for (int levelIndex = 1; levelIndex <= NumConstant.TEN; levelIndex++) {
        long upgradeExperience = perv.getConsumeGold(goldLowPrice) + (stepExperience * levelIndex);
        int nextLevel = perv.getEndLevel() + levelIndex;

        if (Objects.equals(consumeGold, upgradeExperience)) {
          if (index == len - 1 && levelIndex == NumConstant.TEN) {
            return getBuildUserLevelExperience(nextLevel, consumeGold, consumeGold);
          }
          return getBuildUserLevelExperience(nextLevel, consumeGold, levelIndex == NumConstant.TEN
                  ? (wealthCharismaLevels[index + 1].getConsumeGold(goldLowPrice) - that.getConsumeGold(goldLowPrice)) / levelSpacing
                  : stepExperience);
        }

        if (consumeGold < upgradeExperience) {
          return getBuildUserLevelExperience(nextLevel - 1, consumeGold, upgradeExperience - consumeGold);
        }
      }
    }
    throw new IllegalArgumentException("getLevelOneToTen param error:" + consumeGold);
  }

  /**
   * 通用等级计算逻辑 - 基于累积经验值查找等级
   * @param consumeGold 消费金额
   * @param configs 等级配置枚举数组
   */
  private UserLevelExperience calculationLevelV2(Long consumeGold, LevelConfig[] configs) {
    if (Objects.isNull(consumeGold) || consumeGold <= 0) {
      // 没有消费，返回1级，距离2级还需要的经验
      long nextLevelGold = configs[0].getCumulativeExperience();
      return getBuildUserLevelExperience(1, 0L, nextLevelGold);
    }

    // 遍历等级配置
    for (int i = 0; i < configs.length; i++) {
      LevelConfig config = configs[i];
      long cumulativeGold = config.getCumulativeExperience();
      
      if (consumeGold <= cumulativeGold) {
        // 找到对应等级
        int currentLevel = config.getToLevel();
        
        if (consumeGold == cumulativeGold) {
          // 正好达到某一级
          if (i == configs.length - 1) {
            // 已经是最高级
            return getBuildUserLevelExperience(currentLevel, consumeGold, 0L);
          } else {
            // 计算到下一级还需要的经验
            long nextLevelGold = configs[i + 1].getCumulativeExperience();
            long needGold = nextLevelGold - cumulativeGold;
            return getBuildUserLevelExperience(currentLevel, consumeGold, needGold);
          }
        } else {
          // 在当前级别，但未达到下一级
          long needGold = cumulativeGold - consumeGold;
          return getBuildUserLevelExperience(currentLevel - 1, consumeGold, needGold);
        }
      }
    }
    
    // 如果超过最高级配置，返回最高级
    LevelConfig maxConfig = configs[configs.length - 1];
    return getBuildUserLevelExperience(maxConfig.getToLevel(), consumeGold, 0L);
  }

  private UserLevelExperience getLevelOneToTen(Long consumeGold) {
    Long[] experiences = {1L, 5L, 10L, 20L, 30L, 40L, 50L, 60L, 80L, 100L};
    for (int index = 0; index < experiences.length; index++) {
      Long levelExperienceGold = experiences[index] * goldLowPrice;
      if (Objects.equals(consumeGold, levelExperienceGold)) {
        return getBuildUserLevelExperience(index + 1,
                consumeGold, index == experiences.length - 1
                        ? (WealthCharismaLevelEnums.eleven_TO_twenty.getConsumeGold(goldLowPrice) - experiences[experiences.length - 1]) / levelSpacing
                        : experiences[index + 1] * goldLowPrice - consumeGold);
      }
      if (consumeGold < levelExperienceGold) {
        return getBuildUserLevelExperience(index, consumeGold, levelExperienceGold - consumeGold);
      }
    }
    throw new IllegalArgumentException("getLevelOneToTen param error:" + consumeGold);
  }

  private static UserLevelExperience getBuildUserLevelExperience(int nextLevel, long thatExperience, long nextExperience) {
    return new UserLevelExperience()
        .setLevel(nextLevel)
        .setThatExperience(thatExperience)
        .setThatExperienceFormat(NumUtils.formatLong(thatExperience))
        .setNextExperience(nextExperience)
        .setNextExperienceFormat(NumUtils.formatLong(nextExperience));
  }

  /**
   * 等级配置接口 - 抽象公共逻辑
   */
  interface LevelConfig {
    int getToLevel();
    long getCumulativeExperience();
  }

  /**
   * l~10=1, 5, 10, 20, 30, 40, 50, 60, 80, 100 other=(prev$-thisRange$)/10
   */
  enum WealthCharismaLevelEnums {
    /**
     * 1~10=$100
     */
    one_TO_ten(1, 10, 100),
    /**
     * 11~20=$500
     */
    eleven_TO_twenty(11, 20, 500),
    /**
     * 21~30=$1500
     */
    twenty_one_TO_thirty(21, 30, 1500),
    /**
     * 31~40=$3000
     */
    thirty_one_TO_forty(31, 40, 3000),
    /**
     * 41~50=6000
     */
    forty_one_TO_fifty(41, 50, 6000),
    /**
     * 51~60=10000
     */
    fifty_one_TO_sixty(51, 60, 10000),
    /**
     * 61~70=20000
     */
    sixty_one_TO_seventy(61, 70, 20000),
    /**
     * 71~80=50000
     */
    seventy_one_TO_eighty(71, 80, 50000),
    /**
     * 81~90=100000
     */
    eighty_one_TO_ninety(81, 90, 100000),
    /**
     * 91~100=200000
     */
    ninety_one_TO_one_hundred(91, 100, 200000),
    /**
     * 101~110=400000
     */
    one_hundred_and_one_TO_one_hundred_and_ten(101, 110, 400000),
    /**
     * 111~120=700000
     */
    one_hundred_and_ten_TO_one_hundred_and_twenty(111, 120, 700000),
    /**
     * 121~130=1200000
     */
    one_hundred_and_ten_TO_one_hundred_and_thirty(121, 130, 1200000),
    /**
     * 131~140=2000000
     */
    one_hundred_and_ten_TO_one_hundred_and_forty(131, 140, 2000000),
    /**
     * 141~150=4000000
     */
    one_hundred_and_ten_TO_one_hundred_and_fifty(141, 150, 400000000),
    ;


    private final int startLevel;
    private final int endLevel;
    private final long consumeGold;

    WealthCharismaLevelEnums(int startLevel, int endLevel, long consumeGold) {
      this.startLevel = startLevel;
      this.endLevel = endLevel;
      this.consumeGold = consumeGold;
    }

    public int getStartLevel() {
      return startLevel;
    }

    public int getEndLevel() {
      return endLevel;
    }

    public long getConsumeGold(Long goldLowPrice) {
      return consumeGold * goldLowPrice;
    }
  }

  /**
   * 新版用户等级配置枚举 - 基于累积经验值
   * 每个枚举项表示达到某个等级所需的累积经验值
   */
  enum NewLevelConfigEnums implements LevelConfig {
    LEVEL_1_TO_2(2, 2500),
    LEVEL_2_TO_3(3, 7500),
    LEVEL_3_TO_4(4, 15000),
    LEVEL_4_TO_5(5, 30000),
    LEVEL_5_TO_6(6, 60000),
    LEVEL_6_TO_7(7, 110000),
    LEVEL_7_TO_8(8, 200000),
    LEVEL_8_TO_9(9, 330000),
    LEVEL_9_TO_10(10, 530000),
    LEVEL_10_TO_11(11, 780000),
    LEVEL_11_TO_12(12, 1080000),
    LEVEL_12_TO_13(13, 1450000),
    LEVEL_13_TO_14(14, 1920000),
    LEVEL_14_TO_15(15, 2520000),
    LEVEL_15_TO_16(16, 3270000),
    LEVEL_16_TO_17(17, 4170000),
    LEVEL_17_TO_18(18, 5270000),
    LEVEL_18_TO_19(19, 6620000),
    LEVEL_19_TO_20(20, 8120000),
    LEVEL_20_TO_21(21, 9820000),
    LEVEL_21_TO_22(22, 11820000),
    LEVEL_22_TO_23(23, 14220000),
    LEVEL_23_TO_24(24, 17120000),
    LEVEL_24_TO_25(25, 20620000),
    LEVEL_25_TO_26(26, 24820000),
    LEVEL_26_TO_27(27, 29820000),
    LEVEL_27_TO_28(28, 35720000),
    LEVEL_28_TO_29(29, 42620000),
    LEVEL_29_TO_30(30, 50620000),
    LEVEL_30_TO_31(31, 60120000),
    LEVEL_31_TO_32(32, 71120000),
    LEVEL_32_TO_33(33, 84120000),
    LEVEL_33_TO_34(34, 99120000),
    LEVEL_34_TO_35(35, 119120000),
    LEVEL_35_TO_36(36, 142120000),
    LEVEL_36_TO_37(37, 167120000),
    LEVEL_37_TO_38(38, 194120000),
    LEVEL_38_TO_39(39, 223120000),
    LEVEL_39_TO_40(40, 263120000),
    LEVEL_40_TO_41(41, 308120000),
    LEVEL_41_TO_42(42, 363120000),
    LEVEL_42_TO_43(43, 428520000),
    LEVEL_43_TO_44(44, 503520000),
    LEVEL_44_TO_45(45, 603520000),
    LEVEL_45_TO_46(46, 753520000),
    LEVEL_46_TO_47(47, 1003520000),
    LEVEL_47_TO_48(48, 1353520000),
    LEVEL_48_TO_49(49, 1803520000L),
    LEVEL_49_TO_50(50, 2403520000L);

    private final int toLevel;
    private final long cumulativeExperience;

    NewLevelConfigEnums(int toLevel, long cumulativeExperience) {
      this.toLevel = toLevel;
      this.cumulativeExperience = cumulativeExperience;
    }

    public int getToLevel() {
      return toLevel;
    }

    public long getCumulativeExperience() {
      return cumulativeExperience;
    }

    /**
     * @deprecated 新版本不需要乘以goldLowPrice，直接使用getCumulativeExperience()
     */
    @Deprecated
    public long getCumulativeGold(Long goldLowPrice) {
      return cumulativeExperience;
    }
  }

  /**
   * 财富等级配置枚举 - 基于累积经验值
   */
  enum WealthLevelConfigEnums implements LevelConfig {
    WEALTH_1_TO_2(2, 10000),
    WEALTH_2_TO_3(3, 30000),
    WEALTH_3_TO_4(4, 60000),
    WEALTH_4_TO_5(5, 100000),
    WEALTH_5_TO_6(6, 150000),
    WEALTH_6_TO_7(7, 220000),
    WEALTH_7_TO_8(8, 310000),
    WEALTH_8_TO_9(9, 420000),
    WEALTH_9_TO_10(10, 540000),
    WEALTH_10_TO_11(11, 670000),
    WEALTH_11_TO_12(12, 810000),
    WEALTH_12_TO_13(13, 960000),
    WEALTH_13_TO_14(14, 1120000),
    WEALTH_14_TO_15(15, 1370000),
    WEALTH_15_TO_16(16, 1640000),
    WEALTH_16_TO_17(17, 1930000),
    WEALTH_17_TO_18(18, 2240000),
    WEALTH_18_TO_19(19, 2570000),
    WEALTH_19_TO_20(20, 3120000),
    WEALTH_20_TO_21(21, 3720000),
    WEALTH_21_TO_22(22, 4370000),
    WEALTH_22_TO_23(23, 5070000),
    WEALTH_23_TO_24(24, 5820000),
    WEALTH_24_TO_25(25, 6820000),
    WEALTH_25_TO_26(26, 7920000),
    WEALTH_26_TO_27(27, 9120000),
    WEALTH_27_TO_28(28, 10420000),
    WEALTH_28_TO_29(29, 11820000),
    WEALTH_29_TO_30(30, 13370000),
    WEALTH_30_TO_31(31, 15020000),
    WEALTH_31_TO_32(32, 16770000),
    WEALTH_32_TO_33(33, 18670000),
    WEALTH_33_TO_34(34, 21170000),
    WEALTH_34_TO_35(35, 24370000),
    WEALTH_35_TO_36(36, 28370000),
    WEALTH_36_TO_37(37, 33370000),
    WEALTH_37_TO_38(38, 40370000),
    WEALTH_38_TO_39(39, 50370000),
    WEALTH_39_TO_40(40, 65370000),
    WEALTH_40_TO_41(41, 88370000),
    WEALTH_41_TO_42(42, 123370000),
    WEALTH_42_TO_43(43, 173370000),
    WEALTH_43_TO_44(44, 243370000),
    WEALTH_44_TO_45(45, 343370000),
    WEALTH_45_TO_46(46, 493370000),
    WEALTH_46_TO_47(47, 743370000),
    WEALTH_47_TO_48(48, 1113370000),
    WEALTH_48_TO_49(49, 1613370000L),
    WEALTH_49_TO_50(50, 2513370000L);

    private final int toLevel;
    private final long cumulativeExperience;

    WealthLevelConfigEnums(int toLevel, long cumulativeExperience) {
      this.toLevel = toLevel;
      this.cumulativeExperience = cumulativeExperience;
    }

    public int getToLevel() {
      return toLevel;
    }

    public long getCumulativeExperience() {
      return cumulativeExperience;
    }
  }
}
