import { AggregateRoot } from '@nestjs/cqrs';
import { DauCalculatedEvent } from '../../events/dau-calculated.event';

export class DailyActiveStats extends AggregateRoot {
  private _day: Date;
  private _dauCount: number;
  private _dauByProvince: Map<string, number>;
  private _dauByCity: Map<string, number>;
  private _calculatedAt: Date;
  private _version: number;

  private constructor() {
    super();
  }

  // Getters
  get day(): Date {
    return this._day;
  }

  get dauCount(): number {
    return this._dauCount;
  }

  get dauByProvince(): Map<string, number> {
    return new Map(this._dauByProvince);
  }

  get dauByCity(): Map<string, number> {
    return new Map(this._dauByCity);
  }

  get calculatedAt(): Date {
    return this._calculatedAt;
  }

  get version(): number {
    return this._version;
  }

  // 工厂方法
  static create(props: {
    day: Date;
    dauCount: number;
    dauByProvince?: Map<string, number>;
    dauByCity?: Map<string, number>;
  }): DailyActiveStats {
    const stats = new DailyActiveStats();
    stats._day = props.day;
    stats._dauCount = props.dauCount;
    stats._dauByProvince = props.dauByProvince ?? new Map();
    stats._dauByCity = props.dauByCity ?? new Map();
    stats._calculatedAt = new Date();
    stats._version = 1;

    stats.apply(new DauCalculatedEvent(stats._day, stats._dauCount));
    return stats;
  }

  // 重新计算
  recalculate(newDauCount: number, byProvince?: Map<string, number>, byCity?: Map<string, number>): void {
    this._dauCount = newDauCount;
    if (byProvince) this._dauByProvince = byProvince;
    if (byCity) this._dauByCity = byCity;
    this._calculatedAt = new Date();
    this._version++;

    this.apply(new DauCalculatedEvent(this._day, this._dauCount));
  }

  // 从持久化恢复
  static reconstitute(props: {
    day: Date;
    dauCount: number;
    dauByProvince: Map<string, number>;
    dauByCity: Map<string, number>;
    calculatedAt: Date;
    version: number;
  }): DailyActiveStats {
    const stats = new DailyActiveStats();
    stats._day = props.day;
    stats._dauCount = props.dauCount;
    stats._dauByProvince = props.dauByProvince;
    stats._dauByCity = props.dauByCity;
    stats._calculatedAt = props.calculatedAt;
    stats._version = props.version;
    return stats;
  }
}
