import { AuthorizationRole, MonthlyAssessment } from '@/domain/aggregates'
import { LadderTargetRule } from '@/domain/entities'
import { Month, RegionCode } from '@/domain/value-objects'
import { RoleType } from '@/domain/enums'
import { IMonthlyAssessmentRepository, IAuthorizationRoleRepository } from '@/domain/repositories'

export interface TeamStatistics {
  userId: string
  accountSequence: string
  totalTeamPlantingCount: number
  selfPlantingCount: number
  /** 下级团队认种数（不包括自己）= totalTeamPlantingCount - selfPlantingCount */
  get subordinateTeamPlantingCount(): number
  getProvinceTeamCount(provinceCode: string): number
  getCityTeamCount(cityCode: string): number
}

export interface ITeamStatisticsRepository {
  findByUserId(userId: string): Promise<TeamStatistics | null>
  findByAccountSequence(accountSequence: string): Promise<TeamStatistics | null>
  /** 获取用户的祖先链（推荐链），返回从直接推荐人到根节点的 accountSequence 列表 */
  getReferralChain(accountSequence: string): Promise<string[]>
}

export class AssessmentCalculatorService {
  /**
   * 计算月度考核
   */
  async calculateMonthlyAssessment(
    authorization: AuthorizationRole,
    assessmentMonth: Month,
    teamStats: TeamStatistics,
    repository: IMonthlyAssessmentRepository,
  ): Promise<MonthlyAssessment> {
    // 1. 查找或创建本月考核
    let assessment = await repository.findByAuthorizationAndMonth(
      authorization.authorizationId,
      assessmentMonth,
    )

    if (!assessment) {
      // 获取目标
      const monthIndex = authorization.currentMonthIndex || 1
      const target = LadderTargetRule.getTarget(authorization.roleType, monthIndex)

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

    // 2. 执行考核
    const localTeamCount = this.getLocalTeamCount(
      teamStats,
      authorization.roleType,
      authorization.regionCode,
    )

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

    return assessment
  }

  /**
   * 批量评估并排名
   */
  async assessAndRankRegion(
    roleType: RoleType,
    regionCode: RegionCode,
    assessmentMonth: Month,
    authorizationRepository: IAuthorizationRoleRepository,
    statsRepository: ITeamStatisticsRepository,
    assessmentRepository: IMonthlyAssessmentRepository,
  ): Promise<MonthlyAssessment[]> {
    // 1. 查找该区域的所有激活授权
    const authorizations = await authorizationRepository.findActiveByRoleTypeAndRegion(
      roleType,
      regionCode,
    )

    // 2. 计算所有考核
    const assessments: MonthlyAssessment[] = []

    for (const auth of authorizations) {
      // 使用 accountSequence 查询团队统计（referral-service 使用 accountSequence 作为主键）
      const teamStats = await statsRepository.findByAccountSequence(auth.userId.accountSequence)
      if (!teamStats) continue

      const assessment = await this.calculateMonthlyAssessment(
        auth,
        assessmentMonth,
        teamStats,
        assessmentRepository,
      )

      assessments.push(assessment)
    }

    // 3. 排名规则：
    //    - 按超越比例降序排列
    //    - 比例相同时，按达标时间升序排列（先完成的排前面）
    assessments.sort((a, b) => {
      // 先按超越比例降序
      if (b.exceedRatio !== a.exceedRatio) {
        return b.exceedRatio - a.exceedRatio
      }
      // 比例相同时按达标时间升序
      if (a.completedAt && b.completedAt) {
        return a.completedAt.getTime() - b.completedAt.getTime()
      }
      // 有达标时间的排前面
      if (a.completedAt) return -1
      if (b.completedAt) return 1
      return 0
    })

    // 4. 设置排名
    assessments.forEach((assessment, index) => {
      assessment.setRanking(index + 1, index === 0)
    })

    return assessments
  }

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