import { Controller, Logger, Inject } from '@nestjs/common'
import { EventPattern, Payload, Ctx, KafkaContext } from '@nestjs/microservices'
import {
  IAuthorizationRoleRepository,
  AUTHORIZATION_ROLE_REPOSITORY,
  IMonthlyAssessmentRepository,
  MONTHLY_ASSESSMENT_REPOSITORY,
} from '../../domain/repositories'
import {
  TEAM_STATISTICS_REPOSITORY,
} from '../../application/services/authorization-application.service'
import type { ITeamStatisticsRepository, TeamStatistics } from '../../domain/services'
import { UserId, Month } from '../../domain/value-objects'
import { RoleType, AuthorizationStatus } from '../../domain/enums'
import { LadderTargetRule } from '../../domain/entities'
import { MonthlyAssessment, AuthorizationRole } from '../../domain/aggregates'
import { EventPublisherService } from './event-publisher.service'
import { EventAckPublisher } from './event-ack.publisher'

interface TreePlantedPayload {
  userId: string
  accountSequence?: string
  treeCount: number
  provinceCode?: string
  cityCode?: string
}

interface PlantingEventMessage {
  eventName?: string
  eventType?: string
  aggregateId?: string
  occurredAt?: string
  data?: TreePlantedPayload
  payload?: TreePlantedPayload
  // B方案：outbox 元数据
  _outbox?: {
    id: string
    aggregateId: string
    eventType: string
  }
}

/**
 * 团队统计更新事件消息格式
 * 来自 referral-service 的 TeamStatisticsUpdatedEvent
 */
interface TeamStatisticsUpdatedMessage {
  eventId?: string
  eventName?: string
  occurredAt?: string
  data?: {
    userId: string
    accountSequence: string
    totalTeamCount: number
    directReferralCount: number
    leaderboardScore: number
    updateReason: 'planting_added' | 'planting_removed' | 'member_joined' | 'recalculation'
  }
}

@Controller()
export class EventConsumerController {
  private readonly logger = new Logger(EventConsumerController.name)

  constructor(
    @Inject(AUTHORIZATION_ROLE_REPOSITORY)
    private readonly authorizationRepository: IAuthorizationRoleRepository,
    @Inject(MONTHLY_ASSESSMENT_REPOSITORY)
    private readonly assessmentRepository: IMonthlyAssessmentRepository,
    @Inject(TEAM_STATISTICS_REPOSITORY)
    private readonly statsRepository: ITeamStatisticsRepository,
    private readonly eventPublisher: EventPublisherService,
    private readonly eventAckPublisher: EventAckPublisher,
  ) {}

  // 监听认种事件 - 用于更新考核进度
  @EventPattern('planting-events')
  async handlePlantingEvent(
    @Payload() message: PlantingEventMessage,
    @Ctx() context: KafkaContext,
  ) {
    const eventType = message.eventType || message.eventName || 'unknown'
    const outboxInfo = message._outbox
    const eventId = outboxInfo?.aggregateId || message.aggregateId || 'unknown'

    try {
      this.logger.log(`[KAFKA] Received planting event: ${eventType}`)
      this.logger.debug(`[KAFKA] Event payload: ${JSON.stringify(message)}`)

      // 获取 payload（支持多种格式）
      const payload = message.payload || message.data

      switch (eventType) {
        case 'planting.tree.planted':
        case 'PlantingOrderPaid':
        case 'MiningEnabled':
          if (payload) {
            await this.handleTreePlanted(payload)
          }
          break
        default:
          this.logger.debug(`[KAFKA] Unhandled planting event type: ${eventType}`)
      }

      // B方案：发送处理成功确认
      if (outboxInfo) {
        await this.eventAckPublisher.sendSuccess(eventId, outboxInfo.eventType)
      }
    } catch (error) {
      this.logger.error('[KAFKA] Failed to handle planting event:', error)

      // B方案：发送处理失败确认
      if (outboxInfo) {
        const errorMessage = error instanceof Error ? error.message : String(error)
        await this.eventAckPublisher.sendFailure(eventId, outboxInfo.eventType, errorMessage)
      }
    }
  }

  // 监听推荐关系事件 - 用于验证团队内唯一性
  @EventPattern('referral-events')
  async handleReferralEvent(
    @Payload() message: any,
    @Ctx() context: KafkaContext,
  ) {
    try {
      this.logger.log(`[KAFKA] Received referral event: ${message.eventType}`)

      switch (message.eventType) {
        case 'referral.relationship.created':
          // 处理推荐关系创建事件
          break
        default:
          this.logger.debug(`[KAFKA] Unhandled referral event type: ${message.eventType}`)
      }
    } catch (error) {
      this.logger.error('[KAFKA] Failed to handle referral event:', error)
    }
  }

  /**
   * 监听团队统计更新事件 - 用于检查自动升级条件
   * 当 referral-service 更新用户团队统计后发布此事件
   * 这确保了在统计数据已更新后再进行升级检查，避免竞态条件
   */
  @EventPattern('referral.team-statistics.events')
  async handleTeamStatisticsUpdated(
    @Payload() message: TeamStatisticsUpdatedMessage,
    @Ctx() context: KafkaContext,
  ) {
    const eventName = message.eventName || 'unknown'
    const eventId = message.eventId || 'unknown'

    try {
      this.logger.log(`[KAFKA] Received team statistics event: ${eventName}, eventId=${eventId}`)
      this.logger.debug(`[KAFKA] Event payload: ${JSON.stringify(message)}`)

      if (eventName === 'referral.team_statistics.updated' && message.data) {
        const { accountSequence, totalTeamCount } = message.data
        await this.checkUserAutoUpgrade(accountSequence, totalTeamCount)
      }
    } catch (error) {
      this.logger.error('[KAFKA] Failed to handle team statistics event:', error)
    }
  }

  /**
   * 检查特定用户的自动升级条件
   * 当该用户的团队统计更新后被调用
   */
  private async checkUserAutoUpgrade(accountSequence: string, totalTeamCount: number): Promise<void> {
    this.logger.debug(`[TEAM-AUTO-UPGRADE] Checking upgrade for ${accountSequence}, totalTeamCount=${totalTeamCount}`)

    // 获取该用户的所有授权
    const authProvince = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.AUTH_PROVINCE_COMPANY,
    )
    const authCity = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.AUTH_CITY_COMPANY,
    )

    // 检查省团队升级
    if (authProvince && authProvince.benefitActive && authProvince.status === AuthorizationStatus.AUTHORIZED) {
      await this.checkAuthProvinceUpgrade(authProvince)
    }

    // 检查市团队升级
    if (authCity && authCity.benefitActive && authCity.status === AuthorizationStatus.AUTHORIZED) {
      await this.checkAuthCityUpgrade(authCity)
    }
  }

  /**
   * 处理认种事件
   * 1. 检查用户是否有待激活的授权（初始考核）
   * 2. 更新正在进行的月度考核进度
   *
   * 注意：planting-service 发送的 userId 是订单表的自增主键，不是 referral-service 的 user_id
   * 因此必须使用 accountSequence 来查询团队统计
   */
  private async handleTreePlanted(payload: TreePlantedPayload): Promise<void> {
    const { userId, accountSequence, treeCount } = payload
    this.logger.log(`[PLANTING] Processing tree planted event: userId=${userId}, accountSequence=${accountSequence}, count=${treeCount}`)

    // 优先使用 accountSequence 查询，因为 userId 可能是 planting-service 的订单主键
    if (!accountSequence) {
      this.logger.warn(`[PLANTING] No accountSequence in payload, skipping. userId=${userId}`)
      return
    }

    try {
      // 1. 使用 accountSequence 获取用户团队统计
      const teamStats = await this.statsRepository.findByAccountSequence(accountSequence)
      if (!teamStats) {
        this.logger.warn(`[PLANTING] No team stats found for accountSequence ${accountSequence}, skipping`)
        return
      }

      // 使用下级团队认种数（不含自己）进行考核判断
      const subordinateTreeCount = teamStats.subordinateTeamPlantingCount
      this.logger.debug(`[PLANTING] User ${accountSequence} subordinate team planting count: ${subordinateTreeCount}`)

      // 2. 获取用户所有授权
      const authorizations = await this.authorizationRepository.findByUserId(
        UserId.create(teamStats.userId, accountSequence),
      )

      // 3. 处理每个授权（如果有的话）
      if (authorizations.length === 0) {
        this.logger.debug(`[PLANTING] User ${accountSequence} has no authorizations, skipping individual auth processing`)
      }

      for (const auth of authorizations) {
        this.logger.debug(`[PLANTING] Processing authorization: ${auth.authorizationId.value}, role=${auth.roleType}, benefitActive=${auth.benefitActive}, status=${auth.status}`)

        // 3.1 检查初始考核（权益未激活的情况）
        // 支持 PENDING（用户申请）和 AUTHORIZED（管理员授权）两种状态
        if (!auth.benefitActive && (auth.status === AuthorizationStatus.PENDING || auth.status === AuthorizationStatus.AUTHORIZED)) {
          const initialTarget = auth.getInitialTarget()
          this.logger.debug(`[PLANTING] Checking initial target: ${subordinateTreeCount}/${initialTarget}`)

          if (subordinateTreeCount >= initialTarget) {
            this.logger.log(`[PLANTING] User ${accountSequence} reached initial target for ${auth.roleType}, activating benefit`)
            auth.activateBenefit()
            await this.authorizationRepository.save(auth)
            await this.eventPublisher.publishAll(auth.domainEvents)
            auth.clearDomainEvents()

            // 创建首月考核（针对授权省市公司）
            if (auth.roleType === RoleType.AUTH_PROVINCE_COMPANY ||
                auth.roleType === RoleType.AUTH_CITY_COMPANY) {
              await this.createInitialAssessment(auth, teamStats)
            }
          }
        }

        // 3.2 更新月度考核进度（权益已激活的授权省市公司）
        if (auth.benefitActive &&
            (auth.roleType === RoleType.AUTH_PROVINCE_COMPANY ||
             auth.roleType === RoleType.AUTH_CITY_COMPANY)) {
          await this.updateMonthlyAssessment(auth, teamStats)
        }
      }

      // 注意：自动升级检查已移至 handleTeamStatisticsUpdated
      // 通过监听 referral.team-statistics.events 事件来触发升级检查
      // 这样确保在 referral-service 完成统计更新后再进行检查，避免竞态条件

      this.logger.log(`[PLANTING] Completed processing tree planted event for accountSequence ${accountSequence}`)
    } catch (error) {
      this.logger.error(`[PLANTING] Error processing tree planted for accountSequence ${accountSequence}:`, error)
      throw error
    }
  }

  /**
   * 创建首月考核
   */
  private async createInitialAssessment(
    authorization: AuthorizationRole,
    teamStats: TeamStatistics,
  ): Promise<void> {
    const currentMonth = Month.current()
    const target = LadderTargetRule.getTarget(authorization.roleType, 1)

    this.logger.log(`[ASSESSMENT] Creating initial assessment for ${authorization.authorizationId.value}, month=${currentMonth.value}`)

    // 检查是否已存在
    const existing = await this.assessmentRepository.findByAuthorizationAndMonth(
      authorization.authorizationId,
      currentMonth,
    )

    if (existing) {
      this.logger.debug(`[ASSESSMENT] Assessment already exists, updating...`)
      await this.doAssessmentUpdate(existing, authorization, teamStats)
      return
    }

    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,
    })

    await this.doAssessmentUpdate(assessment, authorization, teamStats)
    this.logger.log(`[ASSESSMENT] Created initial assessment for ${authorization.authorizationId.value}`)
  }

  /**
   * 更新月度考核进度
   */
  private async updateMonthlyAssessment(
    authorization: AuthorizationRole,
    teamStats: TeamStatistics,
  ): Promise<void> {
    const currentMonth = Month.current()

    // 查找当月考核记录
    const assessment = await this.assessmentRepository.findByAuthorizationAndMonth(
      authorization.authorizationId,
      currentMonth,
    )

    if (!assessment) {
      this.logger.debug(`[ASSESSMENT] No assessment found for ${authorization.authorizationId.value} in ${currentMonth.value}`)
      return
    }

    await this.doAssessmentUpdate(assessment, authorization, teamStats)
    this.logger.log(`[ASSESSMENT] Updated assessment for ${authorization.authorizationId.value}`)
  }

  /**
   * 执行考核评估
   */
  private async doAssessmentUpdate(
    assessment: MonthlyAssessment,
    authorization: AuthorizationRole,
    teamStats: TeamStatistics,
  ): Promise<void> {
    // 计算本地团队数量
    let localTeamCount = 0
    if (authorization.roleType === RoleType.AUTH_PROVINCE_COMPANY) {
      localTeamCount = teamStats.getProvinceTeamCount(authorization.regionCode.value)
    } else if (authorization.roleType === RoleType.AUTH_CITY_COMPANY) {
      localTeamCount = teamStats.getCityTeamCount(authorization.regionCode.value)
    }

    this.logger.debug(`[ASSESSMENT] Assessing: cumulative=${teamStats.totalTeamPlantingCount}, local=${localTeamCount}, total=${teamStats.totalTeamPlantingCount}`)

    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 static readonly PROVINCE_UPGRADE_THRESHOLD = 50000 // 5万棵
  private static readonly CITY_UPGRADE_THRESHOLD = 10000 // 1万棵


  /**
   * 检查单个省团队是否可以升级为省区域
   * 业务规则：省团队本人伞下认种数（不含自己）达到5万棵时自动升级
   * 注意：referral-service 返回的 totalTeamPlantingCount 已经是不含自己的伞下认种数
   */
  private async checkAuthProvinceUpgrade(authProvince: AuthorizationRole): Promise<void> {
    const accountSequence = authProvince.userId.accountSequence
    const provinceCode = authProvince.regionCode.value
    const provinceName = authProvince.regionName

    // 1. 获取该用户的团队统计
    const teamStats = await this.statsRepository.findByAccountSequence(accountSequence)
    if (!teamStats) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] No team stats found for auth province ${accountSequence}`)
      return
    }

    // totalTeamPlantingCount 已经是伞下认种数（不含自己）
    const subordinateCount = teamStats.totalTeamPlantingCount

    // 2. 检查伞下认种数是否达到省区域升级阈值（5万棵）
    if (subordinateCount < EventConsumerController.PROVINCE_UPGRADE_THRESHOLD) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] Auth province ${accountSequence} has subordinate count ${subordinateCount}, not reaching ${EventConsumerController.PROVINCE_UPGRADE_THRESHOLD} threshold`)
      return
    }

    this.logger.log(`[TEAM-AUTO-UPGRADE] Auth province ${accountSequence} subordinate count ${subordinateCount} reached threshold, checking upgrade eligibility`)

    // 3. 检查该用户是否已有省区域授权
    const existingProvinceCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.PROVINCE_COMPANY,
    )
    if (existingProvinceCompany && existingProvinceCompany.status !== AuthorizationStatus.REVOKED) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] User ${accountSequence} already has province company authorization`)
      return
    }

    // 4. 检查该用户是否已有市区域授权（互斥）
    const existingCityCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.CITY_COMPANY,
    )
    if (existingCityCompany && existingCityCompany.status !== AuthorizationStatus.REVOKED) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] User ${accountSequence} already has city company authorization, cannot upgrade to province`)
      return
    }

    // 5. 检查该省是否已有省区域授权
    const existingProvinceRegion = await this.authorizationRepository.findProvinceCompanyByRegion(provinceCode)
    if (existingProvinceRegion) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] Province ${provinceName} already has province company authorization`)
      return
    }

    // 6. 执行自动升级：省团队 → 省区域
    this.logger.log(`[TEAM-AUTO-UPGRADE] Auto upgrading auth province ${accountSequence} to province company: ${provinceName}`)

    const userId = UserId.create(teamStats.userId, accountSequence)
    const authorization = AuthorizationRole.createAutoUpgradedProvinceCompany({
      userId,
      provinceCode,
      provinceName,
    })

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

    this.logger.log(`[TEAM-AUTO-UPGRADE] Successfully auto upgraded auth province ${accountSequence} to province company: ${provinceName}`)
  }

  /**
   * 检查单个市团队是否可以升级为市区域
   * 业务规则：市团队本人伞下认种数（不含自己）达到1万棵时自动升级
   * 注意：referral-service 返回的 totalTeamPlantingCount 已经是不含自己的伞下认种数
   */
  private async checkAuthCityUpgrade(authCity: AuthorizationRole): Promise<void> {
    const accountSequence = authCity.userId.accountSequence
    const cityCode = authCity.regionCode.value
    const cityName = authCity.regionName

    // 1. 获取该用户的团队统计
    const teamStats = await this.statsRepository.findByAccountSequence(accountSequence)
    if (!teamStats) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] No team stats found for auth city ${accountSequence}`)
      return
    }

    // totalTeamPlantingCount 已经是伞下认种数（不含自己）
    const subordinateCount = teamStats.totalTeamPlantingCount

    // 2. 检查伞下认种数是否达到市区域升级阈值（1万棵）
    if (subordinateCount < EventConsumerController.CITY_UPGRADE_THRESHOLD) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] Auth city ${accountSequence} has subordinate count ${subordinateCount}, not reaching ${EventConsumerController.CITY_UPGRADE_THRESHOLD} threshold`)
      return
    }

    this.logger.log(`[TEAM-AUTO-UPGRADE] Auth city ${accountSequence} subordinate count ${subordinateCount} reached threshold, checking upgrade eligibility`)

    // 3. 检查该用户是否已有市区域授权
    const existingCityCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.CITY_COMPANY,
    )
    if (existingCityCompany && existingCityCompany.status !== AuthorizationStatus.REVOKED) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] User ${accountSequence} already has city company authorization`)
      return
    }

    // 4. 检查该用户是否已有省区域授权（互斥）
    const existingProvinceCompany = await this.authorizationRepository.findByAccountSequenceAndRoleType(
      accountSequence,
      RoleType.PROVINCE_COMPANY,
    )
    if (existingProvinceCompany && existingProvinceCompany.status !== AuthorizationStatus.REVOKED) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] User ${accountSequence} already has province company authorization, cannot upgrade to city`)
      return
    }

    // 5. 检查该市是否已有市区域授权
    const existingCityRegion = await this.authorizationRepository.findCityCompanyByRegion(cityCode)
    if (existingCityRegion) {
      this.logger.debug(`[TEAM-AUTO-UPGRADE] City ${cityName} already has city company authorization`)
      return
    }

    // 6. 执行自动升级：市团队 → 市区域
    this.logger.log(`[TEAM-AUTO-UPGRADE] Auto upgrading auth city ${accountSequence} to city company: ${cityName}`)

    const userId = UserId.create(teamStats.userId, accountSequence)
    const authorization = AuthorizationRole.createAutoUpgradedCityCompany({
      userId,
      cityCode,
      cityName,
    })

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

    this.logger.log(`[TEAM-AUTO-UPGRADE] Successfully auto upgraded auth city ${accountSequence} to city company: ${cityName}`)
  }
}
