import { Injectable, Inject, Logger } from '@nestjs/common'
import { AuthorizationRole, MonthlyAssessment, BenefitAssessmentRecord } from '@/domain/aggregates'
import { LadderTargetRule } from '@/domain/entities'
import {
  UserId,
  AdminUserId,
  RegionCode,
  AuthorizationId,
  Month,
} from '@/domain/value-objects'
import { RoleType, AuthorizationStatus, AssessmentResult, BenefitActionType } from '@/domain/enums'
import {
  IAuthorizationRoleRepository,
  AUTHORIZATION_ROLE_REPOSITORY,
  IMonthlyAssessmentRepository,
  MONTHLY_ASSESSMENT_REPOSITORY,
  IBenefitAssessmentRecordRepository,
  BENEFIT_ASSESSMENT_RECORD_REPOSITORY,
} from '@/domain/repositories'
import {
  AuthorizationValidatorService,
  AssessmentCalculatorService,
  IReferralRepository,
  ITeamStatisticsRepository,
  TeamStatistics,
} from '@/domain/services'
import { EventPublisherService } from '@/infrastructure/kafka'
import { ReferralServiceClient, IdentityServiceClient, RewardServiceClient } from '@/infrastructure/external'
import { ApplicationError, NotFoundError } from '@/shared/exceptions'
import {
  ApplyCommunityAuthCommand,
  ApplyCommunityAuthResult,
  ApplyAuthProvinceCompanyCommand,
  ApplyAuthProvinceCompanyResult,
  ApplyAuthCityCompanyCommand,
  ApplyAuthCityCompanyResult,
  GrantCommunityCommand,
  GrantProvinceCompanyCommand,
  GrantCityCompanyCommand,
  GrantAuthProvinceCompanyCommand,
  GrantAuthCityCompanyCommand,
  RevokeAuthorizationCommand,
  GrantMonthlyBypassCommand,
  ExemptLocalPercentageCheckCommand,
  SelfApplyAuthorizationCommand,
} from '@/application/commands'
import {
  SelfApplyAuthorizationResponseDto,
  UserAuthorizationStatusResponseDto,
  SelfApplyAuthorizationType,
  TeamChainOccupiedRegionDto,
} from '@/api/dto/request/self-apply-authorization.dto'
import { AuthorizationDTO, StickmanRankingDTO, CommunityHierarchyDTO } from '@/application/dto'

export const REFERRAL_REPOSITORY = Symbol('IReferralRepository')
export const TEAM_STATISTICS_REPOSITORY = Symbol('ITeamStatisticsRepository')

@Injectable()
export class AuthorizationApplicationService {
  private readonly logger = new Logger(AuthorizationApplicationService.name)
  private readonly validatorService = new AuthorizationValidatorService()

  constructor(
    @Inject(AUTHORIZATION_ROLE_REPOSITORY)
    private readonly authorizationRepository: IAuthorizationRoleRepository,
    @Inject(MONTHLY_ASSESSMENT_REPOSITORY)
    private readonly assessmentRepository: IMonthlyAssessmentRepository,
    // [2026-01-08] 新增：权益考核记录仓储，用于保存权益有效性考核历史
    @Inject(BENEFIT_ASSESSMENT_RECORD_REPOSITORY)
    private readonly benefitAssessmentRecordRepository: IBenefitAssessmentRecordRepository,
    @Inject(REFERRAL_REPOSITORY)
    private readonly referralRepository: IReferralRepository,
    @Inject(TEAM_STATISTICS_REPOSITORY)
    private readonly statsRepository: ITeamStatisticsRepository,
    private readonly eventPublisher: EventPublisherService,
    private readonly referralServiceClient: ReferralServiceClient,
    private readonly identityServiceClient: IdentityServiceClient,
    private readonly rewardServiceClient: RewardServiceClient,
  ) {}

  /**
   * 申请社区授权
   */
  async applyCommunityAuth(
    command: ApplyCommunityAuthCommand,
  ): Promise<ApplyCommunityAuthResult> {
    const userId = UserId.create(command.userId, command.accountSequence)

    // 1. 检查是否已有社区授权
    const existing = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      userId.accountSequence,
      RoleType.COMMUNITY,
    )

    if (existing && existing.status !== AuthorizationStatus.REVOKED) {
      throw new ApplicationError('您已申请过社区授权')
    }

    // 2. 创建社区授权
    const authorization = AuthorizationRole.createCommunityAuth({
      userId,
      communityName: command.communityName,
    })

    // 3. 检查初始考核（100棵）- 使用下级团队认种数（不含自己）
    const teamStats = await this.statsRepository.findByAccountSequence(userId.accountSequence)
    const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0

    if (subordinateTreeCount >= authorization.getInitialTarget()) {
      // 达标，激活权益
      authorization.activateBenefit()
    }

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()

    return {
      authorizationId: authorization.authorizationId.value,
      status: authorization.status,
      benefitActive: authorization.benefitActive,
      message: authorization.benefitActive
        ? '社区权益已激活'
        : `需要下级团队累计认种达到${authorization.getInitialTarget()}棵才能激活`,
      currentTreeCount: subordinateTreeCount,
      requiredTreeCount: authorization.getInitialTarget(),
    }
  }

  /**
   * 申请授权省公司
   */
  async applyAuthProvinceCompany(
    command: ApplyAuthProvinceCompanyCommand,
  ): Promise<ApplyAuthProvinceCompanyResult> {
    const userId = UserId.create(command.userId, command.accountSequence)
    const regionCode = RegionCode.create(command.provinceCode)

    // 1. 验证授权申请（团队内唯一性）
    const validation = await this.validatorService.validateAuthorizationRequest(
      userId,
      RoleType.AUTH_PROVINCE_COMPANY,
      regionCode,
      this.referralRepository,
      this.authorizationRepository,
    )

    if (!validation.isValid) {
      throw new ApplicationError(validation.errorMessage!)
    }

    // 2. 创建授权
    const authorization = AuthorizationRole.createAuthProvinceCompany({
      userId,
      provinceCode: command.provinceCode,
      provinceName: command.provinceName,
    })

    // 3. 检查初始考核（500棵）- 使用下级团队认种数（不含自己）
    const teamStats = await this.statsRepository.findByAccountSequence(userId.accountSequence)
    const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0

    if (subordinateTreeCount >= authorization.getInitialTarget()) {
      // 达标，激活权益并创建首月考核
      authorization.activateBenefit()
      await this.createInitialAssessment(authorization, teamStats!)
    }

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()

    return {
      authorizationId: authorization.authorizationId.value,
      status: authorization.status,
      benefitActive: authorization.benefitActive,
      displayTitle: authorization.displayTitle,
      message: authorization.benefitActive
        ? '授权省公司权益已激活，开始阶梯考核'
        : `需要下级团队累计认种达到${authorization.getInitialTarget()}棵才能激活`,
      currentTreeCount: subordinateTreeCount,
      requiredTreeCount: authorization.getInitialTarget(),
    }
  }

  /**
   * 申请授权市公司
   */
  async applyAuthCityCompany(
    command: ApplyAuthCityCompanyCommand,
  ): Promise<ApplyAuthCityCompanyResult> {
    const userId = UserId.create(command.userId, command.accountSequence)
    const regionCode = RegionCode.create(command.cityCode)

    // 1. 验证
    const validation = await this.validatorService.validateAuthorizationRequest(
      userId,
      RoleType.AUTH_CITY_COMPANY,
      regionCode,
      this.referralRepository,
      this.authorizationRepository,
    )

    if (!validation.isValid) {
      throw new ApplicationError(validation.errorMessage!)
    }

    // 2. 创建授权
    const authorization = AuthorizationRole.createAuthCityCompany({
      userId,
      cityCode: command.cityCode,
      cityName: command.cityName,
    })

    // 3. 检查初始考核（500棵）- 使用下级团队认种数（不含自己）
    const teamStats = await this.statsRepository.findByAccountSequence(userId.accountSequence)
    const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0

    if (subordinateTreeCount >= authorization.getInitialTarget()) {
      authorization.activateBenefit()
      await this.createInitialAssessment(authorization, teamStats!)
    }

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()

    return {
      authorizationId: authorization.authorizationId.value,
      status: authorization.status,
      benefitActive: authorization.benefitActive,
      displayTitle: authorization.displayTitle,
      message: authorization.benefitActive
        ? '授权市公司权益已激活，开始阶梯考核'
        : `需要下级团队累计认种达到${authorization.getInitialTarget()}棵才能激活`,
      currentTreeCount: subordinateTreeCount,
      requiredTreeCount: authorization.getInitialTarget(),
    }
  }

  /**
   * 管理员直接授权社区
   *
   * 业务规则：
   * - 一个用户只能拥有一个社区角色
   * - 社区名称全局唯一，不允许重复
   */
  async grantCommunity(command: GrantCommunityCommand): Promise<void> {
    const userId = UserId.create(command.userId, command.accountSequence)
    const adminId = AdminUserId.create(command.adminId, command.adminAccountSequence)

    // 0. 检查用户是否已认种（授权前置条件）
    await this.ensureUserHasPlanted(command.accountSequence)

    // 1. 检查用户是否已有社区角色
    const existingUserCommunity = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      command.accountSequence,
      RoleType.COMMUNITY,
    )
    if (existingUserCommunity) {
      throw new ApplicationError(
        `用户 ${command.accountSequence} 已拥有社区角色「${existingUserCommunity.displayTitle}」，不能重复授权`,
      )
    }

    // 2. 检查社区名称是否已被使用
    const existingCommunityName = await this.authorizationRepository.findCommunityByName(command.communityName)
    if (existingCommunityName) {
      throw new ApplicationError(
        `社区名称「${command.communityName}」已被使用，请选择其他名称`,
      )
    }

    // 3. 创建社区授权
    const authorization = AuthorizationRole.createCommunity({
      userId,
      communityName: command.communityName,
      adminId,
      skipAssessment: command.skipAssessment,
    })

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()
  }

  /**
   * 管理员授权正式省公司（省区域）
   *
   * 业务规则：
   * - 同一个用户不能同时拥有省区域和市区域两种身份
   * - 同一个省份只允许授权给一个账户（按省份唯一）
   */
  async grantProvinceCompany(command: GrantProvinceCompanyCommand): Promise<void> {
    // 0. 检查用户是否已认种（授权前置条件）
    await this.ensureUserHasPlanted(command.accountSequence)

    const userId = UserId.create(command.userId, command.accountSequence)
    const adminId = AdminUserId.create(command.adminId, command.adminAccountSequence)

    // 1. 检查用户是否已有市区域授权（省区域和市区域互斥）
    const existingCityCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      command.accountSequence,
      RoleType.CITY_COMPANY,
    )
    if (existingCityCompany && existingCityCompany.status !== AuthorizationStatus.REVOKED) {
      throw new ApplicationError(
        `用户 ${command.accountSequence} 已拥有市区域角色「${existingCityCompany.regionName}」，不能同时拥有省区域角色`,
      )
    }

    // 2. 检查用户是否已有省区域授权（一个用户只能有一个省区域）
    const existingProvinceCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      command.accountSequence,
      RoleType.PROVINCE_COMPANY,
    )
    if (existingProvinceCompany && existingProvinceCompany.status !== AuthorizationStatus.REVOKED) {
      throw new ApplicationError(
        `用户 ${command.accountSequence} 已拥有省区域角色「${existingProvinceCompany.regionName}」，不能重复授权`,
      )
    }

    // 3. 检查该省份是否已有省区域授权（同一省份只能授权给一个账户）
    const existingProvinceRegion = await this.authorizationRepository.findProvinceCompanyByRegion(command.provinceCode)
    if (existingProvinceRegion) {
      throw new ApplicationError(
        `省份「${command.provinceName}」已有省区域角色授权给用户 ${existingProvinceRegion.userId.accountSequence}，不能重复授权`,
      )
    }

    // 4. 创建授权
    const authorization = AuthorizationRole.createProvinceCompany({
      userId,
      provinceCode: command.provinceCode,
      provinceName: command.provinceName,
      adminId,
      skipAssessment: command.skipAssessment,
    })

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()
  }

  /**
   * 管理员授权正式市公司（市区域）
   *
   * 业务规则：
   * - 同一个用户不能同时拥有市区域和省区域两种身份
   * - 同一个城市只允许一个市区域角色被授权
   */
  async grantCityCompany(command: GrantCityCompanyCommand): Promise<void> {
    // 0. 检查用户是否已认种（授权前置条件）
    await this.ensureUserHasPlanted(command.accountSequence)

    const userId = UserId.create(command.userId, command.accountSequence)
    const adminId = AdminUserId.create(command.adminId, command.adminAccountSequence)

    // 1. 检查用户是否已有省区域授权（市区域和省区域互斥）
    const existingProvinceCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      command.accountSequence,
      RoleType.PROVINCE_COMPANY,
    )
    if (existingProvinceCompany && existingProvinceCompany.status !== AuthorizationStatus.REVOKED) {
      throw new ApplicationError(
        `用户 ${command.accountSequence} 已拥有省区域角色「${existingProvinceCompany.regionName}」，不能同时拥有市区域角色`,
      )
    }

    // 2. 检查用户是否已有市区域授权（一个用户只能有一个市区域）
    const existingCityCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      command.accountSequence,
      RoleType.CITY_COMPANY,
    )
    if (existingCityCompany && existingCityCompany.status !== AuthorizationStatus.REVOKED) {
      throw new ApplicationError(
        `用户 ${command.accountSequence} 已拥有市区域角色「${existingCityCompany.regionName}」，不能重复授权`,
      )
    }

    // 3. 检查该城市是否已有市区域授权（同一城市全局唯一）
    const existingCityRegion = await this.authorizationRepository.findCityCompanyByRegion(command.cityCode)
    if (existingCityRegion && existingCityRegion.status !== AuthorizationStatus.REVOKED) {
      throw new ApplicationError(
        `城市「${command.cityName}」已有市区域角色授权给用户 ${existingCityRegion.userId.accountSequence}，不能重复授权`,
      )
    }

    // 4. 创建授权
    const authorization = AuthorizationRole.createCityCompany({
      userId,
      cityCode: command.cityCode,
      cityName: command.cityName,
      adminId,
      skipAssessment: command.skipAssessment,
    })

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()
  }

  /**
   * 管理员授权授权省公司（省团队）
   * Admin直接授权，跳过用户申请流程
   * 需要验证团队内唯一性：同一推荐链上不能有重复的相同省份授权
   */
  async grantAuthProvinceCompany(command: GrantAuthProvinceCompanyCommand): Promise<void> {
    // 0. 检查用户是否已认种（授权前置条件）
    await this.ensureUserHasPlanted(command.accountSequence)

    const userId = UserId.create(command.userId, command.accountSequence)
    const adminId = AdminUserId.create(command.adminId, command.adminAccountSequence)
    const regionCode = RegionCode.create(command.provinceCode)

    // 1. 验证团队内唯一性（同一推荐链上不能有重复的相同省份授权）
    const validation = await this.validatorService.validateAuthorizationRequest(
      userId,
      RoleType.AUTH_PROVINCE_COMPANY,
      regionCode,
      this.referralRepository,
      this.authorizationRepository,
    )

    if (!validation.isValid) {
      throw new ApplicationError(validation.errorMessage!)
    }

    // 2. 创建授权
    const authorization = AuthorizationRole.createAuthProvinceCompanyByAdmin({
      userId,
      provinceCode: command.provinceCode,
      provinceName: command.provinceName,
      adminId,
      skipAssessment: command.skipAssessment,
    })

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()
  }

  /**
   * 管理员授权授权市公司（市团队）
   * Admin直接授权，跳过用户申请流程
   * 需要验证团队内唯一性：同一推荐链上不能有重复的相同城市授权
   */
  async grantAuthCityCompany(command: GrantAuthCityCompanyCommand): Promise<void> {
    // 0. 检查用户是否已认种（授权前置条件）
    await this.ensureUserHasPlanted(command.accountSequence)

    const userId = UserId.create(command.userId, command.accountSequence)
    const adminId = AdminUserId.create(command.adminId, command.adminAccountSequence)
    const regionCode = RegionCode.create(command.cityCode)

    // 1. 验证团队内唯一性（同一推荐链上不能有重复的相同城市授权）
    const validation = await this.validatorService.validateAuthorizationRequest(
      userId,
      RoleType.AUTH_CITY_COMPANY,
      regionCode,
      this.referralRepository,
      this.authorizationRepository,
    )

    if (!validation.isValid) {
      throw new ApplicationError(validation.errorMessage!)
    }

    // 2. 创建授权
    const authorization = AuthorizationRole.createAuthCityCompanyByAdmin({
      userId,
      cityCode: command.cityCode,
      cityName: command.cityName,
      adminId,
      skipAssessment: command.skipAssessment,
    })

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()
  }

  /**
   * 撤销授权
   */
  async revokeAuthorization(command: RevokeAuthorizationCommand): Promise<void> {
    const authorization = await this.authorizationRepository.findById(
      AuthorizationId.create(command.authorizationId),
    )

    if (!authorization) {
      throw new NotFoundError('授权不存在')
    }

    // Note: We need the adminId from somewhere, for now using a placeholder
    // In a real scenario, we would need to fetch the admin's userId from the accountSequence
    const adminId = AdminUserId.create('admin', command.adminAccountSequence)
    authorization.revoke(adminId, command.reason)

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()
  }

  /**
   * 授予单月豁免
   */
  async grantMonthlyBypass(command: GrantMonthlyBypassCommand): Promise<void> {
    const assessment = await this.assessmentRepository.findByAuthorizationAndMonth(
      AuthorizationId.create(command.authorizationId),
      Month.create(command.month),
    )

    if (!assessment) {
      throw new NotFoundError('考核记录不存在')
    }

    // Note: We need the adminId from somewhere, for now using a placeholder
    const adminId = AdminUserId.create('admin', command.adminAccountSequence)
    assessment.grantBypass(adminId)

    await this.assessmentRepository.save(assessment)
    await this.eventPublisher.publishAll(assessment.domainEvents)
    assessment.clearDomainEvents()
  }

  /**
   * 豁免占比考核
   */
  async exemptLocalPercentageCheck(command: ExemptLocalPercentageCheckCommand): Promise<void> {
    const authorization = await this.authorizationRepository.findById(
      AuthorizationId.create(command.authorizationId),
    )

    if (!authorization) {
      throw new NotFoundError('授权不存在')
    }

    // Note: We need the adminId from somewhere, for now using a placeholder
    const adminId = AdminUserId.create('admin', command.adminAccountSequence)
    authorization.exemptLocalPercentageCheck(adminId)

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()
  }

  /**
   * 查询用户授权列表
   */
  async getUserAuthorizations(accountSequence: string): Promise<AuthorizationDTO[]> {
    const authorizations = await this.authorizationRepository.findByAccountSequence(
      accountSequence,
    )

    // 查询用户团队统计数据
    const teamStats = await this.statsRepository.findByAccountSequence(accountSequence)
    const currentTreeCount = teamStats?.totalTeamPlantingCount || 0

    return authorizations.map((auth) => this.toAuthorizationDTO(auth, currentTreeCount))
  }

  /**
   * 查询用户授权详情
   */
  async getAuthorizationById(authorizationId: string): Promise<AuthorizationDTO | null> {
    const authorization = await this.authorizationRepository.findById(
      AuthorizationId.create(authorizationId),
    )

    if (!authorization) return null

    // 查询用户团队统计数据
    const teamStats = await this.statsRepository.findByAccountSequence(authorization.userId.accountSequence)
    const currentTreeCount = teamStats?.totalTeamPlantingCount || 0

    return this.toAuthorizationDTO(authorization, currentTreeCount)
  }

  /**
   * 查询火柴人排名数据
   *
   * 业务规则：查询同一区域内该角色类型的所有排名数据
   * 只显示与当前用户相同省/市的授权用户排名
   */
  async getStickmanRanking(
    month: string,
    roleType: RoleType,
    regionCode: string,
    currentUserId?: string,
  ): Promise<StickmanRankingDTO[]> {
    this.logger.log(
      `[getStickmanRanking] 查询火柴人排名: month=${month}, roleType=${roleType}, regionCode=${regionCode}, currentUserId=${currentUserId}`,
    )

    const monthVO = Month.create(month)
    const regionCodeVO = RegionCode.create(regionCode)

    // 查询同一区域内该角色类型的所有评估记录
    let assessments = await this.assessmentRepository.findRankingsByMonthAndRegion(
      monthVO,
      roleType,
      regionCodeVO,
    )

    this.logger.log(
      `[getStickmanRanking] 查询到 ${assessments.length} 条评估记录`,
    )

    // 如果没有评估记录，尝试实时创建（只为当前区域创建）
    if (assessments.length === 0) {
      this.logger.log(
        `[getStickmanRanking] 没有评估记录，尝试实时创建: month=${month}, roleType=${roleType}, regionCode=${regionCode}`,
      )

      // 使用 AssessmentCalculatorService 为当前区域创建评估
      const calculatorService = new AssessmentCalculatorService()

      this.logger.log(
        `[getStickmanRanking] 为区域 ${regionCode} 创建评估`,
      )

      const regionAssessments = await calculatorService.assessAndRankRegion(
        roleType,
        regionCodeVO,
        monthVO,
        this.authorizationRepository,
        this.statsRepository,
        this.assessmentRepository,
      )

      this.logger.log(
        `[getStickmanRanking] 区域 ${regionCode} 创建了 ${regionAssessments.length} 条评估记录`,
      )

      // 保存评估记录
      if (regionAssessments.length > 0) {
        await this.assessmentRepository.saveAll(regionAssessments)
      }

      // 重新查询当前区域的评估记录
      assessments = await this.assessmentRepository.findRankingsByMonthAndRegion(
        monthVO,
        roleType,
        regionCodeVO,
      )

      this.logger.log(
        `[getStickmanRanking] 重新查询到 ${assessments.length} 条评估记录`,
      )

      if (assessments.length === 0) {
        this.logger.warn(
          `[getStickmanRanking] 创建评估后仍然没有记录，month=${month}, roleType=${roleType}, regionCode=${regionCode}`,
        )
        return []
      }
    }

    // 批量获取用户信息（使用 accountSequence）
    const accountSequences = assessments.map(a => a.userId.accountSequence)
    const userInfoMap = await this.identityServiceClient.batchGetUserInfoBySequence(accountSequences)

    // 批量获取月度收益（从 reward-service）
    // 根据角色类型确定要查询的权益类型
    const rightTypes = roleType === RoleType.AUTH_PROVINCE_COMPANY
      ? ['PROVINCE_TEAM_RIGHT', 'SHARE_RIGHT']  // 省团队：省团队权益 + 分享权益
      : ['CITY_TEAM_RIGHT', 'SHARE_RIGHT']      // 市团队：市团队权益 + 分享权益
    const monthlyEarningsMap = await this.rewardServiceClient.batchGetMonthlyEarnings(
      accountSequences,
      month,
      rightTypes,
    )

    this.logger.debug(
      `[getStickmanRanking] 获取到 ${monthlyEarningsMap.size} 条月度收益记录`,
    )

    const rankings: StickmanRankingDTO[] = []
    const finalTarget = LadderTargetRule.getFinalTarget(roleType)

    for (const assessment of assessments) {
      const userInfo = userInfoMap.get(assessment.userId.accountSequence)
      const earnings = monthlyEarningsMap.get(assessment.userId.accountSequence)
      this.logger.debug(
        `[getStickmanRanking] 处理评估记录: userId=${assessment.userId.value}, ` +
        `regionCode=${assessment.regionCode.value}, cumulativeCompleted=${assessment.cumulativeCompleted}, ` +
        `monthlyEarnings=${earnings?.monthlyTotalUsdt || 0}`,
      )
      rankings.push({
        id: assessment.authorizationId.value,
        userId: assessment.userId.value,
        accountSequence: assessment.userId.accountSequence,
        authorizationId: assessment.authorizationId.value,
        roleType: assessment.roleType,
        regionCode: assessment.regionCode.value,
        nickname: userInfo?.nickname || `用户${assessment.userId.accountSequence.slice(-4)}`,
        avatarUrl: userInfo?.avatarUrl,
        completedCount: assessment.cumulativeCompleted,
        monthlyEarnings: earnings?.monthlyTotalUsdt || 0, // 从奖励服务获取的月度可结算收益
        isCurrentUser: currentUserId ? assessment.userId.value === currentUserId : false,
        ranking: assessment.rankingInRegion || 0,
        isFirstPlace: assessment.isFirstPlace,
        cumulativeCompleted: assessment.cumulativeCompleted,
        cumulativeTarget: assessment.cumulativeTarget,
        finalTarget,
        progressPercentage: (assessment.cumulativeCompleted / finalTarget) * 100,
        exceedRatio: assessment.exceedRatio,
        monthlyRewardUsdt: earnings?.monthlyTotalUsdt || 0, // 与 monthlyEarnings 相同
        monthlyRewardRwad: 0, // 算力奖励暂未实现
      })
    }

    // 按完成数量降序排序
    rankings.sort((a, b) => b.completedCount - a.completedCount)

    // 详细日志：显示每条记录的区域信息
    this.logger.log(
      `[getStickmanRanking] 返回 ${rankings.length} 条排名数据，请求区域=${regionCode}`,
    )
    for (const r of rankings) {
      this.logger.debug(
        `[getStickmanRanking] - ${r.nickname} (${r.accountSequence}): regionCode=${r.regionCode}, completedCount=${r.completedCount}`,
      )
    }

    return rankings
  }

  // 辅助方法
  private async createInitialAssessment(
    authorization: AuthorizationRole,
    teamStats: TeamStatistics,
  ): Promise<void> {
    const currentMonth = Month.current()
    const target = LadderTargetRule.getTarget(authorization.roleType, 1)

    const assessment = MonthlyAssessment.create({
      authorizationId: authorization.authorizationId,
      userId: authorization.userId,
      roleType: authorization.roleType,
      regionCode: authorization.regionCode,
      assessmentMonth: currentMonth,
      monthIndex: 1,
      monthlyTarget: target.monthlyTarget,
      cumulativeTarget: target.cumulativeTarget,
    })

    // 立即评估首月
    const localTeamCount = this.getLocalTeamCount(
      teamStats,
      authorization.roleType,
      authorization.regionCode,
    )

    assessment.assess({
      cumulativeCompleted: teamStats.totalTeamPlantingCount,
      localTeamCount,
      totalTeamCount: teamStats.totalTeamPlantingCount,
      requireLocalPercentage: authorization.requireLocalPercentage,
      exemptFromPercentageCheck: authorization.exemptFromPercentageCheck,
    })

    await this.assessmentRepository.save(assessment)
    await this.eventPublisher.publishAll(assessment.domainEvents)
    assessment.clearDomainEvents()
  }

  private getLocalTeamCount(
    teamStats: TeamStatistics,
    roleType: RoleType,
    regionCode: RegionCode,
  ): number {
    if (roleType === RoleType.AUTH_PROVINCE_COMPANY) {
      return teamStats.getProvinceTeamCount(regionCode.value)
    } else if (roleType === RoleType.AUTH_CITY_COMPANY) {
      return teamStats.getCityTeamCount(regionCode.value)
    }
    return 0
  }

  private toAuthorizationDTO(auth: AuthorizationRole, currentTreeCount: number): AuthorizationDTO {
    // 获取月度考核目标（社区固定10，其他类型根据阶梯规则）
    let monthlyTargetTreeCount = 0
    if (auth.roleType === RoleType.COMMUNITY) {
      monthlyTargetTreeCount = 10  // 社区固定每月新增10棵
    } else if (auth.benefitActive && auth.currentMonthIndex > 0) {
      // 省/市公司使用阶梯目标
      const target = LadderTargetRule.getTarget(auth.roleType, auth.currentMonthIndex)
      monthlyTargetTreeCount = target.monthlyTarget
    }

    return {
      authorizationId: auth.authorizationId.value,
      userId: auth.userId.value,
      roleType: auth.roleType,
      regionCode: auth.regionCode.value,
      regionName: auth.regionName,
      status: auth.status,
      displayTitle: auth.displayTitle,
      benefitActive: auth.benefitActive,
      currentMonthIndex: auth.currentMonthIndex,
      requireLocalPercentage: auth.requireLocalPercentage,
      exemptFromPercentageCheck: auth.exemptFromPercentageCheck,
      // 考核进度字段
      initialTargetTreeCount: auth.getInitialTarget(),
      currentTreeCount,
      monthlyTargetTreeCount,
      createdAt: auth.createdAt,
      updatedAt: auth.updatedAt,
    }
  }

  /**
   * 获取用户的社区层级信息
   * - myCommunity: 我的社区授权（如果有）
   * - parentCommunity: 上级社区（沿推荐链往上找最近的，如果没有则返回总部社区）
   * - childCommunities: 下级社区（在我的团队中找最近的社区）
   */
  async getCommunityHierarchy(accountSequence: string): Promise<CommunityHierarchyDTO> {
    this.logger.debug(`[getCommunityHierarchy] accountSequence=${accountSequence}`)

    // 1. 查询我的社区授权
    const myCommunity = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.COMMUNITY,
    )

    // 2. 获取我的祖先链（推荐链）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
    this.logger.debug(`[getCommunityHierarchy] ancestorPath: ${ancestorAccountSequences.join(',')}`)

    // 3. 查找上级社区（在祖先链中找最近的有社区授权的用户）
    let parentCommunityAuth: AuthorizationRole | null = null
    if (ancestorAccountSequences.length > 0) {
      const ancestorCommunities = await this.authorizationRepository.findActiveCommunityByAccountSequences(
        ancestorAccountSequences,
      )

      // 找最近的（ancestorAccountSequences 是从直接推荐人到根节点的顺序）
      if (ancestorCommunities.length > 0) {
        // 按祖先链顺序找第一个匹配的
        for (const ancestorSeq of ancestorAccountSequences) {
          const found = ancestorCommunities.find(
            (auth) => auth.userId.accountSequence === ancestorSeq,
          )
          if (found) {
            parentCommunityAuth = found
            break
          }
        }
      }
    }

    // 4. 获取我的团队成员
    const teamMemberAccountSequences = await this.referralServiceClient.getTeamMembers(accountSequence)
    this.logger.debug(`[getCommunityHierarchy] teamMembers count: ${teamMemberAccountSequences.length}`)

    // 5. 查找下级社区（在团队成员中找最近的有社区授权的用户）
    // "最近" 的定义：直接下级优先，然后是下级的下级，以此类推
    // 由于 getTeamMembers 返回的是广度优先遍历结果，可以直接使用顺序
    let childCommunityAuths: AuthorizationRole[] = []
    if (teamMemberAccountSequences.length > 0) {
      const teamCommunities = await this.authorizationRepository.findActiveCommunityByAccountSequences(
        teamMemberAccountSequences,
      )

      // 只保留"最近的"下级社区
      // 如果一个社区的上级不在我的直接团队成员中，或者其上级就是我，则它是"最近的"
      // 简化实现：返回所有团队中的社区，前端可以根据需要过滤
      // 但按用户要求"只计算最近的那个"，这里需要做过滤
      // 算法：如果某个社区 A 的祖先中有另一个社区 B 也在团队中，则 A 不是最近的

      const communityAccountSeqs = new Set(teamCommunities.map((c) => c.userId.accountSequence))

      for (const comm of teamCommunities) {
        // 获取这个社区成员的祖先链
        const commAncestors = await this.referralServiceClient.getReferralChain(comm.userId.accountSequence)

        // 检查这个社区是否有"更近"的祖先社区
        let hasCloserAncestorCommunity = false
        for (const ancestorSeq of commAncestors) {
          // 如果祖先是我，停止检查
          if (ancestorSeq === accountSequence) {
            break
          }
          // 如果祖先也是社区且在我的团队中，则当前社区不是最近的
          if (communityAccountSeqs.has(ancestorSeq)) {
            hasCloserAncestorCommunity = true
            break
          }
        }

        if (!hasCloserAncestorCommunity) {
          childCommunityAuths.push(comm)
        }
      }
    }

    // 6. 构建响应
    const HEADQUARTERS_COMMUNITY = {
      authorizationId: 'headquarters',
      accountSequence: '0',
      communityName: '总部',
      userId: undefined,
      isHeadquarters: true,
    }

    return {
      myCommunity: myCommunity && myCommunity.status === AuthorizationStatus.AUTHORIZED
        ? {
            authorizationId: myCommunity.authorizationId.value,
            accountSequence: myCommunity.userId.accountSequence,
            communityName: myCommunity.displayTitle,
            userId: myCommunity.userId.value,
            isHeadquarters: false,
          }
        : null,
      parentCommunity: parentCommunityAuth
        ? {
            authorizationId: parentCommunityAuth.authorizationId.value,
            accountSequence: parentCommunityAuth.userId.accountSequence,
            communityName: parentCommunityAuth.displayTitle,
            userId: parentCommunityAuth.userId.value,
            isHeadquarters: false,
          }
        : HEADQUARTERS_COMMUNITY,
      childCommunities: childCommunityAuths.map((auth) => ({
        authorizationId: auth.authorizationId.value,
        accountSequence: auth.userId.accountSequence,
        communityName: auth.displayTitle,
        userId: auth.userId.value,
        isHeadquarters: false,
      })),
      hasParentCommunity: parentCommunityAuth !== null,
      childCommunityCount: childCommunityAuths.length,
    }
  }

  /**
   * 查找用户推荐链中最近的社区授权用户
   * 用于 reward-service 分配社区权益
   * @returns accountSequence of nearest community authorization holder, or null
   */
  async findNearestAuthorizedCommunity(accountSequence: string): Promise<string | null> {
    this.logger.debug(`[findNearestAuthorizedCommunity] accountSequence=${accountSequence}`)

    // 获取用户的祖先链（推荐链）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)

    if (ancestorAccountSequences.length === 0) {
      return null
    }

    // 在祖先链中找最近的有社区授权的用户
    const ancestorCommunities = await this.authorizationRepository.findActiveCommunityByAccountSequences(
      ancestorAccountSequences,
    )

    if (ancestorCommunities.length === 0) {
      return null
    }

    // 按祖先链顺序找第一个匹配的
    for (const ancestorSeq of ancestorAccountSequences) {
      const found = ancestorCommunities.find(
        (auth) => auth.userId.accountSequence === ancestorSeq,
      )
      if (found) {
        return found.userId.accountSequence
      }
    }

    return null
  }

  /**
   * 查找用户推荐链中最近的省公司授权用户（匹配指定省份）
   * 用于 reward-service 分配省团队权益
   * @returns accountSequence of nearest province authorization holder, or null
   */
  async findNearestAuthorizedProvince(
    accountSequence: string,
    provinceCode: string,
  ): Promise<string | null> {
    this.logger.debug(
      `[findNearestAuthorizedProvince] accountSequence=${accountSequence}, provinceCode=${provinceCode}`,
    )

    // 获取用户的祖先链（推荐链）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)

    if (ancestorAccountSequences.length === 0) {
      return null
    }

    // 在祖先链中找最近的有省公司授权且匹配省份代码的用户
    const ancestorProvinces = await this.authorizationRepository.findActiveProvinceByAccountSequencesAndRegion(
      ancestorAccountSequences,
      provinceCode,
    )

    if (ancestorProvinces.length === 0) {
      return null
    }

    // 按祖先链顺序找第一个匹配的
    for (const ancestorSeq of ancestorAccountSequences) {
      const found = ancestorProvinces.find(
        (auth) => auth.userId.accountSequence === ancestorSeq,
      )
      if (found) {
        return found.userId.accountSequence
      }
    }

    return null
  }

  /**
   * 查找用户推荐链中最近的市公司授权用户（匹配指定城市）
   * 用于 reward-service 分配市团队权益
   * @returns accountSequence of nearest city authorization holder, or null
   */
  async findNearestAuthorizedCity(
    accountSequence: string,
    cityCode: string,
  ): Promise<string | null> {
    this.logger.debug(
      `[findNearestAuthorizedCity] accountSequence=${accountSequence}, cityCode=${cityCode}`,
    )

    // 获取用户的祖先链（推荐链）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)

    if (ancestorAccountSequences.length === 0) {
      return null
    }

    // 在祖先链中找最近的有市公司授权且匹配城市代码的用户
    const ancestorCities = await this.authorizationRepository.findActiveCityByAccountSequencesAndRegion(
      ancestorAccountSequences,
      cityCode,
    )

    if (ancestorCities.length === 0) {
      return null
    }

    // 按祖先链顺序找第一个匹配的
    for (const ancestorSeq of ancestorAccountSequences) {
      const found = ancestorCities.find(
        (auth) => auth.userId.accountSequence === ancestorSeq,
      )
      if (found) {
        return found.userId.accountSequence
      }
    }

    return null
  }

  /**
   * 检查用户是否已认种至少一棵树
   * 授权前置条件：用户必须先认种才能被授权任何角色
   */
  private async ensureUserHasPlanted(accountSequence: string): Promise<void> {
    const teamStats = await this.referralServiceClient.findByAccountSequence(accountSequence)
    const selfPlantingCount = teamStats?.selfPlantingCount || 0

    if (selfPlantingCount < 1) {
      throw new ApplicationError(
        `用户 ${accountSequence} 尚未认种任何树，无法授权。请先至少认种1棵树后再进行授权操作。`,
      )
    }

    this.logger.debug(
      `[ensureUserHasPlanted] User ${accountSequence} has planted ${selfPlantingCount} tree(s), authorization allowed`,
    )
  }

  /**
   * 尝试激活授权权益
   * 仅当权益未激活时执行激活操作
   *
   * 对于社区权益：需要级联激活推荐链上所有父级社区
   */
  private async tryActivateBenefit(authorization: AuthorizationRole): Promise<void> {
    if (authorization.benefitActive) {
      return // 已激活，无需操作
    }

    this.logger.log(
      `[tryActivateBenefit] Activating benefit for authorization ${authorization.authorizationId.value}, ` +
      `role=${authorization.roleType}, accountSequence=${authorization.userId.accountSequence}`,
    )

    authorization.activateBenefit()
    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()

    // 如果是社区权益，需要级联激活上级社区
    if (authorization.roleType === RoleType.COMMUNITY) {
      await this.cascadeActivateParentCommunities(authorization.userId.accountSequence)
    }

    // 如果是市团队授权权益，需要级联激活上级市团队授权
    if (authorization.roleType === RoleType.AUTH_CITY_COMPANY) {
      await this.cascadeActivateParentAuthCities(authorization.userId.accountSequence)
    }

    // 如果是省团队授权权益，需要级联激活上级省团队授权
    if (authorization.roleType === RoleType.AUTH_PROVINCE_COMPANY) {
      await this.cascadeActivateParentAuthProvinces(authorization.userId.accountSequence)
    }
  }

  /**
   * 级联激活上级社区权益
   * 当一个社区的权益被激活时，需要同时激活推荐链上所有父级社区的权益
   *
   * 业务规则：
   * - 从当前社区往上找，找到所有已授权但权益未激活的社区
   * - 将它们的权益都激活
   * - 总部社区不需要考核，不在此处理
   */
  private async cascadeActivateParentCommunities(accountSequence: string): Promise<void> {
    this.logger.log(
      `[cascadeActivateParentCommunities] Starting cascade activation for communities above ${accountSequence}`,
    )

    // 1. 获取推荐链（不包括当前用户）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
    if (ancestorAccountSequences.length === 0) {
      return
    }

    // 2. 查找推荐链上所有社区授权（包括 benefitActive=false）
    const ancestorCommunities = await this.authorizationRepository.findCommunityByAccountSequences(
      ancestorAccountSequences,
    )

    // 3. 筛选出已授权但权益未激活的社区
    const inactiveCommunities = ancestorCommunities.filter(
      (auth) => auth.status === AuthorizationStatus.AUTHORIZED && !auth.benefitActive,
    )

    if (inactiveCommunities.length === 0) {
      this.logger.debug('[cascadeActivateParentCommunities] No inactive parent communities to activate')
      return
    }

    // 4. 激活这些社区的权益
    for (const community of inactiveCommunities) {
      this.logger.log(
        `[cascadeActivateParentCommunities] Cascade activating community benefit: ` +
        `authorizationId=${community.authorizationId.value}, accountSequence=${community.userId.accountSequence}`,
      )

      community.activateBenefit()
      await this.authorizationRepository.save(community)
      await this.eventPublisher.publishAll(community.domainEvents)
      community.clearDomainEvents()
    }

    this.logger.log(
      `[cascadeActivateParentCommunities] Cascade activated ${inactiveCommunities.length} parent communities`,
    )
  }

  /**
   * 级联停用社区权益
   * 当一个社区的月度考核失败时，需要停用该社区及其推荐链上所有父级社区的权益
   *
   * 业务规则：
   * - 从当前社区开始，往上找到所有已授权且权益已激活的社区
   * - 将它们的权益都停用，重新开始100棵树的初始考核
   * - 总部社区不受影响
   *
   * @param accountSequence 月度考核失败的社区的 accountSequence
   * @param reason 停用原因
   */
  async cascadeDeactivateCommunityBenefits(
    accountSequence: string,
    reason: string,
  ): Promise<{ deactivatedCount: number }> {
    this.logger.log(
      `[cascadeDeactivateCommunityBenefits] Starting cascade deactivation from ${accountSequence}, reason=${reason}`,
    )

    // 1. 获取当前社区的授权
    const currentCommunity = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.COMMUNITY,
    )

    if (!currentCommunity) {
      this.logger.warn(`[cascadeDeactivateCommunityBenefits] Community not found for ${accountSequence}`)
      return { deactivatedCount: 0 }
    }

    // 2. 收集需要停用的社区列表
    const communitiesToDeactivate: AuthorizationRole[] = []

    // 如果当前社区权益已激活，加入停用列表
    if (currentCommunity.benefitActive) {
      communitiesToDeactivate.push(currentCommunity)
    }

    // 3. 获取推荐链上的所有父级社区
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
    if (ancestorAccountSequences.length > 0) {
      const ancestorCommunities = await this.authorizationRepository.findCommunityByAccountSequences(
        ancestorAccountSequences,
      )

      // 筛选出已授权且权益已激活的社区
      const activeCommunities = ancestorCommunities.filter(
        (auth) => auth.status === AuthorizationStatus.AUTHORIZED && auth.benefitActive,
      )

      communitiesToDeactivate.push(...activeCommunities)
    }

    if (communitiesToDeactivate.length === 0) {
      this.logger.debug('[cascadeDeactivateCommunityBenefits] No active communities to deactivate')
      return { deactivatedCount: 0 }
    }

    // 4. 停用这些社区的权益
    for (const community of communitiesToDeactivate) {
      this.logger.log(
        `[cascadeDeactivateCommunityBenefits] Deactivating community benefit: ` +
        `authorizationId=${community.authorizationId.value}, accountSequence=${community.userId.accountSequence}`,
      )

      community.deactivateBenefit(reason)
      await this.authorizationRepository.save(community)
      await this.eventPublisher.publishAll(community.domainEvents)
      community.clearDomainEvents()
    }

    this.logger.log(
      `[cascadeDeactivateCommunityBenefits] Cascade deactivated ${communitiesToDeactivate.length} communities`,
    )

    return { deactivatedCount: communitiesToDeactivate.length }
  }

  /**
   * 级联激活上级市团队授权权益
   * 当一个市团队授权的权益被激活时，需要同时激活推荐链上所有父级市团队授权的权益
   *
   * 业务规则：
   * - 从当前市团队授权往上找，找到所有已授权但权益未激活的市团队授权
   * - 将它们的权益都激活
   * - 系统账户不需要考核，不在此处理
   */
  private async cascadeActivateParentAuthCities(accountSequence: string): Promise<void> {
    this.logger.log(
      `[cascadeActivateParentAuthCities] Starting cascade activation for auth cities above ${accountSequence}`,
    )

    // 1. 获取推荐链（不包括当前用户）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
    if (ancestorAccountSequences.length === 0) {
      return
    }

    // 2. 查找推荐链上所有市团队授权（包括 benefitActive=false）
    const ancestorAuthCities = await this.authorizationRepository.findAuthCityByAccountSequences(
      ancestorAccountSequences,
    )

    // 3. 筛选出已授权但权益未激活的市团队授权
    const inactiveAuthCities = ancestorAuthCities.filter(
      (auth) => auth.status === AuthorizationStatus.AUTHORIZED && !auth.benefitActive,
    )

    if (inactiveAuthCities.length === 0) {
      this.logger.debug('[cascadeActivateParentAuthCities] No inactive parent auth cities to activate')
      return
    }

    // 4. 激活这些市团队授权的权益
    for (const authCity of inactiveAuthCities) {
      this.logger.log(
        `[cascadeActivateParentAuthCities] Cascade activating auth city benefit: ` +
        `authorizationId=${authCity.authorizationId.value}, accountSequence=${authCity.userId.accountSequence}`,
      )

      authCity.activateBenefit()
      await this.authorizationRepository.save(authCity)
      await this.eventPublisher.publishAll(authCity.domainEvents)
      authCity.clearDomainEvents()
    }

    this.logger.log(
      `[cascadeActivateParentAuthCities] Cascade activated ${inactiveAuthCities.length} parent auth cities`,
    )
  }

  /**
   * 级联停用市团队授权权益
   * 当一个市团队授权的月度考核失败时，需要停用该市团队授权及其推荐链上所有父级市团队授权的权益
   *
   * 业务规则：
   * - 从当前市团队授权开始，往上找到所有已授权且权益已激活的市团队授权
   * - 将它们的权益都停用，重新开始500棵树的初始考核
   */
  async cascadeDeactivateAuthCityBenefits(
    accountSequence: string,
    reason: string,
  ): Promise<{ deactivatedCount: number }> {
    this.logger.log(
      `[cascadeDeactivateAuthCityBenefits] Starting cascade deactivation from ${accountSequence}, reason=${reason}`,
    )

    // 1. 获取当前市团队授权
    const currentAuthCity = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.AUTH_CITY_COMPANY,
    )

    if (!currentAuthCity) {
      this.logger.warn(`[cascadeDeactivateAuthCityBenefits] Auth city not found for ${accountSequence}`)
      return { deactivatedCount: 0 }
    }

    // 2. 收集需要停用的市团队授权列表
    const authCitiesToDeactivate: AuthorizationRole[] = []

    // 如果当前市团队授权权益已激活，加入停用列表
    if (currentAuthCity.benefitActive) {
      authCitiesToDeactivate.push(currentAuthCity)
    }

    // 3. 获取推荐链上的所有父级市团队授权
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
    if (ancestorAccountSequences.length > 0) {
      const ancestorAuthCities = await this.authorizationRepository.findAuthCityByAccountSequences(
        ancestorAccountSequences,
      )

      // 筛选出已授权且权益已激活的市团队授权
      const activeAuthCities = ancestorAuthCities.filter(
        (auth) => auth.status === AuthorizationStatus.AUTHORIZED && auth.benefitActive,
      )

      authCitiesToDeactivate.push(...activeAuthCities)
    }

    if (authCitiesToDeactivate.length === 0) {
      this.logger.debug('[cascadeDeactivateAuthCityBenefits] No active auth cities to deactivate')
      return { deactivatedCount: 0 }
    }

    // 4. 停用这些市团队授权的权益
    for (const authCity of authCitiesToDeactivate) {
      this.logger.log(
        `[cascadeDeactivateAuthCityBenefits] Deactivating auth city benefit: ` +
        `authorizationId=${authCity.authorizationId.value}, accountSequence=${authCity.userId.accountSequence}`,
      )

      authCity.deactivateBenefit(reason)
      await this.authorizationRepository.save(authCity)
      await this.eventPublisher.publishAll(authCity.domainEvents)
      authCity.clearDomainEvents()
    }

    this.logger.log(
      `[cascadeDeactivateAuthCityBenefits] Cascade deactivated ${authCitiesToDeactivate.length} auth cities`,
    )

    return { deactivatedCount: authCitiesToDeactivate.length }
  }

  /**
   * 处理过期的市团队授权权益
   * 定时任务调用此方法来检查并处理过期的市团队授权权益
   *
   * 业务规则：
   * - 查找所有 benefitValidUntil < 当前时间 且 benefitActive=true 的市团队授权
   * - 检查其月度考核（当月新增100棵树）
   * - 如果达标，续期；如果不达标，级联停用
   *
   * @param limit 每次处理的最大数量
   */
  async processExpiredAuthCityBenefits(limit = 100): Promise<{
    processedCount: number
    renewedCount: number
    deactivatedCount: number
  }> {
    const now = new Date()
    this.logger.log(`[processExpiredAuthCityBenefits] Starting at ${now.toISOString()}, limit=${limit}`)

    // 查找过期但仍激活的市团队授权
    const expiredAuthCities = await this.findExpiredActiveAuthCities(now, limit)

    if (expiredAuthCities.length === 0) {
      this.logger.debug('[processExpiredAuthCityBenefits] No expired auth cities found')
      return { processedCount: 0, renewedCount: 0, deactivatedCount: 0 }
    }

    let renewedCount = 0
    let deactivatedCount = 0

    for (const authCity of expiredAuthCities) {
      const accountSequence = authCity.userId.accountSequence
      const AUTH_CITY_TARGET = 100 // 市团队授权固定目标：100棵

      // 使用 getTreesForAssessment 获取正确的考核数据
      const treesForAssessment = authCity.getTreesForAssessment(now)

      this.logger.debug(
        `[processExpiredAuthCityBenefits] Checking auth city ${accountSequence}: ` +
        `treesForAssessment=${treesForAssessment}, ` +
        `monthlyTreesAdded=${authCity.monthlyTreesAdded}, ` +
        `lastMonthTreesAdded=${authCity.lastMonthTreesAdded}, ` +
        `benefitValidUntil=${authCity.benefitValidUntil?.toISOString()}, target=${AUTH_CITY_TARGET}`,
      )

      // 计算考核月份：基于 benefitValidUntil
      const assessmentMonth = authCity.benefitValidUntil
        ? Month.fromDate(authCity.benefitValidUntil)
        : Month.current().previous()

      const previousBenefitStatus = authCity.benefitActive

      if (treesForAssessment >= AUTH_CITY_TARGET) {
        // 达标，续期
        authCity.renewBenefit(treesForAssessment)
        await this.authorizationRepository.save(authCity)

        // [2026-01-08] 保存权益考核记录到新表
        await this.saveBenefitAssessmentRecord({
          authorization: authCity,
          assessmentMonth,
          monthIndex: authCity.currentMonthIndex,
          monthlyTarget: AUTH_CITY_TARGET,
          cumulativeTarget: AUTH_CITY_TARGET, // 固定目标，无累计概念
          treesCompleted: treesForAssessment,
          treesRequired: AUTH_CITY_TARGET,
          benefitActionTaken: BenefitActionType.RENEWED,
          previousBenefitStatus,
          newBenefitStatus: true,
          newValidUntil: authCity.benefitValidUntil,
          result: AssessmentResult.PASS,
          remarks: `续期成功：完成${treesForAssessment}棵，达到${AUTH_CITY_TARGET}棵目标`,
        })

        renewedCount++

        this.logger.log(
          `[processExpiredAuthCityBenefits] Auth city ${accountSequence} renewed, ` +
          `trees=${treesForAssessment}, new validUntil=${authCity.benefitValidUntil?.toISOString()}`,
        )
      } else {
        // [2026-01-08] 保存权益考核记录到新表（失效）
        await this.saveBenefitAssessmentRecord({
          authorization: authCity,
          assessmentMonth,
          monthIndex: authCity.currentMonthIndex,
          monthlyTarget: AUTH_CITY_TARGET,
          cumulativeTarget: AUTH_CITY_TARGET,
          treesCompleted: treesForAssessment,
          treesRequired: AUTH_CITY_TARGET,
          benefitActionTaken: BenefitActionType.DEACTIVATED,
          previousBenefitStatus,
          newBenefitStatus: false,
          newValidUntil: null,
          result: AssessmentResult.FAIL,
          remarks: `考核不达标：完成${treesForAssessment}棵，未达到${AUTH_CITY_TARGET}棵目标`,
        })

        // 不达标，级联停用
        const result = await this.cascadeDeactivateAuthCityBenefits(
          accountSequence,
          `月度考核不达标：考核期内新增${treesForAssessment}棵，未达到${AUTH_CITY_TARGET}棵目标`,
        )
        deactivatedCount += result.deactivatedCount
      }
    }

    this.logger.log(
      `[processExpiredAuthCityBenefits] Completed: processed=${expiredAuthCities.length}, ` +
      `renewed=${renewedCount}, deactivated=${deactivatedCount}`,
    )

    return {
      processedCount: expiredAuthCities.length,
      renewedCount,
      deactivatedCount,
    }
  }

  /**
   * 查找过期但仍激活的市团队授权
   */
  private async findExpiredActiveAuthCities(
    checkDate: Date,
    limit: number,
  ): Promise<AuthorizationRole[]> {
    return this.authorizationRepository.findExpiredActiveByRoleType(
      RoleType.AUTH_CITY_COMPANY,
      checkDate,
      limit,
    )
  }

  /**
   * 级联激活上级省团队授权权益
   * 当一个省团队授权的权益被激活时，需要同时激活推荐链上所有父级省团队授权的权益
   *
   * 业务规则：
   * - 从当前省团队授权往上找，找到所有已授权但权益未激活的省团队授权
   * - 将它们的权益都激活
   * - 系统账户不需要考核，不在此处理
   */
  private async cascadeActivateParentAuthProvinces(accountSequence: string): Promise<void> {
    this.logger.log(
      `[cascadeActivateParentAuthProvinces] Starting cascade activation for auth provinces above ${accountSequence}`,
    )

    // 1. 获取推荐链（不包括当前用户）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
    if (ancestorAccountSequences.length === 0) {
      return
    }

    // 2. 查找推荐链上所有省团队授权（包括 benefitActive=false）
    const ancestorAuthProvinces = await this.authorizationRepository.findAuthProvinceByAccountSequences(
      ancestorAccountSequences,
    )

    // 3. 筛选出已授权但权益未激活的省团队授权
    const inactiveAuthProvinces = ancestorAuthProvinces.filter(
      (auth) => auth.status === AuthorizationStatus.AUTHORIZED && !auth.benefitActive,
    )

    if (inactiveAuthProvinces.length === 0) {
      this.logger.debug('[cascadeActivateParentAuthProvinces] No inactive parent auth provinces to activate')
      return
    }

    // 4. 激活这些省团队授权的权益
    for (const authProvince of inactiveAuthProvinces) {
      this.logger.log(
        `[cascadeActivateParentAuthProvinces] Cascade activating auth province benefit: ` +
        `authorizationId=${authProvince.authorizationId.value}, accountSequence=${authProvince.userId.accountSequence}`,
      )

      authProvince.activateBenefit()
      await this.authorizationRepository.save(authProvince)
      await this.eventPublisher.publishAll(authProvince.domainEvents)
      authProvince.clearDomainEvents()
    }

    this.logger.log(
      `[cascadeActivateParentAuthProvinces] Cascade activated ${inactiveAuthProvinces.length} parent auth provinces`,
    )
  }

  /**
   * 级联停用省团队授权权益
   * 当一个省团队授权的月度考核失败时，需要停用该省团队授权及其推荐链上所有父级省团队授权的权益
   *
   * 业务规则：
   * - 从当前省团队授权开始，往上找到所有已授权且权益已激活的省团队授权
   * - 将它们的权益都停用，重新开始500棵树的初始考核
   */
  async cascadeDeactivateAuthProvinceBenefits(
    accountSequence: string,
    reason: string,
  ): Promise<{ deactivatedCount: number }> {
    this.logger.log(
      `[cascadeDeactivateAuthProvinceBenefits] Starting cascade deactivation from ${accountSequence}, reason=${reason}`,
    )

    // 1. 获取当前省团队授权
    const currentAuthProvince = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.AUTH_PROVINCE_COMPANY,
    )

    if (!currentAuthProvince) {
      this.logger.warn(`[cascadeDeactivateAuthProvinceBenefits] Auth province not found for ${accountSequence}`)
      return { deactivatedCount: 0 }
    }

    // 2. 收集需要停用的省团队授权列表
    const authProvincesToDeactivate: AuthorizationRole[] = []

    // 如果当前省团队授权权益已激活，加入停用列表
    if (currentAuthProvince.benefitActive) {
      authProvincesToDeactivate.push(currentAuthProvince)
    }

    // 3. 获取推荐链上的所有父级省团队授权
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
    if (ancestorAccountSequences.length > 0) {
      const ancestorAuthProvinces = await this.authorizationRepository.findAuthProvinceByAccountSequences(
        ancestorAccountSequences,
      )

      // 筛选出已授权且权益已激活的省团队授权
      const activeAuthProvinces = ancestorAuthProvinces.filter(
        (auth) => auth.status === AuthorizationStatus.AUTHORIZED && auth.benefitActive,
      )

      authProvincesToDeactivate.push(...activeAuthProvinces)
    }

    if (authProvincesToDeactivate.length === 0) {
      this.logger.debug('[cascadeDeactivateAuthProvinceBenefits] No active auth provinces to deactivate')
      return { deactivatedCount: 0 }
    }

    // 4. 停用这些省团队授权的权益
    for (const authProvince of authProvincesToDeactivate) {
      this.logger.log(
        `[cascadeDeactivateAuthProvinceBenefits] Deactivating auth province benefit: ` +
        `authorizationId=${authProvince.authorizationId.value}, accountSequence=${authProvince.userId.accountSequence}`,
      )

      authProvince.deactivateBenefit(reason)
      await this.authorizationRepository.save(authProvince)
      await this.eventPublisher.publishAll(authProvince.domainEvents)
      authProvince.clearDomainEvents()
    }

    this.logger.log(
      `[cascadeDeactivateAuthProvinceBenefits] Cascade deactivated ${authProvincesToDeactivate.length} auth provinces`,
    )

    return { deactivatedCount: authProvincesToDeactivate.length }
  }

  /**
   * 处理过期的省团队授权权益
   * 定时任务调用此方法来检查并处理过期的省团队授权权益
   *
   * 业务规则：
   * - 查找所有 benefitValidUntil < 当前时间 且 benefitActive=true 的省团队授权
   * - 检查其月度考核（当月新增500棵树）
   * - 如果达标，续期；如果不达标，级联停用
   *
   * @param limit 每次处理的最大数量
   */
  async processExpiredAuthProvinceBenefits(limit = 100): Promise<{
    processedCount: number
    renewedCount: number
    deactivatedCount: number
  }> {
    const now = new Date()
    this.logger.log(`[processExpiredAuthProvinceBenefits] Starting at ${now.toISOString()}, limit=${limit}`)

    // 查找过期但仍激活的省团队授权
    const expiredAuthProvinces = await this.findExpiredActiveAuthProvinces(now, limit)

    if (expiredAuthProvinces.length === 0) {
      this.logger.debug('[processExpiredAuthProvinceBenefits] No expired auth provinces found')
      return { processedCount: 0, renewedCount: 0, deactivatedCount: 0 }
    }

    let renewedCount = 0
    let deactivatedCount = 0

    for (const authProvince of expiredAuthProvinces) {
      const accountSequence = authProvince.userId.accountSequence
      const AUTH_PROVINCE_TARGET = 3000 // 省团队授权固定目标：3000棵

      // 使用 getTreesForAssessment 获取正确的考核数据
      const treesForAssessment = authProvince.getTreesForAssessment(now)

      this.logger.debug(
        `[processExpiredAuthProvinceBenefits] Checking auth province ${accountSequence}: ` +
        `treesForAssessment=${treesForAssessment}, ` +
        `monthlyTreesAdded=${authProvince.monthlyTreesAdded}, ` +
        `lastMonthTreesAdded=${authProvince.lastMonthTreesAdded}, ` +
        `benefitValidUntil=${authProvince.benefitValidUntil?.toISOString()}, target=${AUTH_PROVINCE_TARGET}`,
      )

      // 计算考核月份：基于 benefitValidUntil
      const assessmentMonth = authProvince.benefitValidUntil
        ? Month.fromDate(authProvince.benefitValidUntil)
        : Month.current().previous()

      const previousBenefitStatus = authProvince.benefitActive

      if (treesForAssessment >= AUTH_PROVINCE_TARGET) {
        // 达标，续期
        authProvince.renewBenefit(treesForAssessment)
        await this.authorizationRepository.save(authProvince)

        // [2026-01-08] 保存权益考核记录到新表
        await this.saveBenefitAssessmentRecord({
          authorization: authProvince,
          assessmentMonth,
          monthIndex: authProvince.currentMonthIndex,
          monthlyTarget: AUTH_PROVINCE_TARGET,
          cumulativeTarget: AUTH_PROVINCE_TARGET, // 固定目标，无累计概念
          treesCompleted: treesForAssessment,
          treesRequired: AUTH_PROVINCE_TARGET,
          benefitActionTaken: BenefitActionType.RENEWED,
          previousBenefitStatus,
          newBenefitStatus: true,
          newValidUntil: authProvince.benefitValidUntil,
          result: AssessmentResult.PASS,
          remarks: `续期成功：完成${treesForAssessment}棵，达到${AUTH_PROVINCE_TARGET}棵目标`,
        })

        renewedCount++

        this.logger.log(
          `[processExpiredAuthProvinceBenefits] Auth province ${accountSequence} renewed, ` +
          `trees=${treesForAssessment}, new validUntil=${authProvince.benefitValidUntil?.toISOString()}`,
        )
      } else {
        // [2026-01-08] 保存权益考核记录到新表（失效）
        await this.saveBenefitAssessmentRecord({
          authorization: authProvince,
          assessmentMonth,
          monthIndex: authProvince.currentMonthIndex,
          monthlyTarget: AUTH_PROVINCE_TARGET,
          cumulativeTarget: AUTH_PROVINCE_TARGET,
          treesCompleted: treesForAssessment,
          treesRequired: AUTH_PROVINCE_TARGET,
          benefitActionTaken: BenefitActionType.DEACTIVATED,
          previousBenefitStatus,
          newBenefitStatus: false,
          newValidUntil: null,
          result: AssessmentResult.FAIL,
          remarks: `考核不达标：完成${treesForAssessment}棵，未达到${AUTH_PROVINCE_TARGET}棵目标`,
        })

        // 不达标，级联停用
        const result = await this.cascadeDeactivateAuthProvinceBenefits(
          accountSequence,
          `月度考核不达标：考核期内新增${treesForAssessment}棵，未达到${AUTH_PROVINCE_TARGET}棵目标`,
        )
        deactivatedCount += result.deactivatedCount
      }
    }

    this.logger.log(
      `[processExpiredAuthProvinceBenefits] Completed: processed=${expiredAuthProvinces.length}, ` +
      `renewed=${renewedCount}, deactivated=${deactivatedCount}`,
    )

    return {
      processedCount: expiredAuthProvinces.length,
      renewedCount,
      deactivatedCount,
    }
  }

  /**
   * 查找过期但仍激活的省团队授权
   */
  private async findExpiredActiveAuthProvinces(
    checkDate: Date,
    limit: number,
  ): Promise<AuthorizationRole[]> {
    return this.authorizationRepository.findExpiredActiveByRoleType(
      RoleType.AUTH_PROVINCE_COMPANY,
      checkDate,
      limit,
    )
  }

  /**
   * 处理过期的社区权益
   * 定时任务调用此方法来检查并处理过期的社区权益
   *
   * 业务规则：
   * - 查找所有 benefitValidUntil < 当前时间 且 benefitActive=true 的社区
   * - 检查其月度考核（当月新增10棵树）
   * - 如果达标，续期；如果不达标，级联停用
   *
   * @param limit 每次处理的最大数量
   */
  async processExpiredCommunityBenefits(limit = 100): Promise<{
    processedCount: number
    renewedCount: number
    deactivatedCount: number
  }> {
    const now = new Date()
    this.logger.log(`[processExpiredCommunityBenefits] Starting at ${now.toISOString()}, limit=${limit}`)

    // 查找过期但仍激活的社区
    // 需要在 repository 中添加此查询方法
    const expiredCommunities = await this.findExpiredActiveCommunities(now, limit)

    if (expiredCommunities.length === 0) {
      this.logger.debug('[processExpiredCommunityBenefits] No expired communities found')
      return { processedCount: 0, renewedCount: 0, deactivatedCount: 0 }
    }

    let renewedCount = 0
    let deactivatedCount = 0

    for (const community of expiredCommunities) {
      const accountSequence = community.userId.accountSequence

      // 使用 getTreesForAssessment 获取正确的考核数据
      // - 有效期在上月末 → 用 lastMonthTreesAdded（存档数据）
      // - 有效期在当月末 → 用 monthlyTreesAdded（当月数据）
      const treesForAssessment = community.getTreesForAssessment(now)

      this.logger.debug(
        `[processExpiredCommunityBenefits] Checking community ${accountSequence}: ` +
        `treesForAssessment=${treesForAssessment}, ` +
        `monthlyTreesAdded=${community.monthlyTreesAdded}, ` +
        `lastMonthTreesAdded=${community.lastMonthTreesAdded}, ` +
        `benefitValidUntil=${community.benefitValidUntil?.toISOString()}, target=10`,
      )

      // 计算考核月份：基于 benefitValidUntil 而非当前时间
      // benefitValidUntil 是月末，考核的是该月
      const assessmentMonth = community.benefitValidUntil
        ? Month.fromDate(community.benefitValidUntil)
        : Month.current().previous()

      const COMMUNITY_TARGET = 10 // 社区月度目标：10棵
      const previousBenefitStatus = community.benefitActive

      try {
        if (treesForAssessment >= COMMUNITY_TARGET) {
          // 先生成考核记录（达标）- 考核记录优先，更难人工补录
          await this.createCommunityAssessmentRecord(
            community,
            assessmentMonth,
            treesForAssessment,
            AssessmentResult.PASS,
          )

          // 再续期并保存
          community.renewBenefit(treesForAssessment)
          await this.authorizationRepository.save(community)

          // [2026-01-08] 保存权益考核记录到新表
          await this.saveBenefitAssessmentRecord({
            authorization: community,
            assessmentMonth,
            monthIndex: community.currentMonthIndex,
            monthlyTarget: COMMUNITY_TARGET,
            cumulativeTarget: COMMUNITY_TARGET,
            treesCompleted: treesForAssessment,
            treesRequired: COMMUNITY_TARGET,
            benefitActionTaken: BenefitActionType.RENEWED,
            previousBenefitStatus,
            newBenefitStatus: true,
            newValidUntil: community.benefitValidUntil,
            result: AssessmentResult.PASS,
            remarks: `续期成功：完成${treesForAssessment}棵，达到${COMMUNITY_TARGET}棵目标`,
          })

          renewedCount++
          this.logger.log(
            `[processExpiredCommunityBenefits] Community ${accountSequence} renewed, ` +
            `trees=${treesForAssessment}, new validUntil=${community.benefitValidUntil?.toISOString()}`,
          )
        } else {
          // 先生成考核记录（不达标）
          await this.createCommunityAssessmentRecord(
            community,
            assessmentMonth,
            treesForAssessment,
            AssessmentResult.FAIL,
          )

          // [2026-01-08] 保存权益考核记录到新表（失效）
          await this.saveBenefitAssessmentRecord({
            authorization: community,
            assessmentMonth,
            monthIndex: community.currentMonthIndex,
            monthlyTarget: COMMUNITY_TARGET,
            cumulativeTarget: COMMUNITY_TARGET,
            treesCompleted: treesForAssessment,
            treesRequired: COMMUNITY_TARGET,
            benefitActionTaken: BenefitActionType.DEACTIVATED,
            previousBenefitStatus,
            newBenefitStatus: false,
            newValidUntil: null,
            result: AssessmentResult.FAIL,
            remarks: `考核不达标：完成${treesForAssessment}棵，未达到${COMMUNITY_TARGET}棵目标`,
          })

          // 再级联停用
          const result = await this.cascadeDeactivateCommunityBenefits(
            accountSequence,
            `月度考核不达标：考核期内新增${treesForAssessment}棵，未达到10棵目标`,
          )
          deactivatedCount += result.deactivatedCount
        }
      } catch (error) {
        this.logger.error(
          `[processExpiredCommunityBenefits] Failed to process community ${accountSequence}: ${error}`,
        )
        // 继续处理下一个社区，不中断整体流程
      }
    }

    this.logger.log(
      `[processExpiredCommunityBenefits] Completed: processed=${expiredCommunities.length}, ` +
      `renewed=${renewedCount}, deactivated=${deactivatedCount}`,
    )

    return {
      processedCount: expiredCommunities.length,
      renewedCount,
      deactivatedCount,
    }
  }

  /**
   * 查找过期但仍激活的社区
   * TODO: 后续优化可以移到 repository 层
   */
  private async findExpiredActiveCommunities(now: Date, limit: number): Promise<AuthorizationRole[]> {
    // 获取所有激活的社区授权
    const activeCommunities = await this.authorizationRepository.findAllActive(RoleType.COMMUNITY)

    // 筛选出已过期的
    return activeCommunities
      .filter((auth) => auth.benefitActive && auth.isBenefitExpired(now))
      .slice(0, limit)
  }

  /**
   * 创建社区权益考核记录
   * @param community 社区授权
   * @param assessmentMonth 考核月份
   * @param treesCompleted 完成的树数
   * @param result 考核结果
   */
  private async createCommunityAssessmentRecord(
    community: AuthorizationRole,
    assessmentMonth: Month,
    treesCompleted: number,
    result: AssessmentResult,
  ): Promise<void> {
    const COMMUNITY_TARGET = 10 // 社区月度考核目标：10棵

    // 检查是否已存在该月的考核记录，避免重复
    const existing = await this.assessmentRepository.findByAuthorizationAndMonth(
      community.authorizationId,
      assessmentMonth,
    )
    if (existing) {
      this.logger.warn(
        `[createCommunityAssessmentRecord] Assessment record already exists for community ${community.userId.accountSequence}, ` +
        `month=${assessmentMonth.value}, skipping`,
      )
      return
    }

    // 创建考核记录
    const assessment = MonthlyAssessment.create({
      authorizationId: community.authorizationId,
      userId: community.userId,
      roleType: RoleType.COMMUNITY,
      regionCode: community.regionCode,
      assessmentMonth,
      monthIndex: community.currentMonthIndex,
      monthlyTarget: COMMUNITY_TARGET,
      cumulativeTarget: COMMUNITY_TARGET, // 社区无累计目标概念，使用月度目标
    })

    // 执行考核（社区没有本地占比要求）
    assessment.assess({
      cumulativeCompleted: treesCompleted,
      localTeamCount: 0,
      totalTeamCount: 0,
      requireLocalPercentage: 0,
      exemptFromPercentageCheck: true,
    })

    // 更新进度
    assessment.updateProgress(treesCompleted, treesCompleted)

    // 保存考核记录
    await this.assessmentRepository.save(assessment)

    this.logger.log(
      `[createCommunityAssessmentRecord] Created assessment record for community ${community.userId.accountSequence}: ` +
      `month=${assessmentMonth.value}, completed=${treesCompleted}, target=${COMMUNITY_TARGET}, result=${result}`,
    )
  }

  /**
   * 创建正式市/省公司考核记录
   * @param company 正式市/省公司授权
   * @param assessmentMonth 考核月份
   * @param monthIndex 当前月份索引
   * @param monthlyTarget 月度目标
   * @param cumulativeTarget 累计目标
   * @param treesCompleted 完成的树数
   * @param result 考核结果
   */
  private async createCompanyAssessmentRecord(
    company: AuthorizationRole,
    assessmentMonth: Month,
    monthIndex: number,
    monthlyTarget: number,
    cumulativeTarget: number,
    treesCompleted: number,
    result: AssessmentResult,
  ): Promise<void> {
    // 检查是否已存在该月的考核记录，避免重复
    const existing = await this.assessmentRepository.findByAuthorizationAndMonth(
      company.authorizationId,
      assessmentMonth,
    )
    if (existing) {
      this.logger.warn(
        `[createCompanyAssessmentRecord] Assessment record already exists for ${company.roleType} ${company.userId.accountSequence}, ` +
        `month=${assessmentMonth.value}, skipping`,
      )
      return
    }

    // 创建考核记录
    const assessment = MonthlyAssessment.create({
      authorizationId: company.authorizationId,
      userId: company.userId,
      roleType: company.roleType,
      regionCode: company.regionCode,
      assessmentMonth,
      monthIndex,
      monthlyTarget,
      cumulativeTarget,
    })

    // 执行考核（正式市/省公司没有本地占比要求）
    assessment.assess({
      cumulativeCompleted: treesCompleted,
      localTeamCount: 0,
      totalTeamCount: 0,
      requireLocalPercentage: 0,
      exemptFromPercentageCheck: true,
    })

    // 更新进度
    assessment.updateProgress(treesCompleted, treesCompleted)

    // 保存考核记录
    await this.assessmentRepository.save(assessment)

    this.logger.log(
      `[createCompanyAssessmentRecord] Created assessment record for ${company.roleType} ${company.userId.accountSequence}: ` +
      `month=${assessmentMonth.value}, monthIndex=${monthIndex}, completed=${treesCompleted}, ` +
      `monthlyTarget=${monthlyTarget}, cumulativeTarget=${cumulativeTarget}, result=${result}`,
    )
  }

  /**
   * 获取社区权益分配方案
   * 根据考核规则计算每棵树的社区权益应该分配给谁
   *
   * 规则：
   * 1. 找到认种用户推荐链上最近的社区
   * 2. 如果该社区 benefitActive=true，全部权益给该社区
   * 3. 如果该社区 benefitActive=false：
   *    - 计算该社区还需要多少棵才能达到初始考核(100棵)
   *    - 考核前的部分给上级社区或总部
   *    - 考核后的部分给该社区（同时激活权益）
   * 4. 如果没有社区，全部给总部
   */
  async getCommunityRewardDistribution(
    accountSequence: string,
    treeCount: number,
  ): Promise<{
    distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
    }>
  }> {
    this.logger.debug(
      `[getCommunityRewardDistribution] accountSequence=${accountSequence}, treeCount=${treeCount}`,
    )

    const HEADQUARTERS_ACCOUNT_SEQUENCE = '1' // 总部社区账号

    // 1. 获取用户的祖先链（推荐链）
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)

    if (ancestorAccountSequences.length === 0) {
      // 无推荐链，全部给总部
      return {
        distributions: [
          {
            accountSequence: HEADQUARTERS_ACCOUNT_SEQUENCE,
            treeCount,
            reason: '无推荐链，进总部社区',
          },
        ],
      }
    }

    // 2. 查找祖先链中所有社区授权（包括 benefitActive=false 的）
    const ancestorCommunities = await this.authorizationRepository.findCommunityByAccountSequences(
      ancestorAccountSequences,
    )

    if (ancestorCommunities.length === 0) {
      // 推荐链上没有社区，全部给总部
      return {
        distributions: [
          {
            accountSequence: HEADQUARTERS_ACCOUNT_SEQUENCE,
            treeCount,
            reason: '推荐链上无社区授权，进总部社区',
          },
        ],
      }
    }

    // 3. 按祖先链顺序找最近的社区
    let nearestCommunity: typeof ancestorCommunities[0] | null = null
    let nearestCommunityIndex = -1

    for (let i = 0; i < ancestorAccountSequences.length; i++) {
      const ancestorSeq = ancestorAccountSequences[i]
      const found = ancestorCommunities.find(
        (auth) => auth.userId.accountSequence === ancestorSeq,
      )
      if (found) {
        nearestCommunity = found
        nearestCommunityIndex = i
        break
      }
    }

    if (!nearestCommunity) {
      // 这种情况理论上不应该发生，但作为兜底
      return {
        distributions: [
          {
            accountSequence: HEADQUARTERS_ACCOUNT_SEQUENCE,
            treeCount,
            reason: '未找到匹配的社区，进总部社区',
          },
        ],
      }
    }

    // 4. 检查最近社区的权益状态
    if (nearestCommunity.benefitActive) {
      // 权益已激活，全部给该社区
      // 累加月度新增树数（用于月度考核）
      nearestCommunity.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(nearestCommunity)

      return {
        distributions: [
          {
            accountSequence: nearestCommunity.userId.accountSequence,
            treeCount,
            reason: '社区权益已激活',
          },
        ],
      }
    }

    // 5. 权益未激活，需要计算考核分配
    // 获取该社区的团队统计数据 - 使用下级团队认种数（不含自己）
    const communityStats = await this.statsRepository.findByAccountSequence(
      nearestCommunity.userId.accountSequence,
    )
    const rawSubordinateCount = communityStats?.subordinateTeamPlantingCount ?? 0

    // 重要：由于 referral-service 和 reward-service 都消费同一个 Kafka 事件，
    // 存在竞态条件，此时查询到的 subordinateTeamPlantingCount 可能已经包含了本次认种。
    // 因此需要减去本次认种数量来还原"认种前"的下级团队数。
    // 注意：如果 referral-service 还没处理完，rawSubordinateCount 可能还是旧值，
    // 此时 currentTeamCount 可能为负数，需要取 max(0, ...)
    const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount)
    const initialTarget = nearestCommunity.getInitialTarget() // 社区初始考核目标：100棵

    this.logger.debug(
      `[getCommunityRewardDistribution] Community ${nearestCommunity.userId.accountSequence} ` +
      `benefitActive=false, rawSubordinateCount=${rawSubordinateCount}, treeCount=${treeCount}, ` +
      `currentTeamCount(before)=${currentTeamCount}, initialTarget=${initialTarget}`,
    )

    // 6. 查找上级社区（用于接收考核前的权益）
    let parentCommunityAccountSequence: string = HEADQUARTERS_ACCOUNT_SEQUENCE
    let parentCommunityReason = '上级为总部社区'

    // 从最近社区之后继续查找上级社区
    for (let i = nearestCommunityIndex + 1; i < ancestorAccountSequences.length; i++) {
      const ancestorSeq = ancestorAccountSequences[i]
      const found = ancestorCommunities.find(
        (auth) => auth.userId.accountSequence === ancestorSeq && auth.benefitActive,
      )
      if (found) {
        parentCommunityAccountSequence = found.userId.accountSequence
        parentCommunityReason = '上级社区权益已激活'
        break
      }
    }

    // 7. 计算分配方案
    const distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
    }> = []

    if (currentTeamCount >= initialTarget) {
      // 已达标但权益未激活（可能是月度考核失败），全部给该社区
      // 注：这种情况下应该由系统自动激活权益，但这里作为兜底处理
      distributions.push({
        accountSequence: nearestCommunity.userId.accountSequence,
        treeCount,
        reason: '已达初始考核目标',
      })

      // 自动激活权益
      await this.tryActivateBenefit(nearestCommunity)

      // 累加月度新增树数（用于月度考核）
      nearestCommunity.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(nearestCommunity)
    } else {
      // 未达标，需要拆分
      // toReachTarget: 还差多少棵达到考核目标（包括达标那一棵）
      // 业务规则：第1-100棵全部给上级的上级/总部，第101棵开始才给该社区
      // 例如：目标100棵，当前20棵 -> toReachTarget = 80（第21-100棵给上级，第101棵开始给自己）
      const toReachTarget = Math.max(0, initialTarget - currentTeamCount)
      const afterPlantingCount = currentTeamCount + treeCount // 本次认种后的总数

      if (afterPlantingCount <= initialTarget) {
        // 本次认种后仍未超过目标（包括刚好达标），全部给上级/总部
        distributions.push({
          accountSequence: parentCommunityAccountSequence,
          treeCount,
          reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget})，${parentCommunityReason}`,
        })

        // 如果刚好达标，激活权益（但本批次树全部给上级）
        if (afterPlantingCount === initialTarget) {
          await this.tryActivateBenefit(nearestCommunity)
        }
      } else {
        // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget)
        // 达标前的部分（包括第100棵）给上级/总部
        if (toReachTarget > 0) {
          distributions.push({
            accountSequence: parentCommunityAccountSequence,
            treeCount: toReachTarget,
            reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})，${parentCommunityReason}`,
          })
        }
        // 超过达标点的部分（第101棵开始），给该社区
        const afterTargetCount = treeCount - toReachTarget
        if (afterTargetCount > 0) {
          distributions.push({
            accountSequence: nearestCommunity.userId.accountSequence,
            treeCount: afterTargetCount,
            reason: `考核达标后权益生效(第${initialTarget + 1}棵起)`,
          })
        }

        // 自动激活权益（本次认种使其达标）
        await this.tryActivateBenefit(nearestCommunity)

        // 激活后累加月度新增树数（只计算归自己的那部分）
        if (afterTargetCount > 0) {
          nearestCommunity.addMonthlyTrees(afterTargetCount)
          await this.authorizationRepository.save(nearestCommunity)
        }
      }
    }

    this.logger.debug(
      `[getCommunityRewardDistribution] Result: ${JSON.stringify(distributions)}`,
    )

    return { distributions }
  }

  /**
   * 获取省团队权益分配方案 (20 USDT)
   *
   * 规则：
   * 1. 找到认种用户推荐链上最近的授权省公司（AUTH_PROVINCE_COMPANY）
   * 2. 如果该授权省公司 benefitActive=true，全部权益给该用户
   * 3. 如果该授权省公司 benefitActive=false：
   *    - 计算还需要多少棵才能达到初始考核(500棵)
   *    - 考核前的部分给上级/总部
   *    - 考核后的部分给该用户
   * 4. 如果没有授权省公司，全部给总部
   */
  async getProvinceTeamRewardDistribution(
    accountSequence: string,
    provinceCode: string,
    treeCount: number,
  ): Promise<{
    distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
    }>
  }> {
    this.logger.debug(
      `[getProvinceTeamRewardDistribution] accountSequence=${accountSequence}, provinceCode=${provinceCode}, treeCount=${treeCount}`,
    )

    // 系统省团队账户ID格式: 7 + 省份代码
    const systemProvinceTeamAccountSequence = `7${provinceCode.padStart(6, '0')}`

    // 1. 获取用户的祖先链
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)

    if (ancestorAccountSequences.length === 0) {
      return {
        distributions: [
          { accountSequence: systemProvinceTeamAccountSequence, treeCount, reason: '无推荐链，进系统省团队账户' },
        ],
      }
    }

    // 2. 查找祖先链中所有授权省公司（包括 benefitActive=false）
    // 注意：省团队收益不再要求省份匹配，只要推荐链上有省团队授权即可获得收益
    const ancestorAuthProvinces = await this.authorizationRepository.findAuthProvinceByAccountSequences(
      ancestorAccountSequences,
    )

    if (ancestorAuthProvinces.length === 0) {
      return {
        distributions: [
          { accountSequence: systemProvinceTeamAccountSequence, treeCount, reason: '推荐链上无授权省公司，进系统省团队账户' },
        ],
      }
    }

    // 3. 按祖先链顺序找最近的授权省公司
    let nearestAuthProvince: typeof ancestorAuthProvinces[0] | null = null
    let nearestIndex = -1

    for (let i = 0; i < ancestorAccountSequences.length; i++) {
      const ancestorSeq = ancestorAccountSequences[i]
      const found = ancestorAuthProvinces.find(
        (auth) => auth.userId.accountSequence === ancestorSeq,
      )
      if (found) {
        nearestAuthProvince = found
        nearestIndex = i
        break
      }
    }

    if (!nearestAuthProvince) {
      return {
        distributions: [
          { accountSequence: systemProvinceTeamAccountSequence, treeCount, reason: '未找到匹配的授权省公司，进系统省团队账户' },
        ],
      }
    }

    // 4. 检查权益状态
    if (nearestAuthProvince.benefitActive) {
      // 权益已激活，全部给该省团队
      // 累加月度新增树数（用于月度考核）
      nearestAuthProvince.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(nearestAuthProvince)

      return {
        distributions: [
          { accountSequence: nearestAuthProvince.userId.accountSequence, treeCount, reason: '省团队权益已激活' },
        ],
      }
    }

    // 5. 权益未激活，计算考核分配 - 使用下级团队认种数（不含自己）
    const stats = await this.statsRepository.findByAccountSequence(nearestAuthProvince.userId.accountSequence)
    const rawSubordinateCount = stats?.subordinateTeamPlantingCount ?? 0
    // 修复竞态条件：减去本次认种数量来还原"认种前"的下级团队数
    const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount)
    const initialTarget = nearestAuthProvince.getInitialTarget() // 3000棵

    this.logger.debug(
      `[getProvinceTeamRewardDistribution] rawSubordinateCount=${rawSubordinateCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}`,
    )

    // 6. 查找上级（用于接收考核前的权益）
    let parentAccountSequence: string = systemProvinceTeamAccountSequence
    let parentReason = '上级为系统省团队账户'

    for (let i = nearestIndex + 1; i < ancestorAccountSequences.length; i++) {
      const ancestorSeq = ancestorAccountSequences[i]
      const found = ancestorAuthProvinces.find(
        (auth) => auth.userId.accountSequence === ancestorSeq && auth.benefitActive,
      )
      if (found) {
        parentAccountSequence = found.userId.accountSequence
        parentReason = '上级授权省公司权益已激活'
        break
      }
    }

    // 7. 计算分配
    const distributions: Array<{ accountSequence: string; treeCount: number; reason: string }> = []

    if (currentTeamCount >= initialTarget) {
      // 已达标但权益未激活（可能是月度考核失败），全部给该省团队
      // 注：这种情况下应该由系统自动激活权益，但这里作为兜底处理
      distributions.push({
        accountSequence: nearestAuthProvince.userId.accountSequence,
        treeCount,
        reason: '已达初始考核目标',
      })

      // 自动激活权益
      await this.tryActivateBenefit(nearestAuthProvince)

      // 累加月度新增树数（用于月度考核）
      nearestAuthProvince.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(nearestAuthProvince)
    } else {
      // toReachTarget: 还差多少棵达到考核目标（包括达标那一棵）
      // 业务规则：达标前的全部给上级/总部，超过达标点后才给该省团队
      const toReachTarget = Math.max(0, initialTarget - currentTeamCount)
      const afterPlantingCount = currentTeamCount + treeCount

      if (afterPlantingCount <= initialTarget) {
        // 本次认种后仍未超过目标（包括刚好达标），全部给上级/总部
        distributions.push({
          accountSequence: parentAccountSequence,
          treeCount,
          reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget})，${parentReason}`,
        })

        // 如果刚好达标，激活权益（但本批次树全部给上级）
        if (afterPlantingCount === initialTarget) {
          await this.tryActivateBenefit(nearestAuthProvince)
        }
      } else {
        // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget)
        // 达标前的部分（包括第500棵）给上级/总部
        if (toReachTarget > 0) {
          distributions.push({
            accountSequence: parentAccountSequence,
            treeCount: toReachTarget,
            reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})，${parentReason}`,
          })
        }
        // 超过达标点的部分（第501棵开始），给该省团队
        const afterTargetCount = treeCount - toReachTarget
        if (afterTargetCount > 0) {
          distributions.push({
            accountSequence: nearestAuthProvince.userId.accountSequence,
            treeCount: afterTargetCount,
            reason: `考核达标后权益生效(第${initialTarget + 1}棵起)`,
          })
        }

        // 自动激活权益（本次认种使其达标）
        await this.tryActivateBenefit(nearestAuthProvince)

        // 激活后累加月度新增树数（只计算归自己的那部分）
        if (afterTargetCount > 0) {
          nearestAuthProvince.addMonthlyTrees(afterTargetCount)
          await this.authorizationRepository.save(nearestAuthProvince)
        }
      }
    }

    this.logger.debug(`[getProvinceTeamRewardDistribution] Result: ${JSON.stringify(distributions)}`)
    return { distributions }
  }

  /**
   * 获取省区域权益分配方案 (15 USDT + 1%算力)
   *
   * 规则：
   * 1. 查找该省份是否有正式省公司（PROVINCE_COMPANY）
   * 2. 如果有且 benefitActive=true，权益进该省公司自己的账户，并累加当月新增树数
   * 3. 如果有但 benefitActive=false（考核中）：
   *    - 使用阶梯目标（第1月150，第2月300，...，第9月11750）
   *    - 计算还需要多少棵才能达到当月目标
   *    - 考核前的部分进系统省账户
   *    - 考核后的部分给该省公司
   *    - 第一个月达标150棵立即激活权益
   * 4. 如果没有正式省公司，全部进系统省账户
   */
  async getProvinceAreaRewardDistribution(
    provinceCode: string,
    treeCount: number,
  ): Promise<{
    distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
      isSystemAccount: boolean
    }>
  }> {
    this.logger.debug(
      `[getProvinceAreaRewardDistribution] provinceCode=${provinceCode}, treeCount=${treeCount}`,
    )

    // 系统省账户ID格式: 9 + 省份代码
    const systemProvinceAccountId = `9${provinceCode.padStart(6, '0')}`

    // 查找该省份的正式省公司
    const provinceCompany = await this.authorizationRepository.findProvinceCompanyByRegion(provinceCode)

    if (!provinceCompany) {
      // 无正式省公司，全部进系统省账户
      return {
        distributions: [
          {
            accountSequence: systemProvinceAccountId,
            treeCount,
            reason: '无正式省公司授权，进系统省账户',
            isSystemAccount: true,
          },
        ],
      }
    }

    if (provinceCompany.benefitActive) {
      // 正式省公司权益已激活，进该省公司账户
      // 累加当月新增树数用于月度考核
      provinceCompany.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(provinceCompany)

      return {
        distributions: [
          {
            accountSequence: provinceCompany.userId.accountSequence,
            treeCount,
            reason: '省区域权益已激活',
            isSystemAccount: false,
          },
        ],
      }
    }

    // 权益未激活，使用阶梯目标计算考核分配
    // 使用当前月份索引获取阶梯目标（第一个月为150棵）
    const monthIndex = provinceCompany.currentMonthIndex || 1
    const ladderTarget = LadderTargetRule.getTarget(RoleType.PROVINCE_COMPANY, monthIndex)
    const initialTarget = ladderTarget.monthlyTarget  // 第一个月150棵

    // 使用 monthlyTreesAdded 作为当前累计认种数
    const currentTeamCount = provinceCompany.monthlyTreesAdded

    this.logger.debug(
      `[getProvinceAreaRewardDistribution] monthIndex=${monthIndex}, currentTeamCount=${currentTeamCount}, treeCount=${treeCount}, initialTarget=${initialTarget}`,
    )

    const distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
      isSystemAccount: boolean
    }> = []

    if (currentTeamCount >= initialTarget) {
      // 已达标但权益未激活，全部给该省公司
      distributions.push({
        accountSequence: provinceCompany.userId.accountSequence,
        treeCount,
        reason: '已达初始考核目标',
        isSystemAccount: false,
      })
      // 累加当月新增树数
      provinceCompany.addMonthlyTrees(treeCount)
      // 自动激活权益
      await this.tryActivateBenefit(provinceCompany)
    } else {
      // toReachTarget: 还差多少棵达到考核目标（包括达标那一棵）
      // 业务规则：达标前的全部进系统省账户，超过达标点后才给该省公司
      const toReachTarget = Math.max(0, initialTarget - currentTeamCount)
      const afterPlantingCount = currentTeamCount + treeCount

      if (afterPlantingCount <= initialTarget) {
        // 本次认种后仍未超过目标（包括刚好达标），全部进系统省账户
        distributions.push({
          accountSequence: systemProvinceAccountId,
          treeCount,
          reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget})，进系统省账户`,
          isSystemAccount: true,
        })
        // 累加当月新增树数
        provinceCompany.addMonthlyTrees(treeCount)
        await this.authorizationRepository.save(provinceCompany)

        // 如果刚好达标，激活权益（但本批次树全部进系统省账户）
        if (afterPlantingCount === initialTarget) {
          await this.tryActivateBenefit(provinceCompany)
        }
      } else {
        // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget)
        // 达标前的部分进系统省账户
        if (toReachTarget > 0) {
          distributions.push({
            accountSequence: systemProvinceAccountId,
            treeCount: toReachTarget,
            reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})，进系统省账户`,
            isSystemAccount: true,
          })
        }
        // 超过达标点的部分，给该省公司
        const afterTargetCount = treeCount - toReachTarget
        if (afterTargetCount > 0) {
          distributions.push({
            accountSequence: provinceCompany.userId.accountSequence,
            treeCount: afterTargetCount,
            reason: `考核达标后权益生效(第${initialTarget + 1}棵起)`,
            isSystemAccount: false,
          })
        }
        // 累加当月新增树数
        provinceCompany.addMonthlyTrees(treeCount)
        // 自动激活权益（本次认种使其达标）
        await this.tryActivateBenefit(provinceCompany)
      }
    }

    this.logger.debug(`[getProvinceAreaRewardDistribution] Result: ${JSON.stringify(distributions)}`)
    return { distributions }
  }

  /**
   * 获取市团队权益分配方案 (40 USDT)
   *
   * 规则：
   * 1. 找到认种用户推荐链上最近的授权市公司（AUTH_CITY_COMPANY）
   * 2. 如果该授权市公司 benefitActive=true，全部权益给该用户
   * 3. 如果该授权市公司 benefitActive=false：
   *    - 计算还需要多少棵才能达到初始考核(500棵)
   *    - 考核前的部分给上级/总部
   *    - 考核后的部分给该用户
   * 4. 如果没有授权市公司，全部给总部
   */
  async getCityTeamRewardDistribution(
    accountSequence: string,
    cityCode: string,
    treeCount: number,
  ): Promise<{
    distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
    }>
  }> {
    this.logger.debug(
      `[getCityTeamRewardDistribution] accountSequence=${accountSequence}, cityCode=${cityCode}, treeCount=${treeCount}`,
    )

    // 系统市团队账户ID格式: 6 + 城市代码
    const systemCityTeamAccountSequence = `6${cityCode.padStart(6, '0')}`

    // 1. 获取用户的祖先链
    const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)

    if (ancestorAccountSequences.length === 0) {
      return {
        distributions: [
          { accountSequence: systemCityTeamAccountSequence, treeCount, reason: '无推荐链，进系统市团队账户' },
        ],
      }
    }

    // 2. 查找祖先链中所有授权市公司（包括 benefitActive=false）
    // 注意：市团队收益不再要求城市匹配，只要推荐链上有市团队授权即可获得收益
    const ancestorAuthCities = await this.authorizationRepository.findAuthCityByAccountSequences(
      ancestorAccountSequences,
    )

    if (ancestorAuthCities.length === 0) {
      return {
        distributions: [
          { accountSequence: systemCityTeamAccountSequence, treeCount, reason: '推荐链上无授权市公司，进系统市团队账户' },
        ],
      }
    }

    // 3. 按祖先链顺序找最近的授权市公司
    let nearestAuthCity: typeof ancestorAuthCities[0] | null = null
    let nearestIndex = -1

    for (let i = 0; i < ancestorAccountSequences.length; i++) {
      const ancestorSeq = ancestorAccountSequences[i]
      const found = ancestorAuthCities.find(
        (auth) => auth.userId.accountSequence === ancestorSeq,
      )
      if (found) {
        nearestAuthCity = found
        nearestIndex = i
        break
      }
    }

    if (!nearestAuthCity) {
      return {
        distributions: [
          { accountSequence: systemCityTeamAccountSequence, treeCount, reason: '未找到匹配的授权市公司，进系统市团队账户' },
        ],
      }
    }

    // 4. 检查权益状态
    if (nearestAuthCity.benefitActive) {
      // 权益已激活，全部给该市团队
      // 累加月度新增树数（用于月度考核）
      nearestAuthCity.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(nearestAuthCity)

      return {
        distributions: [
          { accountSequence: nearestAuthCity.userId.accountSequence, treeCount, reason: '市团队权益已激活' },
        ],
      }
    }

    // 5. 权益未激活，计算考核分配 - 使用下级团队认种数（不含自己）
    const stats = await this.statsRepository.findByAccountSequence(nearestAuthCity.userId.accountSequence)
    const rawSubordinateCount = stats?.subordinateTeamPlantingCount ?? 0
    // 修复竞态条件：减去本次认种数量来还原"认种前"的下级团队数
    const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount)
    const initialTarget = nearestAuthCity.getInitialTarget() // 500棵

    this.logger.debug(
      `[getCityTeamRewardDistribution] rawSubordinateCount=${rawSubordinateCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}`,
    )

    // 6. 查找上级
    let parentAccountSequence: string = systemCityTeamAccountSequence
    let parentReason = '上级为系统市团队账户'

    for (let i = nearestIndex + 1; i < ancestorAccountSequences.length; i++) {
      const ancestorSeq = ancestorAccountSequences[i]
      const found = ancestorAuthCities.find(
        (auth) => auth.userId.accountSequence === ancestorSeq && auth.benefitActive,
      )
      if (found) {
        parentAccountSequence = found.userId.accountSequence
        parentReason = '上级授权市公司权益已激活'
        break
      }
    }

    // 7. 计算分配
    const distributions: Array<{ accountSequence: string; treeCount: number; reason: string }> = []

    if (currentTeamCount >= initialTarget) {
      // 已达标但权益未激活（可能是月度考核失败），全部给该市团队
      // 注：这种情况下应该由系统自动激活权益，但这里作为兜底处理
      distributions.push({
        accountSequence: nearestAuthCity.userId.accountSequence,
        treeCount,
        reason: '已达初始考核目标',
      })

      // 自动激活权益
      await this.tryActivateBenefit(nearestAuthCity)

      // 累加月度新增树数（用于月度考核）
      nearestAuthCity.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(nearestAuthCity)
    } else {
      // toReachTarget: 还差多少棵达到考核目标（包括达标那一棵）
      // 业务规则：达标前的全部给上级/总部，超过达标点后才给该市团队
      const toReachTarget = Math.max(0, initialTarget - currentTeamCount)
      const afterPlantingCount = currentTeamCount + treeCount

      if (afterPlantingCount <= initialTarget) {
        // 本次认种后仍未超过目标（包括刚好达标），全部给上级/总部
        distributions.push({
          accountSequence: parentAccountSequence,
          treeCount,
          reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget})，${parentReason}`,
        })

        // 如果刚好达标，激活权益（但本批次树全部给上级）
        if (afterPlantingCount === initialTarget) {
          await this.tryActivateBenefit(nearestAuthCity)
        }
      } else {
        // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget)
        // 达标前的部分（包括第500棵）给上级/总部
        if (toReachTarget > 0) {
          distributions.push({
            accountSequence: parentAccountSequence,
            treeCount: toReachTarget,
            reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})，${parentReason}`,
          })
        }
        // 超过达标点的部分（第501棵开始），给该市团队
        const afterTargetCount = treeCount - toReachTarget
        if (afterTargetCount > 0) {
          distributions.push({
            accountSequence: nearestAuthCity.userId.accountSequence,
            treeCount: afterTargetCount,
            reason: `考核达标后权益生效(第${initialTarget + 1}棵起)`,
          })
        }

        // 自动激活权益（本次认种使其达标）
        await this.tryActivateBenefit(nearestAuthCity)

        // 激活后累加月度新增树数（只计算归自己的那部分）
        if (afterTargetCount > 0) {
          nearestAuthCity.addMonthlyTrees(afterTargetCount)
          await this.authorizationRepository.save(nearestAuthCity)
        }
      }
    }

    this.logger.debug(`[getCityTeamRewardDistribution] Result: ${JSON.stringify(distributions)}`)
    return { distributions }
  }

  /**
   * 获取市区域权益分配方案 (35 USDT + 2%算力)
   *
   * 规则：
   * 1. 查找该城市是否有正式市公司（CITY_COMPANY）
   * 2. 如果有且 benefitActive=true，权益进该市公司自己的账户，并累加 monthlyTreesAdded
   * 3. 如果有但 benefitActive=false（考核中）：
   *    - 使用阶梯考核目标（第一个月30棵，逐月递增）
   *    - 计算还需要多少棵才能达到当前月份的考核目标
   *    - 考核前的部分进系统市账户
   *    - 考核后的部分给该市公司
   * 4. 如果没有正式市公司，全部进系统市账户
   */
  async getCityAreaRewardDistribution(
    cityCode: string,
    treeCount: number,
  ): Promise<{
    distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
      isSystemAccount: boolean
    }>
  }> {
    this.logger.debug(
      `[getCityAreaRewardDistribution] cityCode=${cityCode}, treeCount=${treeCount}`,
    )

    // 系统市账户ID格式: 8 + 城市代码
    const systemCityAccountId = `8${cityCode.padStart(6, '0')}`

    // 查找该城市的正式市公司
    const cityCompany = await this.authorizationRepository.findCityCompanyByRegion(cityCode)

    if (!cityCompany) {
      // 无正式市公司，全部进系统市账户
      return {
        distributions: [
          {
            accountSequence: systemCityAccountId,
            treeCount,
            reason: '无正式市公司授权，进系统市账户',
            isSystemAccount: true,
          },
        ],
      }
    }

    if (cityCompany.benefitActive) {
      // 正式市公司权益已激活，进该市公司账户
      // 累加月度新增树数（用于后续月度考核）
      cityCompany.addMonthlyTrees(treeCount)
      await this.authorizationRepository.save(cityCompany)

      return {
        distributions: [
          {
            accountSequence: cityCompany.userId.accountSequence,
            treeCount,
            reason: '市区域权益已激活',
            isSystemAccount: false,
          },
        ],
      }
    }

    // 权益未激活，计算考核分配 - 使用阶梯目标
    // 对于未激活的正式市公司，使用第一个月的目标(30棵)进行初始考核
    const monthIndex = cityCompany.currentMonthIndex || 1
    const ladderTarget = LadderTargetRule.getTarget(RoleType.CITY_COMPANY, monthIndex)
    const initialTarget = ladderTarget.monthlyTarget  // 第一个月30棵

    // 获取当前月度新增树数
    const rawMonthlyCount = cityCompany.monthlyTreesAdded ?? 0
    // 修复竞态条件：减去本次认种数量来还原"认种前"的月度数
    const currentMonthlyCount = Math.max(0, rawMonthlyCount - treeCount)

    this.logger.debug(
      `[getCityAreaRewardDistribution] rawMonthlyCount=${rawMonthlyCount}, treeCount=${treeCount}, currentMonthlyCount(before)=${currentMonthlyCount}, initialTarget=${initialTarget}, monthIndex=${monthIndex}`,
    )

    const distributions: Array<{
      accountSequence: string
      treeCount: number
      reason: string
      isSystemAccount: boolean
    }> = []

    if (currentMonthlyCount >= initialTarget) {
      // 已达标但权益未激活，全部给该市公司
      distributions.push({
        accountSequence: cityCompany.userId.accountSequence,
        treeCount,
        reason: '已达初始考核目标',
        isSystemAccount: false,
      })
      // 自动激活权益
      await this.tryActivateBenefit(cityCompany)
    } else {
      // toReachTarget: 还差多少棵达到考核目标（包括达标那一棵）
      // 业务规则：达标前的全部进系统市账户，超过达标点后才给该市公司
      const toReachTarget = Math.max(0, initialTarget - currentMonthlyCount)
      const afterPlantingCount = currentMonthlyCount + treeCount

      if (afterPlantingCount <= initialTarget) {
        // 本次认种后仍未超过目标（包括刚好达标），全部进系统市账户
        distributions.push({
          accountSequence: systemCityAccountId,
          treeCount,
          reason: `初始考核中(${currentMonthlyCount}+${treeCount}=${afterPlantingCount}/${initialTarget})，进系统市账户`,
          isSystemAccount: true,
        })

        // 累加月度新增树数（用于月底考核）
        cityCompany.addMonthlyTrees(treeCount)
        await this.authorizationRepository.save(cityCompany)

        // 如果刚好达标，激活权益（但本批次树全部进系统市账户）
        if (afterPlantingCount === initialTarget) {
          await this.tryActivateBenefit(cityCompany)
        }
      } else {
        // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget)
        // 达标前的部分进系统市账户
        if (toReachTarget > 0) {
          distributions.push({
            accountSequence: systemCityAccountId,
            treeCount: toReachTarget,
            reason: `初始考核(${currentMonthlyCount}+${toReachTarget}=${initialTarget}/${initialTarget})，进系统市账户`,
            isSystemAccount: true,
          })
        }
        // 超过达标点的部分，给该市公司
        const afterTargetCount = treeCount - toReachTarget
        if (afterTargetCount > 0) {
          distributions.push({
            accountSequence: cityCompany.userId.accountSequence,
            treeCount: afterTargetCount,
            reason: `考核达标后权益生效(第${initialTarget + 1}棵起)`,
            isSystemAccount: false,
          })
        }

        // 累加月度新增树数
        cityCompany.addMonthlyTrees(treeCount)
        await this.authorizationRepository.save(cityCompany)

        // 自动激活权益（本次认种使其达标）
        await this.tryActivateBenefit(cityCompany)
      }
    }

    this.logger.debug(`[getCityAreaRewardDistribution] Result: ${JSON.stringify(distributions)}`)
    return { distributions }
  }

  /**
   * 处理过期的正式市公司权益（月度考核）
   *
   * 业务规则：
   * - 检查所有 benefitValidUntil < 当前时间 且 benefitActive=true 的正式市公司
   * - 获取当前月份索引对应的阶梯目标
   * - 如果月度新增树数 >= 阶梯目标，续期并递增月份索引
   * - 如果不达标，停用权益并重置月份索引为0
   */
  async processExpiredCityCompanyBenefits(
    limit: number,
  ): Promise<{ processedCount: number; renewedCount: number; deactivatedCount: number }> {
    const now = new Date()
    const expiredCityCompanies = await this.authorizationRepository.findExpiredActiveByRoleType(
      RoleType.CITY_COMPANY,
      now,
      limit,
    )

    let renewedCount = 0
    let deactivatedCount = 0

    for (const cityCompany of expiredCityCompanies) {
      // 获取当前月份索引对应的阶梯目标
      const monthIndex = cityCompany.currentMonthIndex || 1
      const ladderTarget = LadderTargetRule.getTarget(RoleType.CITY_COMPANY, monthIndex)
      const monthlyTarget = ladderTarget.monthlyTarget
      const cumulativeTarget = ladderTarget.cumulativeTarget

      // 获取用于考核的树数
      const treesForAssessment = cityCompany.getTreesForAssessment(now)

      this.logger.debug(
        `[processExpiredCityCompanyBenefits] ${cityCompany.userId.accountSequence}: ` +
        `monthIndex=${monthIndex}, target=${monthlyTarget}, trees=${treesForAssessment}`,
      )

      // 计算考核月份：基于 benefitValidUntil
      const assessmentMonth = cityCompany.benefitValidUntil
        ? Month.fromDate(cityCompany.benefitValidUntil)
        : Month.current().previous()

      const previousBenefitStatus = cityCompany.benefitActive

      try {
        if (treesForAssessment >= monthlyTarget) {
          // 先生成考核记录（达标）
          await this.createCompanyAssessmentRecord(
            cityCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesForAssessment,
            AssessmentResult.PASS,
          )

          // 达标：续期权益并递增月份索引
          cityCompany.renewBenefit(treesForAssessment)
          cityCompany.incrementMonthIndex()
          await this.authorizationRepository.save(cityCompany)

          // [2026-01-08] 保存权益考核记录到新表
          await this.saveBenefitAssessmentRecord({
            authorization: cityCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesCompleted: treesForAssessment,
            treesRequired: monthlyTarget,
            benefitActionTaken: BenefitActionType.RENEWED,
            previousBenefitStatus,
            newBenefitStatus: true,
            newValidUntil: cityCompany.benefitValidUntil,
            result: AssessmentResult.PASS,
            remarks: `续期成功：完成${treesForAssessment}棵，达到第${monthIndex}月目标${monthlyTarget}棵`,
          })

          renewedCount++

          this.logger.log(
            `[processExpiredCityCompanyBenefits] ${cityCompany.userId.accountSequence} 考核达标，续期成功`,
          )
        } else {
          // 先生成考核记录（不达标）
          await this.createCompanyAssessmentRecord(
            cityCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesForAssessment,
            AssessmentResult.FAIL,
          )

          // [2026-01-08] 保存权益考核记录到新表（失效）
          await this.saveBenefitAssessmentRecord({
            authorization: cityCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesCompleted: treesForAssessment,
            treesRequired: monthlyTarget,
            benefitActionTaken: BenefitActionType.DEACTIVATED,
            previousBenefitStatus,
            newBenefitStatus: false,
            newValidUntil: null,
            result: AssessmentResult.FAIL,
            remarks: `考核不达标：完成${treesForAssessment}棵，未达到第${monthIndex}月目标${monthlyTarget}棵`,
          })

          // 不达标：停用权益
          cityCompany.deactivateBenefit(`月度考核不达标(${treesForAssessment}/${monthlyTarget})`)
          await this.authorizationRepository.save(cityCompany)

          await this.eventPublisher.publishAll(cityCompany.domainEvents)
          cityCompany.clearDomainEvents()

          deactivatedCount++

          this.logger.log(
            `[processExpiredCityCompanyBenefits] ${cityCompany.userId.accountSequence} 考核不达标，权益已停用`,
          )
        }
      } catch (error) {
        this.logger.error(
          `[processExpiredCityCompanyBenefits] Failed to process ${cityCompany.userId.accountSequence}: ${error}`,
        )
      }
    }

    return {
      processedCount: expiredCityCompanies.length,
      renewedCount,
      deactivatedCount,
    }
  }

  /**
   * 获取过期的正式市公司授权列表
   */
  async findExpiredCityCompanyBenefits(
    checkDate: Date,
    limit: number,
  ): Promise<AuthorizationRole[]> {
    return this.authorizationRepository.findExpiredActiveByRoleType(
      RoleType.CITY_COMPANY,
      checkDate,
      limit,
    )
  }

  /**
   * 处理过期的正式省公司权益
   *
   * 业务规则：
   * - 检查所有 benefitValidUntil < 当前时间 且 benefitActive=true 的正式省公司
   * - 使用阶梯目标（第1月150，第2月300，...，第9月11750）
   * - 如果当月新增树数达标，续期并递增月份索引
   * - 如果不达标，停用权益并重置月份索引到1
   */
  async processExpiredProvinceCompanyBenefits(
    limit: number,
  ): Promise<{ processedCount: number; renewedCount: number; deactivatedCount: number }> {
    const now = new Date()
    const expiredProvinceCompanies = await this.authorizationRepository.findExpiredActiveByRoleType(
      RoleType.PROVINCE_COMPANY,
      now,
      limit,
    )

    let renewedCount = 0
    let deactivatedCount = 0

    for (const provinceCompany of expiredProvinceCompanies) {
      // 获取当前月份索引对应的阶梯目标
      const monthIndex = provinceCompany.currentMonthIndex || 1
      const ladderTarget = LadderTargetRule.getTarget(RoleType.PROVINCE_COMPANY, monthIndex)
      const monthlyTarget = ladderTarget.monthlyTarget
      const cumulativeTarget = ladderTarget.cumulativeTarget

      // 获取用于考核的树数
      const treesForAssessment = provinceCompany.getTreesForAssessment(now)

      this.logger.debug(
        `[processExpiredProvinceCompanyBenefits] ${provinceCompany.userId.accountSequence}: ` +
        `monthIndex=${monthIndex}, target=${monthlyTarget}, trees=${treesForAssessment}`,
      )

      // 计算考核月份：基于 benefitValidUntil
      const assessmentMonth = provinceCompany.benefitValidUntil
        ? Month.fromDate(provinceCompany.benefitValidUntil)
        : Month.current().previous()

      const previousBenefitStatus = provinceCompany.benefitActive

      try {
        if (treesForAssessment >= monthlyTarget) {
          // 先生成考核记录（达标）
          await this.createCompanyAssessmentRecord(
            provinceCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesForAssessment,
            AssessmentResult.PASS,
          )

          // 达标：续期权益并递增月份索引
          provinceCompany.renewBenefit(treesForAssessment)
          provinceCompany.incrementMonthIndex()
          await this.authorizationRepository.save(provinceCompany)

          // [2026-01-08] 保存权益考核记录到新表
          await this.saveBenefitAssessmentRecord({
            authorization: provinceCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesCompleted: treesForAssessment,
            treesRequired: monthlyTarget,
            benefitActionTaken: BenefitActionType.RENEWED,
            previousBenefitStatus,
            newBenefitStatus: true,
            newValidUntil: provinceCompany.benefitValidUntil,
            result: AssessmentResult.PASS,
            remarks: `续期成功：完成${treesForAssessment}棵，达到第${monthIndex}月目标${monthlyTarget}棵`,
          })

          renewedCount++

          this.logger.log(
            `[processExpiredProvinceCompanyBenefits] ${provinceCompany.userId.accountSequence} 考核达标，续期成功`,
          )
        } else {
          // 先生成考核记录（不达标）
          await this.createCompanyAssessmentRecord(
            provinceCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesForAssessment,
            AssessmentResult.FAIL,
          )

          // [2026-01-08] 保存权益考核记录到新表（失效）
          await this.saveBenefitAssessmentRecord({
            authorization: provinceCompany,
            assessmentMonth,
            monthIndex,
            monthlyTarget,
            cumulativeTarget,
            treesCompleted: treesForAssessment,
            treesRequired: monthlyTarget,
            benefitActionTaken: BenefitActionType.DEACTIVATED,
            previousBenefitStatus,
            newBenefitStatus: false,
            newValidUntil: null,
            result: AssessmentResult.FAIL,
            remarks: `考核不达标：完成${treesForAssessment}棵，未达到第${monthIndex}月目标${monthlyTarget}棵`,
          })

          // 不达标：停用权益
          provinceCompany.deactivateBenefit(`月度考核不达标(${treesForAssessment}/${monthlyTarget})`)
          await this.authorizationRepository.save(provinceCompany)

          await this.eventPublisher.publishAll(provinceCompany.domainEvents)
          provinceCompany.clearDomainEvents()

          deactivatedCount++

          this.logger.log(
            `[processExpiredProvinceCompanyBenefits] ${provinceCompany.userId.accountSequence} 考核不达标，权益已停用`,
          )
        }
      } catch (error) {
        this.logger.error(
          `[processExpiredProvinceCompanyBenefits] Failed to process ${provinceCompany.userId.accountSequence}: ${error}`,
        )
      }
    }

    return {
      processedCount: expiredProvinceCompanies.length,
      renewedCount,
      deactivatedCount,
    }
  }

  /**
   * 获取过期的正式省公司授权列表
   */
  async findExpiredProvinceCompanyBenefits(
    checkDate: Date,
    limit: number,
  ): Promise<AuthorizationRole[]> {
    return this.authorizationRepository.findExpiredActiveByRoleType(
      RoleType.PROVINCE_COMPANY,
      checkDate,
      limit,
    )
  }

  // ============================================
  // 自助申请授权相关方法
  // ============================================

  /**
   * 获取用户授权状态
   * 用于自助申请页面显示用户当前状态
   */
  async getUserAuthorizationStatus(
    accountSequence: string,
  ): Promise<UserAuthorizationStatusResponseDto> {
    this.logger.log(`[getUserAuthorizationStatus] accountSequence=${accountSequence}`)

    // 1. 获取用户认种数据
    const teamStats = await this.statsRepository.findByAccountSequence(accountSequence)
    const hasPlanted = (teamStats?.selfPlantingCount || 0) > 0
    const plantedCount = teamStats?.selfPlantingCount || 0

    // 2. 获取用户已有的授权
    const authorizations = await this.authorizationRepository.findByAccountSequence(accountSequence)
    const existingAuthorizations = authorizations
      .filter(auth => auth.status !== AuthorizationStatus.REVOKED)
      .map(auth => this.mapRoleTypeToDisplayName(auth.roleType))

    // 3. 查找团队链中已被占用的城市和省份
    const teamChainOccupiedCities = await this.findTeamChainOccupiedRegions(
      accountSequence,
      RoleType.AUTH_CITY_COMPANY,
    )
    const teamChainOccupiedProvinces = await this.findTeamChainOccupiedRegions(
      accountSequence,
      RoleType.AUTH_PROVINCE_COMPANY,
    )

    return {
      hasPlanted,
      plantedCount,
      existingAuthorizations,
      teamChainOccupiedCities,
      teamChainOccupiedProvinces,
    }
  }

  /**
   * 自助申请授权
   */
  async selfApplyAuthorization(
    command: SelfApplyAuthorizationCommand,
  ): Promise<SelfApplyAuthorizationResponseDto> {
    this.logger.log(
      `[selfApplyAuthorization] userId=${command.userId}, type=${command.type}, ` +
      `photos=${command.officePhotoUrls.length}`,
    )

    // 1. 验证用户已认种
    const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence)
    const selfPlantingCount = teamStats?.selfPlantingCount || 0
    if (selfPlantingCount <= 0) {
      throw new ApplicationError('申请授权需要先完成认种')
    }

    // 2. 验证照片数量
    if (command.officePhotoUrls.length < 2) {
      throw new ApplicationError('请至少上传2张办公室照片')
    }
    if (command.officePhotoUrls.length > 6) {
      throw new ApplicationError('最多上传6张办公室照片')
    }

    // 3. 根据申请类型处理
    let result: SelfApplyAuthorizationResponseDto

    switch (command.type) {
      case SelfApplyAuthorizationType.COMMUNITY:
        if (!command.communityName) {
          throw new ApplicationError('申请社区授权需要提供社区名称')
        }
        result = await this.processCommunityApplication(command)
        break

      case SelfApplyAuthorizationType.CITY_TEAM:
        if (!command.cityCode || !command.cityName) {
          throw new ApplicationError('申请市团队授权需要提供城市信息')
        }
        result = await this.processCityTeamApplication(command)
        break

      case SelfApplyAuthorizationType.PROVINCE_TEAM:
        if (!command.provinceCode || !command.provinceName) {
          throw new ApplicationError('申请省团队授权需要提供省份信息')
        }
        result = await this.processProvinceTeamApplication(command)
        break

      default:
        throw new ApplicationError('不支持的授权类型')
    }

    return result
  }

  /**
   * 处理社区授权申请
   */
  private async processCommunityApplication(
    command: SelfApplyAuthorizationCommand,
  ): Promise<SelfApplyAuthorizationResponseDto> {
    // 检查是否已有社区授权
    const existing = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      command.accountSequence,
      RoleType.COMMUNITY,
    )
    if (existing && existing.status !== AuthorizationStatus.REVOKED) {
      throw new ApplicationError('您已拥有社区授权')
    }

    // 直接创建授权（自助申请的社区授权直接生效，状态为 AUTHORIZED）
    const userId = UserId.create(command.userId, command.accountSequence)
    const authorization = AuthorizationRole.createSelfAppliedCommunity({
      userId,
      communityName: command.communityName!,
      officePhotoUrls: command.officePhotoUrls,
    })

    // 检查初始考核
    const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence)
    const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0
    if (subordinateTreeCount >= authorization.getInitialTarget()) {
      authorization.activateBenefit()
    }

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()

    return {
      authorizationId: authorization.authorizationId.value,
      type: SelfApplyAuthorizationType.COMMUNITY,
      grantedAt: new Date(),
      benefitsActivated: authorization.benefitActive,
    }
  }

  /**
   * 处理市团队授权申请
   */
  private async processCityTeamApplication(
    command: SelfApplyAuthorizationCommand,
  ): Promise<SelfApplyAuthorizationResponseDto> {
    // 检查用户是否已拥有省团队授权（市团队和省团队互斥，只能二选一）
    const userAuthorizations = await this.authorizationRepository.findByAccountSequence(command.accountSequence)
    const hasProvinceTeam = userAuthorizations.some(
      auth => auth.roleType === RoleType.AUTH_PROVINCE_COMPANY && auth.status !== AuthorizationStatus.REVOKED,
    )
    if (hasProvinceTeam) {
      throw new ApplicationError('您已拥有省团队授权，市团队和省团队只能二选一')
    }

    // 检查是否已有该市的授权市公司（全局唯一性）
    const existingList = await this.authorizationRepository.findActiveByRoleTypeAndRegion(
      RoleType.AUTH_CITY_COMPANY,
      RegionCode.create(command.cityCode!),
    )
    if (existingList.length > 0) {
      throw new ApplicationError('该市已有授权市公司')
    }

    // 检查团队链中是否已有人申请该城市（团队链唯一性）
    const occupiedCities = await this.findTeamChainOccupiedRegions(
      command.accountSequence,
      RoleType.AUTH_CITY_COMPANY,
    )
    const isCityOccupiedInChain = occupiedCities.some(r => r.regionCode === command.cityCode)
    if (isCityOccupiedInChain) {
      throw new ApplicationError(`您的团队链中已有人申请了「${command.cityName}」的市团队授权`)
    }

    // 创建授权市公司授权（自助申请直接生效，状态为 AUTHORIZED）
    const userId = UserId.create(command.userId, command.accountSequence)
    const authorization = AuthorizationRole.createSelfAppliedAuthCityCompany({
      userId,
      cityCode: command.cityCode!,
      cityName: command.cityName!,
      officePhotoUrls: command.officePhotoUrls,
    })

    // 检查初始考核（500棵）
    const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence)
    const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0
    if (subordinateTreeCount >= authorization.getInitialTarget()) {
      authorization.activateBenefit()
    }

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()

    return {
      authorizationId: authorization.authorizationId.value,
      type: SelfApplyAuthorizationType.CITY_TEAM,
      grantedAt: new Date(),
      benefitsActivated: authorization.benefitActive,
    }
  }

  /**
   * 处理省团队授权申请
   */
  private async processProvinceTeamApplication(
    command: SelfApplyAuthorizationCommand,
  ): Promise<SelfApplyAuthorizationResponseDto> {
    // 检查用户是否已拥有市团队授权（市团队和省团队互斥，只能二选一）
    const userAuthorizations = await this.authorizationRepository.findByAccountSequence(command.accountSequence)
    const hasCityTeam = userAuthorizations.some(
      auth => auth.roleType === RoleType.AUTH_CITY_COMPANY && auth.status !== AuthorizationStatus.REVOKED,
    )
    if (hasCityTeam) {
      throw new ApplicationError('您已拥有市团队授权，市团队和省团队只能二选一')
    }

    // 检查是否已有该省的授权省公司（全局唯一性）
    const existingList = await this.authorizationRepository.findActiveByRoleTypeAndRegion(
      RoleType.AUTH_PROVINCE_COMPANY,
      RegionCode.create(command.provinceCode!),
    )
    if (existingList.length > 0) {
      throw new ApplicationError('该省已有授权省公司')
    }

    // 检查团队链中是否已有人申请该省份（团队链唯一性）
    const occupiedProvinces = await this.findTeamChainOccupiedRegions(
      command.accountSequence,
      RoleType.AUTH_PROVINCE_COMPANY,
    )
    const isProvinceOccupiedInChain = occupiedProvinces.some(r => r.regionCode === command.provinceCode)
    if (isProvinceOccupiedInChain) {
      throw new ApplicationError(`您的团队链中已有人申请了「${command.provinceName}」的省团队授权`)
    }

    // 创建授权省公司授权（自助申请直接生效，状态为 AUTHORIZED）
    const userId = UserId.create(command.userId, command.accountSequence)
    const authorization = AuthorizationRole.createSelfAppliedAuthProvinceCompany({
      userId,
      provinceCode: command.provinceCode!,
      provinceName: command.provinceName!,
      officePhotoUrls: command.officePhotoUrls,
    })

    // 检查初始考核（500棵）
    const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence)
    const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0
    if (subordinateTreeCount >= authorization.getInitialTarget()) {
      authorization.activateBenefit()
    }

    await this.authorizationRepository.save(authorization)
    await this.eventPublisher.publishAll(authorization.domainEvents)
    authorization.clearDomainEvents()

    return {
      authorizationId: authorization.authorizationId.value,
      type: SelfApplyAuthorizationType.PROVINCE_TEAM,
      grantedAt: new Date(),
      benefitsActivated: authorization.benefitActive,
    }
  }

  /**
   * 查找团队链中指定类型的所有已占用区域
   * 遍历用户的祖先链（推荐链），收集所有已被占用的城市/省份
   *
   * @returns 已占用区域列表（包含持有者信息和区域信息）
   */
  private async findTeamChainOccupiedRegions(
    accountSequence: string,
    roleType: RoleType.AUTH_CITY_COMPANY | RoleType.AUTH_PROVINCE_COMPANY,
  ): Promise<TeamChainOccupiedRegionDto[]> {
    const occupiedRegions: TeamChainOccupiedRegionDto[] = []

    try {
      // 获取用户的祖先链（推荐链）
      const ancestorChain = await this.referralServiceClient.getReferralChain(accountSequence)
      if (!ancestorChain || ancestorChain.length === 0) {
        return occupiedRegions
      }

      // 遍历祖先链，收集所有持有该类型授权的区域
      for (const ancestorAccountSeq of ancestorChain) {
        const authorizations = await this.authorizationRepository.findByAccountSequence(ancestorAccountSeq)
        const matchingAuths = authorizations.filter(
          auth => auth.roleType === roleType && auth.status !== AuthorizationStatus.REVOKED,
        )

        for (const auth of matchingAuths) {
          // 获取用户昵称（使用 accountSequence）
          const userInfo = await this.identityServiceClient.getUserInfoBySequence(auth.userId.accountSequence)
          occupiedRegions.push({
            accountSequence: ancestorAccountSeq,
            nickname: userInfo?.nickname || `用户${ancestorAccountSeq}`,
            regionCode: auth.regionCode?.value || '',
            regionName: auth.regionName || '',
          })
        }
      }

      return occupiedRegions
    } catch (error) {
      this.logger.error(`[findTeamChainOccupiedRegions] Error: ${error}`)
      return occupiedRegions
    }
  }

  private mapRoleTypeToDisplayName(roleType: RoleType): string {
    const mapping: Record<RoleType, string> = {
      [RoleType.COMMUNITY]: '社区',
      [RoleType.AUTH_CITY_COMPANY]: '市团队',
      [RoleType.AUTH_PROVINCE_COMPANY]: '省团队',
      [RoleType.CITY_COMPANY]: '市区域',
      [RoleType.PROVINCE_COMPANY]: '省区域',
    }
    return mapping[roleType] || roleType
  }

  // ============================================
  // 用户资料相关方法
  // ============================================

  /**
   * 获取用户公开资料
   * 任何登录用户都可以查看，不包含敏感信息
   *
   * @param targetAccountSequence 目标用户的 accountSequence
   */
  async getUserPublicProfile(targetAccountSequence: string): Promise<{
    userId: string
    accountSequence: string
    nickname: string
    avatarUrl?: string
    registeredAt: string
    inviterSequence?: string
    inviterNickname?: string
    directReferralCount: number
    umbrellaUserCount: number
    province?: string
    city?: string
    personalPlantingCount: number
    teamPlantingCount: number
    authorizations: Array<{
      authorizationId: string
      roleType: RoleType
      regionCode: string
      regionName: string
      displayTitle: string
      benefitActive: boolean
    }>
  }> {
    this.logger.debug(`[getUserPublicProfile] targetAccountSequence=${targetAccountSequence}`)

    // 1. 获取基本用户信息
    const userInfo = await this.identityServiceClient.getUserInfoBySequence(targetAccountSequence)
    if (!userInfo) {
      throw new NotFoundError('用户不存在')
    }

    // 2. 获取推荐关系统计
    const profileStats = await this.referralServiceClient.getUserProfileStats(targetAccountSequence)

    // 3. 获取推荐人信息
    let inviterNickname: string | undefined
    const referralChain = await this.referralServiceClient.getReferralChain(targetAccountSequence)
    if (referralChain.length > 0) {
      const inviterInfo = await this.identityServiceClient.getUserInfoBySequence(referralChain[0])
      inviterNickname = inviterInfo?.nickname
    }

    // 4. 获取用户的授权列表
    const authorizations = await this.authorizationRepository.findByAccountSequence(targetAccountSequence)
    const activeAuthorizations = authorizations.filter(
      (auth) => auth.status !== AuthorizationStatus.REVOKED,
    )

    // 5. 获取省市信息（从授权中提取，优先取省团队/市团队授权的区域）
    let province: string | undefined
    let city: string | undefined
    for (const auth of activeAuthorizations) {
      if (auth.roleType === RoleType.AUTH_PROVINCE_COMPANY || auth.roleType === RoleType.PROVINCE_COMPANY) {
        province = auth.regionName
      }
      if (auth.roleType === RoleType.AUTH_CITY_COMPANY || auth.roleType === RoleType.CITY_COMPANY) {
        city = auth.regionName
      }
    }

    // 6. 从用户详情获取注册时间和推荐人序列号
    const userDetail = await this.identityServiceClient.getUserDetailBySequence(targetAccountSequence)

    return {
      userId: userInfo.userId,
      accountSequence: userInfo.accountSequence,
      nickname: userInfo.nickname,
      avatarUrl: userInfo.avatarUrl,
      registeredAt: userDetail?.registeredAt || new Date().toISOString(),
      inviterSequence: userDetail?.inviterSequence,
      inviterNickname,
      directReferralCount: profileStats.directReferralCount,
      umbrellaUserCount: profileStats.umbrellaUserCount,
      province,
      city,
      personalPlantingCount: profileStats.personalPlantingCount,
      teamPlantingCount: profileStats.teamPlantingCount,
      authorizations: activeAuthorizations.map((auth) => ({
        authorizationId: auth.authorizationId.value,
        roleType: auth.roleType,
        regionCode: auth.regionCode.value,
        regionName: auth.regionName,
        displayTitle: auth.displayTitle,
        benefitActive: auth.benefitActive,
      })),
    }
  }

  /**
   * 获取用户私密资料（包含敏感信息）
   * 仅特权用户可以查看（省团队以上级别）
   *
   * @param requestAccountSequence 请求者的 accountSequence
   * @param targetAccountSequence 目标用户的 accountSequence
   */
  async getUserPrivateProfile(
    requestAccountSequence: string,
    targetAccountSequence: string,
  ): Promise<{
    userId: string
    accountSequence: string
    nickname: string
    avatarUrl?: string
    phoneNumber?: string
    email?: string
    realName?: string
    kycStatus: string
    registeredAt: string
    inviterSequence?: string
    inviterNickname?: string
    directReferralCount: number
    umbrellaUserCount: number
    province?: string
    city?: string
    personalPlantingCount: number
    teamPlantingCount: number
    authorizations: Array<{
      authorizationId: string
      roleType: RoleType
      regionCode: string
      regionName: string
      displayTitle: string
      benefitActive: boolean
    }>
  }> {
    this.logger.debug(
      `[getUserPrivateProfile] requestAccountSequence=${requestAccountSequence}, targetAccountSequence=${targetAccountSequence}`,
    )

    // 1. 验证请求者是否有权限查看私密资料
    const hasPrivilege = await this.checkPrivateProfileAccess(requestAccountSequence, targetAccountSequence)
    if (!hasPrivilege) {
      throw new ApplicationError('您没有权限查看该用户的详细信息')
    }

    // 2. 获取公开资料
    const publicProfile = await this.getUserPublicProfile(targetAccountSequence)

    // 3. 获取敏感信息
    const userDetail = await this.identityServiceClient.getUserDetailBySequence(targetAccountSequence)

    // 4. 脱敏处理手机号和邮箱
    const maskedPhoneNumber = userDetail?.phoneNumber
      ? this.maskPhoneNumber(userDetail.phoneNumber)
      : undefined
    const maskedEmail = userDetail?.email
      ? this.maskEmail(userDetail.email)
      : undefined
    const maskedRealName = userDetail?.realName
      ? this.maskRealName(userDetail.realName)
      : undefined

    return {
      ...publicProfile,
      phoneNumber: maskedPhoneNumber,
      email: maskedEmail,
      realName: maskedRealName,
      kycStatus: userDetail?.kycStatus || 'NOT_VERIFIED',
    }
  }

  /**
   * 检查用户是否有权限查看私密资料
   *
   * 注意：目前系统尚未实现权限管理功能，暂时禁止所有用户查看私密资料。
   * 后续实现权限系统后，可以根据以下规则开放：
   * - 省区域公司(PROVINCE_COMPANY)可以查看
   * - 省团队(AUTH_PROVINCE_COMPANY)可以查看
   * - 市区域公司(CITY_COMPANY)可以查看
   * - 其他角色不能查看
   */
  private async checkPrivateProfileAccess(
    _requestAccountSequence: string,
    _targetAccountSequence: string,
  ): Promise<boolean> {
    // TODO: 权限系统实现后，取消下面的注释并启用权限检查
    // const requestorAuthorizations = await this.authorizationRepository.findByAccountSequence(requestAccountSequence)
    // const privilegedRoleTypes = [
    //   RoleType.PROVINCE_COMPANY,
    //   RoleType.AUTH_PROVINCE_COMPANY,
    //   RoleType.CITY_COMPANY,
    // ]
    // return requestorAuthorizations.some(
    //   (auth) =>
    //     auth.status === AuthorizationStatus.AUTHORIZED &&
    //     privilegedRoleTypes.includes(auth.roleType),
    // )

    // 目前暂时禁止所有用户查看私密资料
    return false
  }

  /**
   * 手机号脱敏：138****1234
   */
  private maskPhoneNumber(phone: string): string {
    if (phone.length < 7) return phone
    return phone.substring(0, 3) + '****' + phone.substring(phone.length - 4)
  }

  /**
   * 邮箱脱敏：t***@example.com
   */
  private maskEmail(email: string): string {
    const atIndex = email.indexOf('@')
    if (atIndex < 2) return email
    return email.substring(0, 1) + '***' + email.substring(atIndex)
  }

  /**
   * 姓名脱敏：张*明
   */
  private maskRealName(name: string): string {
    if (name.length <= 1) return name
    if (name.length === 2) return name[0] + '*'
    return name[0] + '*'.repeat(name.length - 2) + name[name.length - 1]
  }

  // ============ 管理员查询方法 ============

  /**
   * 查询授权列表（管理员用）
   */
  async queryAuthorizations(params: {
    roleType?: RoleType
    keyword?: string
    includeRevoked?: boolean
    page?: number
    limit?: number
  }): Promise<{
    items: Array<{
      id: string
      accountSequence: string
      nickname: string
      avatar: string | null
      roleType: RoleType
      regionName: string
      status: AuthorizationStatus
      benefitActive: boolean
      createdAt: Date
      authorizedAt: Date | null
      revokedAt: Date | null
      revokeReason: string | null
      officePhotoUrls: string[]
    }>
    total: number
    page: number
    limit: number
  }> {
    const page = params.page ?? 1
    const limit = params.limit ?? 20
    const includeRevoked = params.includeRevoked ?? false

    this.logger.log(`[queryAuthorizations] 查询参数: roleType=${params.roleType}, includeRevoked=${includeRevoked}, page=${page}, limit=${limit}`)

    // 获取所有授权（管理员应该能看到所有已授权的用户，包括考核期的）
    let allAuthorizations: AuthorizationRole[] = await this.authorizationRepository.findByStatus(
      AuthorizationStatus.AUTHORIZED,
    )
    this.logger.log(`[queryAuthorizations] 查询到 AUTHORIZED 授权数量: ${allAuthorizations.length}`)

    // 按 roleType 过滤
    if (params.roleType) {
      allAuthorizations = allAuthorizations.filter((a) => a.roleType === params.roleType)
    }

    // 如果包含已撤销的，需要添加已撤销的授权
    if (includeRevoked) {
      const revokedAuths = await this.authorizationRepository.findByStatus(AuthorizationStatus.REVOKED)
      // 过滤 roleType
      const filteredRevoked = params.roleType
        ? revokedAuths.filter((a) => a.roleType === params.roleType)
        : revokedAuths
      allAuthorizations = [...allAuthorizations, ...filteredRevoked]
    }

    // 获取用户信息
    const accountSequences = [...new Set(allAuthorizations.map((a) => a.userId.accountSequence))]
    let usersMap = new Map<string, { nickname: string; avatar: string | null }>()

    if (accountSequences.length > 0) {
      try {
        const usersInfoMap = await this.identityServiceClient.batchGetUserInfoBySequence(accountSequences)
        usersInfoMap.forEach((userInfo, accountSequence) => {
          usersMap.set(accountSequence, { nickname: userInfo.nickname, avatar: userInfo.avatarUrl ?? null })
        })
      } catch (e) {
        this.logger.warn(`获取用户信息失败: ${e}`)
      }
    }

    // 关键词过滤
    let filteredAuthorizations = allAuthorizations
    if (params.keyword) {
      const keyword = params.keyword.toLowerCase()
      filteredAuthorizations = allAuthorizations.filter((auth) => {
        const userInfo = usersMap.get(auth.userId.accountSequence)
        return (
          auth.userId.accountSequence.toLowerCase().includes(keyword) ||
          auth.regionName.toLowerCase().includes(keyword) ||
          (userInfo?.nickname && userInfo.nickname.toLowerCase().includes(keyword))
        )
      })
    }

    // 排序：按创建时间降序
    filteredAuthorizations.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())

    // 分页
    const total = filteredAuthorizations.length
    const startIndex = (page - 1) * limit
    const pagedAuthorizations = filteredAuthorizations.slice(startIndex, startIndex + limit)

    // 构建响应
    const items = pagedAuthorizations.map((auth) => {
      const userInfo = usersMap.get(auth.userId.accountSequence)
      return {
        id: auth.authorizationId.value,
        accountSequence: auth.userId.accountSequence,
        nickname: userInfo?.nickname ?? auth.userId.accountSequence,
        avatar: userInfo?.avatar ?? null,
        roleType: auth.roleType,
        regionName: auth.regionName,
        status: auth.status,
        benefitActive: auth.benefitActive,
        createdAt: auth.createdAt,
        authorizedAt: auth.authorizedAt,
        revokedAt: auth.revokedAt,
        revokeReason: auth.revokeReason,
        officePhotoUrls: auth.officePhotoUrls,
      }
    })

    return { items, total, page, limit }
  }

  // ============================================================================
  // [2026-01-08] 新增：权益有效性考核记录
  // 保存到独立的 BenefitAssessmentRecord 表，与火柴人排名（MonthlyAssessment）分离
  // ============================================================================

  /**
   * 创建权益有效性考核记录（保存到新表 BenefitAssessmentRecord）
   * @param authorization 授权角色
   * @param assessmentMonth 考核月份
   * @param monthIndex 当前月份索引
   * @param monthlyTarget 月度目标
   * @param cumulativeTarget 累计目标
   * @param treesCompleted 实际完成数
   * @param treesRequired 需要达到的数量
   * @param benefitActionTaken 权益操作类型
   * @param previousBenefitStatus 考核前权益状态
   * @param newBenefitStatus 考核后权益状态
   * @param newValidUntil 新的有效期截止日
   * @param result 考核结果
   * @param remarks 备注
   */
  private async saveBenefitAssessmentRecord(params: {
    authorization: AuthorizationRole
    assessmentMonth: Month
    monthIndex: number
    monthlyTarget: number
    cumulativeTarget: number
    treesCompleted: number
    treesRequired: number
    benefitActionTaken: BenefitActionType
    previousBenefitStatus: boolean
    newBenefitStatus: boolean
    newValidUntil: Date | null
    result: AssessmentResult
    remarks?: string
  }): Promise<void> {
    const { authorization, assessmentMonth } = params

    // 检查是否已存在该月的记录，避免重复
    const existing = await this.benefitAssessmentRecordRepository.findByAuthorizationAndMonth(
      authorization.authorizationId,
      assessmentMonth,
    )
    if (existing) {
      this.logger.warn(
        `[saveBenefitAssessmentRecord] Record already exists for ${authorization.roleType} ` +
        `${authorization.userId.accountSequence}, month=${assessmentMonth.value}, skipping`,
      )
      return
    }

    // 创建权益考核记录
    const record = BenefitAssessmentRecord.create({
      authorizationId: authorization.authorizationId,
      userId: authorization.userId,
      roleType: authorization.roleType,
      regionCode: authorization.regionCode,
      regionName: authorization.regionName,
      assessmentMonth,
      monthIndex: params.monthIndex,
      monthlyTarget: params.monthlyTarget,
      cumulativeTarget: params.cumulativeTarget,
      treesCompleted: params.treesCompleted,
      treesRequired: params.treesRequired,
      benefitActionTaken: params.benefitActionTaken,
      previousBenefitStatus: params.previousBenefitStatus,
      newBenefitStatus: params.newBenefitStatus,
      newValidUntil: params.newValidUntil,
      result: params.result,
      remarks: params.remarks,
    })

    // 保存到新表
    await this.benefitAssessmentRecordRepository.save(record)

    this.logger.log(
      `[saveBenefitAssessmentRecord] Created record for ${authorization.roleType} ` +
      `${authorization.userId.accountSequence}: month=${assessmentMonth.value}, ` +
      `action=${params.benefitActionTaken}, result=${params.result}`,
    )
  }
}
