import { Injectable, Logger } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import {
  PRE_PLANTING_RIGHT_AMOUNTS,
  PrePlantingRightType,
  SYSTEM_ACCOUNTS,
} from '../../domain/value-objects/pre-planting-right-amounts';
import { PrePlantingRewardStatus } from '../../domain/value-objects/pre-planting-reward-status.enum';
import {
  PrePlantingRewardEntryRepository,
  PrePlantingRewardEntryData,
} from '../../infrastructure/repositories/pre-planting-reward-entry.repository';
import { PrePlantingReferralClient } from '../../infrastructure/external/pre-planting-referral.client';
import { PrePlantingAuthorizationClient } from '../../infrastructure/external/pre-planting-authorization.client';
import { WalletServiceClient } from '../../../infrastructure/external/wallet-service.client';

export interface RewardAllocation {
  recipientAccountSequence: string;
  rightType: PrePlantingRightType;
  amount: number;
  memo: string;
  rewardStatus: PrePlantingRewardStatus;
}

@Injectable()
export class PrePlantingRewardService {
  private readonly logger = new Logger(PrePlantingRewardService.name);

  constructor(
    private readonly rewardEntryRepo: PrePlantingRewardEntryRepository,
    private readonly referralClient: PrePlantingReferralClient,
    private readonly authorizationClient: PrePlantingAuthorizationClient,
    private readonly walletClient: WalletServiceClient,
  ) {}

  /**
   * Step 3-4: 计算分配对象 + 事务内持久化分配记录
   *
   * 返回 allocations 供事务提交后执行转账（不在事务内做 HTTP 调用）
   */
  /**
   * @param portionSupplement 总部运营成本压力涨价（每份加价金额），默认 0 不影响现有逻辑
   */
  async prepareAndPersistRewards(
    tx: Prisma.TransactionClient,
    orderNo: string,
    accountSequence: string,
    provinceCode: string,
    cityCode: string,
    portionCount: number,
    portionSupplement: number = 0,
  ): Promise<RewardAllocation[]> {
    this.logger.log(
      `[PRE-PLANTING] Preparing rewards for order ${orderNo}, ` +
      `${portionCount} portion(s), province=${provinceCode}, city=${cityCode}, supplement=${portionSupplement}`,
    );

    // Step 3: 确定所有分配对象
    const allocations = await this.resolveAllocations(
      accountSequence,
      provinceCode,
      cityCode,
      portionCount,
      portionSupplement,
    );

    // Step 4: 在事务内持久化分配记录
    const entries: PrePlantingRewardEntryData[] = allocations.map((a) => ({
      sourceOrderNo: orderNo,
      sourceAccountSequence: accountSequence,
      recipientAccountSequence: a.recipientAccountSequence,
      rightType: a.rightType,
      usdtAmount: a.amount,
      rewardStatus: a.rewardStatus,
      memo: a.memo,
    }));

    await this.rewardEntryRepo.saveMany(tx, entries);

    this.logger.log(
      `[PRE-PLANTING] Rewards persisted: ${allocations.length} allocations for order ${orderNo}`,
    );

    return allocations;
  }

  /**
   * Step 5: 事务提交后执行资金转账（HTTP 调用 wallet-service）
   *
   * [2026-02-28] 修复：与正常认种对齐
   * - 使用正确的 FundAllocationItem 格式（targetType/targetId/allocationType）
   * - metadata 包含完整信息（rightType, sourceOrderNo, sourceAccountSequence,
   *   treeCount, provinceCode, cityCode, memo），与正常认种 reward-service 一致
   * - metadata.source = 'PRE_PLANTING' 供 wallet-service 添加 [预种] 前缀
   *
   * SHARE_RIGHT 的 PENDING/SETTLEABLE 判断：
   *   预种侧不做 hasPlanted 判断，全部作为 SETTLED 发送给 wallet-service。
   *   wallet-service.allocateToUserWallet() 内部会查询收款方钱包的 hasPlanted 字段：
   *   - hasPlanted=true → 直接 SETTLEABLE（进可结算余额）
   *   - hasPlanted=false → 创建 pending_rewards（24h 过期归总部 S0000000001）
   *   这与正常认种的链路完全一致（reward-service → wallet-service 的同一段代码）。
   */
  async executeAllocations(
    orderNo: string,
    allocations: RewardAllocation[],
    sourceAccountSequence: string,
    treeCount: number,
    provinceCode: string,
    cityCode: string,
  ): Promise<void> {
    const settledAllocations = allocations.filter(
      (a) => a.rewardStatus === PrePlantingRewardStatus.SETTLED,
    );

    await this.walletClient.allocatePrePlantingFunds({
      orderId: orderNo,
      allocations: settledAllocations.map((a) => ({
        targetType: a.recipientAccountSequence.startsWith('S') ? 'SYSTEM' : 'USER',
        targetId: a.recipientAccountSequence,
        allocationType: a.rightType,
        amount: a.amount,
        metadata: {
          source: 'PRE_PLANTING',
          rightType: a.rightType,
          sourceOrderNo: orderNo,
          sourceAccountSequence,
          treeCount,
          provinceCode,
          cityCode,
          memo: a.memo,
        },
      })),
    });

    this.logger.log(
      `[PRE-PLANTING] Funds allocated: ${settledAllocations.length} transfers for order ${orderNo}`,
    );
  }

  /**
   * 确定 10 类权益分配对象 + 涨价补充（如有）
   * @param portionSupplement 总部运营成本压力涨价（每份加价金额），默认 0
   */
  private async resolveAllocations(
    accountSequence: string,
    provinceCode: string,
    cityCode: string,
    portionCount: number,
    portionSupplement: number = 0,
  ): Promise<RewardAllocation[]> {
    const allocations: RewardAllocation[] = [];
    const multiplier = portionCount;

    // [2026-03-01] 标准化省市代码为 6 位格式
    // 预种 DTO 接收前端传入的短格式（省 2 位如 "44"，市 4 位如 "4401"），
    // 但 authorization-service 查询和系统账户编号都需要 6 位格式（"440000"/"440100"）。
    // 正常认种 SelectProvinceCityDto 直接接收 6 位格式，故不存在此问题。
    const stdProvinceCode = provinceCode.length < 6
      ? provinceCode.padEnd(6, '0')
      : provinceCode;
    const stdCityCode = cityCode.length < 6
      ? cityCode.padEnd(6, '0')
      : cityCode;

    // ===== 4 类系统费用（硬编码，无需查询） =====
    allocations.push({
      recipientAccountSequence: SYSTEM_ACCOUNTS.COST,
      rightType: PrePlantingRightType.COST_FEE,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.COST_FEE * multiplier,
      memo: '预种成本费',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    allocations.push({
      recipientAccountSequence: SYSTEM_ACCOUNTS.OPERATION,
      rightType: PrePlantingRightType.OPERATION_FEE,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.OPERATION_FEE * multiplier,
      memo: '预种运营费',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    allocations.push({
      recipientAccountSequence: SYSTEM_ACCOUNTS.HEADQUARTERS,
      rightType: PrePlantingRightType.HEADQUARTERS_BASE_FEE,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.HEADQUARTERS_BASE_FEE * multiplier,
      memo: '预种总部社区费',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    allocations.push({
      recipientAccountSequence: SYSTEM_ACCOUNTS.RWAD_POOL,
      rightType: PrePlantingRightType.RWAD_POOL_INJECTION,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.RWAD_POOL_INJECTION * multiplier,
      memo: '预种RWAD底池注入',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    // ===== 6 类用户权益（需要查询各服务 API） =====
    // 并行查询推荐人和授权信息
    const [
      referralInfo,
      communityResult,
      provinceAreaResult,
      provinceTeamResult,
      cityAreaResult,
      cityTeamResult,
    ] = await Promise.all([
      this.referralClient.getReferralChain(accountSequence),
      this.authorizationClient.getCommunityDistribution(accountSequence),
      this.authorizationClient.getProvinceAreaDistribution(stdProvinceCode),
      this.authorizationClient.getProvinceTeamDistribution(accountSequence, stdProvinceCode),
      this.authorizationClient.getCityAreaDistribution(stdCityCode),
      this.authorizationClient.getCityTeamDistribution(accountSequence, stdCityCode),
    ]);

    // 推荐奖励 (SHARE_RIGHT)
    // 预种侧只确定收款人（推荐人 or S0000000005），全部标记 SETTLED 发给 wallet-service。
    // wallet-service.allocateToUserWallet() 会根据收款方 hasPlanted 自动决定：
    //   已种 → SETTLEABLE（立即可结算）
    //   未种 → PENDING（24h，过期归总部 S0000000001）
    // 与正常认种走同一套 wallet-service 代码，无需预种侧额外判断。
    const referrer = referralInfo.directReferrer;
    if (referrer) {
      allocations.push({
        recipientAccountSequence: referrer.accountSequence,
        rightType: PrePlantingRightType.SHARE_RIGHT,
        amount: PRE_PLANTING_RIGHT_AMOUNTS.SHARE_RIGHT * multiplier,
        memo: '预种推荐奖励',
        rewardStatus: PrePlantingRewardStatus.SETTLED,
      });
    } else {
      allocations.push({
        recipientAccountSequence: SYSTEM_ACCOUNTS.SHARE_RIGHT_POOL,
        rightType: PrePlantingRightType.SHARE_RIGHT,
        amount: PRE_PLANTING_RIGHT_AMOUNTS.SHARE_RIGHT * multiplier,
        memo: '预种推荐奖励（无推荐人，归入分享权益池）',
        rewardStatus: PrePlantingRewardStatus.SETTLED,
      });
    }

    // 社区权益 (COMMUNITY_RIGHT)
    allocations.push({
      recipientAccountSequence: communityResult.recipientAccountSequence,
      rightType: PrePlantingRightType.COMMUNITY_RIGHT,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.COMMUNITY_RIGHT * multiplier,
      memo: communityResult.isFallback ? '预种社区权益（无社区，归总部）' : '预种社区权益',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    // 省区域权益 (PROVINCE_AREA_RIGHT)
    allocations.push({
      recipientAccountSequence: provinceAreaResult.recipientAccountSequence,
      rightType: PrePlantingRightType.PROVINCE_AREA_RIGHT,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.PROVINCE_AREA_RIGHT * multiplier,
      memo: provinceAreaResult.isFallback ? '预种省区域权益（系统省账户）' : '预种省区域权益',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    // 省团队权益 (PROVINCE_TEAM_RIGHT)
    allocations.push({
      recipientAccountSequence: provinceTeamResult.recipientAccountSequence,
      rightType: PrePlantingRightType.PROVINCE_TEAM_RIGHT,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.PROVINCE_TEAM_RIGHT * multiplier,
      memo: provinceTeamResult.isFallback ? '预种省团队权益（归总部）' : '预种省团队权益',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    // 市区域权益 (CITY_AREA_RIGHT)
    allocations.push({
      recipientAccountSequence: cityAreaResult.recipientAccountSequence,
      rightType: PrePlantingRightType.CITY_AREA_RIGHT,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.CITY_AREA_RIGHT * multiplier,
      memo: cityAreaResult.isFallback ? '预种市区域权益（系统市账户）' : '预种市区域权益',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    // 市团队权益 (CITY_TEAM_RIGHT)
    allocations.push({
      recipientAccountSequence: cityTeamResult.recipientAccountSequence,
      rightType: PrePlantingRightType.CITY_TEAM_RIGHT,
      amount: PRE_PLANTING_RIGHT_AMOUNTS.CITY_TEAM_RIGHT * multiplier,
      memo: cityTeamResult.isFallback ? '预种市团队权益（归总部）' : '预种市团队权益',
      rewardStatus: PrePlantingRewardStatus.SETTLED,
    });

    // [2026-02-26] 总部运营成本压力涨价：加价部分全额归总部 (S0000000001)
    if (portionSupplement > 0) {
      allocations.push({
        recipientAccountSequence: SYSTEM_ACCOUNTS.HEADQUARTERS,
        rightType: PrePlantingRightType.HQ_PRICE_SUPPLEMENT,
        amount: portionSupplement * multiplier,
        memo: '预种总部运营成本压力涨价',
        rewardStatus: PrePlantingRewardStatus.SETTLED,
      });
    }

    return allocations;
  }

}
