import { Injectable, Logger, Inject } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { MetricsService } from './metrics.service';
import { PresenceRedisRepository } from '../redis/presence-redis.repository';
import {
  DAILY_ACTIVE_STATS_REPOSITORY,
  IDailyActiveStatsRepository,
} from '../../domain/repositories/daily-active-stats.repository.interface';
import {
  EVENT_LOG_REPOSITORY,
  IEventLogRepository,
} from '../../domain/repositories/event-log.repository.interface';
import { format } from 'date-fns';

@Injectable()
export class MetricsCollectorService {
  private readonly logger = new Logger(MetricsCollectorService.name);
  private readonly presenceWindowSeconds: number;

  constructor(
    private readonly metricsService: MetricsService,
    private readonly presenceRedisRepository: PresenceRedisRepository,
    @Inject(DAILY_ACTIVE_STATS_REPOSITORY)
    private readonly dauRepository: IDailyActiveStatsRepository,
    @Inject(EVENT_LOG_REPOSITORY)
    private readonly eventLogRepository: IEventLogRepository,
  ) {
    this.presenceWindowSeconds = parseInt(
      process.env.PRESENCE_WINDOW_SECONDS || '180',
      10,
    );
  }

  /**
   * 每 15 秒更新在线人数指标
   */
  @Cron('*/15 * * * * *')
  async collectOnlineUsersMetric(): Promise<void> {
    try {
      const now = Math.floor(Date.now() / 1000);
      const threshold = now - this.presenceWindowSeconds;
      const count = await this.presenceRedisRepository.countOnlineUsers(threshold);

      this.metricsService.setOnlineUsers(count);
      this.logger.debug(`Online users metric updated: ${count}`);
    } catch (error) {
      this.logger.error('Failed to collect online users metric', error);
    }
  }

  /**
   * 每 5 分钟更新 DAU 指标
   */
  @Cron(CronExpression.EVERY_5_MINUTES)
  async collectDauMetric(): Promise<void> {
    try {
      const today = new Date();
      const dateStr = format(today, 'yyyy-MM-dd');

      const stats = await this.dauRepository.findByDate(today);
      if (stats) {
        this.metricsService.setDau(dateStr, stats.dauCount);
        this.logger.debug(`DAU metric updated: ${dateStr} = ${stats.dauCount}`);
      }
    } catch (error) {
      this.logger.error('Failed to collect DAU metric', error);
    }
  }

  /**
   * 启动时立即收集一次
   */
  async onModuleInit(): Promise<void> {
    await this.collectOnlineUsersMetric();
    await this.collectDauMetric();
  }
}
