import { Decimal } from '@prisma/client/runtime/library';

export class AnalyticsMetric {
  private _id: bigint | null = null;
  private readonly _metricType: string;
  private readonly _metricCode: string;
  private readonly _dimensionTime: Date | null;
  private readonly _dimensionRegion: string | null;
  private readonly _dimensionUserType: string | null;
  private readonly _dimensionRightType: string | null;
  private _metricValue: Decimal;
  private _metricData: Record<string, any> | null;
  private readonly _calculatedAt: Date;

  private constructor(
    metricType: string,
    metricCode: string,
    dimensionTime: Date | null,
    dimensionRegion: string | null,
    dimensionUserType: string | null,
    dimensionRightType: string | null,
    metricValue: Decimal,
    metricData: Record<string, any> | null,
    calculatedAt: Date,
  ) {
    this._metricType = metricType;
    this._metricCode = metricCode;
    this._dimensionTime = dimensionTime;
    this._dimensionRegion = dimensionRegion;
    this._dimensionUserType = dimensionUserType;
    this._dimensionRightType = dimensionRightType;
    this._metricValue = metricValue;
    this._metricData = metricData;
    this._calculatedAt = calculatedAt;
  }

  static create(params: {
    metricType: string;
    metricCode: string;
    dimensionTime?: Date;
    dimensionRegion?: string;
    dimensionUserType?: string;
    dimensionRightType?: string;
    metricValue: Decimal;
    metricData?: Record<string, any>;
  }): AnalyticsMetric {
    return new AnalyticsMetric(
      params.metricType,
      params.metricCode,
      params.dimensionTime || null,
      params.dimensionRegion || null,
      params.dimensionUserType || null,
      params.dimensionRightType || null,
      params.metricValue,
      params.metricData || null,
      new Date(),
    );
  }

  static reconstitute(params: {
    id: bigint;
    metricType: string;
    metricCode: string;
    dimensionTime: Date | null;
    dimensionRegion: string | null;
    dimensionUserType: string | null;
    dimensionRightType: string | null;
    metricValue: Decimal;
    metricData: Record<string, any> | null;
    calculatedAt: Date;
  }): AnalyticsMetric {
    const metric = new AnalyticsMetric(
      params.metricType,
      params.metricCode,
      params.dimensionTime,
      params.dimensionRegion,
      params.dimensionUserType,
      params.dimensionRightType,
      params.metricValue,
      params.metricData,
      params.calculatedAt,
    );
    metric._id = params.id;
    return metric;
  }

  // Getters
  get id(): bigint | null {
    return this._id;
  }

  get metricType(): string {
    return this._metricType;
  }

  get metricCode(): string {
    return this._metricCode;
  }

  get dimensionTime(): Date | null {
    return this._dimensionTime;
  }

  get dimensionRegion(): string | null {
    return this._dimensionRegion;
  }

  get dimensionUserType(): string | null {
    return this._dimensionUserType;
  }

  get dimensionRightType(): string | null {
    return this._dimensionRightType;
  }

  get metricValue(): Decimal {
    return this._metricValue;
  }

  get metricData(): Record<string, any> | null {
    return this._metricData ? { ...this._metricData } : null;
  }

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

  // Commands
  updateValue(value: Decimal, data?: Record<string, any>): void {
    this._metricValue = value;
    if (data) {
      this._metricData = data;
    }
  }
}
