import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { Inject, Injectable, Logger } from '@nestjs/common';
import { CalculateDauCommand } from './calculate-dau.command';
import {
  IEventLogRepository,
  EVENT_LOG_REPOSITORY,
} from '../../../domain/repositories/event-log.repository.interface';
import {
  IDailyActiveStatsRepository,
  DAILY_ACTIVE_STATS_REPOSITORY,
} from '../../../domain/repositories/daily-active-stats.repository.interface';
import { DauCalculationService } from '../../../domain/services/dau-calculation.service';
import { EventName } from '../../../domain/value-objects/event-name.vo';
import {
  startOfDayInTimezone,
  endOfDayInTimezone,
} from '../../../shared/utils/timezone.util';

@Injectable()
@CommandHandler(CalculateDauCommand)
export class CalculateDauHandler implements ICommandHandler<CalculateDauCommand> {
  private readonly logger = new Logger(CalculateDauHandler.name);

  constructor(
    @Inject(EVENT_LOG_REPOSITORY)
    private readonly eventLogRepository: IEventLogRepository,
    @Inject(DAILY_ACTIVE_STATS_REPOSITORY)
    private readonly dauStatsRepository: IDailyActiveStatsRepository,
    private readonly dauCalculationService: DauCalculationService,
  ) {}

  async execute(command: CalculateDauCommand): Promise<void> {
    const { date } = command;
    const timezone = 'Asia/Shanghai';

    const startOfDay = startOfDayInTimezone(date, timezone);
    const endOfDay = endOfDayInTimezone(date, timezone);

    this.logger.log(`Calculating DAU for ${date.toISOString().split('T')[0]}`);

    // 1. 查询去重用户数
    const result = await this.eventLogRepository.queryDau(
      EventName.APP_SESSION_START,
      startOfDay,
      endOfDay,
    );

    // 2. 创建或更新统计聚合
    const existingStats = await this.dauStatsRepository.findByDate(date);

    if (existingStats) {
      existingStats.recalculate(result.total, result.byProvince, result.byCity);
      await this.dauStatsRepository.upsert(existingStats);
    } else {
      const stats = this.dauCalculationService.createStatsFromQueryResult(date, result);
      await this.dauStatsRepository.upsert(stats);
    }

    this.logger.log(`DAU calculated: ${result.total} users`);
  }
}
