import Decimal from 'decimal.js';
import { ContributionAmount } from '../value-objects/contribution-amount.vo';
import { DistributionRate } from '../value-objects/distribution-rate.vo';
import { ContributionAccountAggregate, ContributionSourceType } from '../aggregates/contribution-account.aggregate';
import { ContributionRecordAggregate } from '../aggregates/contribution-record.aggregate';
import { SyncedAdoption, SyncedReferral } from '../repositories/synced-data.repository.interface';

/**
 * 系统账户贡献值分配
 */
export interface SystemContributionAllocation {
  accountType: 'OPERATION' | 'PROVINCE' | 'CITY' | 'HEADQUARTERS';
  regionCode: string | null;  // 省市代码，如 440000、440100
  rate: DistributionRate;
  amount: ContributionAmount;
}

/**
 * 算力分配结果
 */
export interface ContributionDistributionResult {
  // 个人贡献值记录
  personalRecord: ContributionRecordAggregate;

  // 团队层级贡献值记录（给上线们的）
  teamLevelRecords: ContributionRecordAggregate[];

  // 团队额外奖励贡献值记录（给认种人自己的）
  teamBonusRecords: ContributionRecordAggregate[];

  // 未分配的贡献值（归总部）
  unallocatedContributions: {
    type: string;
    wouldBeAccountSequence: string | null;
    levelDepth: number | null;
    amount: ContributionAmount;
    reason: string;
  }[];

  // 系统账户贡献值（支持按省市细分）
  systemContributions: SystemContributionAllocation[];
}

/**
 * 贡献值计算领域服务
 * 负责核心的算力计算逻辑
 */
export class ContributionCalculatorService {
  // 贡献值有效期：2年
  private static readonly CONTRIBUTION_VALIDITY_YEARS = 2;

  /**
   * 计算认种产生的贡献值分配
   *
   * @param adoption 认种记录
   * @param adopterAccount 认种人的算力账户（用于判断 TEAM_BONUS 解锁状态）
   * @param ancestorChain 上线链条（从直接上线开始，最多15级）
   * @param ancestorAccounts 上线的算力账户（用于判断 TEAM_LEVEL 解锁状态）
   * @returns 分配结果
   */
  calculateAdoptionContribution(
    adoption: SyncedAdoption,
    adopterAccount: ContributionAccountAggregate | null,
    ancestorChain: SyncedReferral[],
    ancestorAccounts: Map<string, ContributionAccountAggregate>,
  ): ContributionDistributionResult {
    const baseContribution = new ContributionAmount(adoption.contributionPerTree);
    const treeCount = adoption.treeCount;
    const totalContribution = baseContribution.multiply(treeCount);

    // 计算生效日期（次日）和过期日期（2年后）
    const effectiveDate = this.getNextDay(adoption.adoptionDate);
    const expireDate = this.addYears(effectiveDate, ContributionCalculatorService.CONTRIBUTION_VALIDITY_YEARS);

    const result: ContributionDistributionResult = {
      personalRecord: null as any,
      teamLevelRecords: [],
      teamBonusRecords: [],
      unallocatedContributions: [],
      systemContributions: [],
    };

    // 1. 个人贡献值 (70%)
    result.personalRecord = ContributionRecordAggregate.createPersonal({
      accountSequence: adoption.accountSequence,
      sourceAdoptionId: adoption.originalAdoptionId,
      treeCount,
      baseContribution,
      effectiveDate,
      expireDate,
    });

    // 2. 系统账户贡献值 (15%)
    // 运营账户（全国）- 12%
    result.systemContributions.push({
      accountType: 'OPERATION',
      regionCode: null,
      rate: DistributionRate.OPERATION,
      amount: totalContribution.multiply(DistributionRate.OPERATION.value),
    });

    // 省公司账户 - 1%（按认种选择的省份）
    const provinceCode = adoption.selectedProvince;
    result.systemContributions.push({
      accountType: 'PROVINCE',
      regionCode: provinceCode || null,
      rate: DistributionRate.PROVINCE,
      amount: totalContribution.multiply(DistributionRate.PROVINCE.value),
    });

    // 市公司账户 - 2%（按认种选择的城市）
    const cityCode = adoption.selectedCity;
    result.systemContributions.push({
      accountType: 'CITY',
      regionCode: cityCode || null,
      rate: DistributionRate.CITY,
      amount: totalContribution.multiply(DistributionRate.CITY.value),
    });

    // 3. 团队贡献值 (15%)
    this.distributeTeamContribution(
      adoption,
      adopterAccount,
      baseContribution,
      treeCount,
      ancestorChain,
      ancestorAccounts,
      effectiveDate,
      expireDate,
      result,
    );

    return result;
  }

  /**
   * 分配团队贡献值
   */
  private distributeTeamContribution(
    adoption: SyncedAdoption,
    adopterAccount: ContributionAccountAggregate | null,
    baseContribution: ContributionAmount,
    treeCount: number,
    ancestorChain: SyncedReferral[],
    ancestorAccounts: Map<string, ContributionAccountAggregate>,
    effectiveDate: Date,
    expireDate: Date,
    result: ContributionDistributionResult,
  ): void {
    // 3.1 层级部分 (7.5% = 0.5% × 15级)
    for (let level = 1; level <= 15; level++) {
      const ancestor = ancestorChain[level - 1];

      if (!ancestor) {
        // 没有这一级的上线，归总部
        const levelAmount = baseContribution.multiply(treeCount).multiply(DistributionRate.LEVEL_PER.value);
        result.unallocatedContributions.push({
          type: 'LEVEL_NO_ANCESTOR',
          wouldBeAccountSequence: null,
          levelDepth: level,
          amount: levelAmount,
          reason: `第${level}级无上线`,
        });
        continue;
      }

      const ancestorAccount = ancestorAccounts.get(ancestor.accountSequence);
      const unlockedLevelDepth = ancestorAccount?.unlockedLevelDepth ?? 0;

      if (unlockedLevelDepth >= level) {
        // 上线已解锁该级别
        result.teamLevelRecords.push(
          ContributionRecordAggregate.createTeamLevel({
            accountSequence: ancestor.accountSequence,
            sourceAdoptionId: adoption.originalAdoptionId,
            sourceAccountSequence: adoption.accountSequence,
            treeCount,
            baseContribution,
            levelDepth: level,
            effectiveDate,
            expireDate,
          }),
        );
      } else {
        // 上线未解锁该级别，归总部
        const levelAmount = baseContribution.multiply(treeCount).multiply(DistributionRate.LEVEL_PER.value);
        result.unallocatedContributions.push({
          type: 'LEVEL_OVERFLOW',
          wouldBeAccountSequence: ancestor.accountSequence,
          levelDepth: level,
          amount: levelAmount,
          reason: `上线${ancestor.accountSequence}未解锁第${level}级（已解锁${unlockedLevelDepth}级）`,
        });
      }
    }

    // 3.2 额外奖励部分 (7.5% = 2.5% × 3档) - 给认种人自己
    // T1: 自己认种即解锁（无条件，当前正在认种所以一定解锁）
    // T2: 直推≥2人认种解锁
    // T3: 直推≥4人认种解锁
    const directReferralAdoptedCount = adopterAccount?.directReferralAdoptedCount ?? 0;

    // T1 始终解锁（因为当前正在认种）
    // T2 需要直推≥2人认种
    // T3 需要直推≥4人认种
    const effectiveUnlockedBonusTiers = this.calculateUnlockedBonusTiers(true, directReferralAdoptedCount);

    for (let tier = 1; tier <= 3; tier++) {
      if (effectiveUnlockedBonusTiers >= tier) {
        // 认种人已解锁该档位，给认种人自己
        result.teamBonusRecords.push(
          ContributionRecordAggregate.createTeamBonus({
            accountSequence: adoption.accountSequence,
            sourceAdoptionId: adoption.originalAdoptionId,
            sourceAccountSequence: adoption.accountSequence,
            treeCount,
            baseContribution,
            bonusTier: tier,
            effectiveDate,
            expireDate,
          }),
        );
      } else {
        // 认种人未解锁该档位，归总部（冻结/待领取）
        const bonusAmount = baseContribution.multiply(treeCount).multiply(DistributionRate.BONUS_PER.value);
        result.unallocatedContributions.push({
          type: `BONUS_TIER_${tier}`,
          wouldBeAccountSequence: adoption.accountSequence,
          levelDepth: null,
          amount: bonusAmount,
          reason: `认种人${adoption.accountSequence}未解锁第${tier}档奖励（需直推${tier === 2 ? '2人' : '4人'}认种）`,
        });
      }
    }
  }

  /**
   * 根据直推认种用户数计算解锁层级
   */
  calculateUnlockedLevelDepth(directReferralAdoptedCount: number): number {
    if (directReferralAdoptedCount >= 5) return 15;
    if (directReferralAdoptedCount >= 3) return 10;
    if (directReferralAdoptedCount >= 1) return 5;
    return 0;
  }

  /**
   * 根据条件计算解锁的额外奖励档位数
   */
  calculateUnlockedBonusTiers(hasAdopted: boolean, directReferralAdoptedCount: number): number {
    let tiers = 0;
    if (hasAdopted) tiers++;
    if (directReferralAdoptedCount >= 2) tiers++;
    if (directReferralAdoptedCount >= 4) tiers++;
    return tiers;
  }

  /**
   * 获取次日日期
   */
  private getNextDay(date: Date): Date {
    const nextDay = new Date(date);
    nextDay.setDate(nextDay.getDate() + 1);
    nextDay.setHours(0, 0, 0, 0);
    return nextDay;
  }

  /**
   * 添加年数
   */
  private addYears(date: Date, years: number): Date {
    const result = new Date(date);
    result.setFullYear(result.getFullYear() + years);
    return result;
  }
}
