/**
 * Domain Entity: AnalyticsSnapshot
 *
 * Aggregated analytics data for a specific entity over a time period.
 * Pre-calculated metrics for sponsor dashboard and entity analytics.
 */

import type { IEntity } from '@core/shared/domain';
import type {
  AnalyticsSnapshotProps,
  AnalyticsMetrics,
  SnapshotEntityType,
  SnapshotPeriod,
} from '../types/AnalyticsSnapshot';
export type { SnapshotEntityType, SnapshotPeriod } from '../types/AnalyticsSnapshot';
import { AnalyticsEntityId } from '../value-objects/AnalyticsEntityId';

export class AnalyticsSnapshot implements IEntity<string> {
  readonly id: string;
  readonly entityType: SnapshotEntityType;
  readonly period: SnapshotPeriod;
  readonly startDate: Date;
  readonly endDate: Date;
  readonly metrics: AnalyticsMetrics;
  readonly createdAt: Date;

  private readonly entityIdVo: AnalyticsEntityId;

  private constructor(props: AnalyticsSnapshotProps) {
    this.id = props.id;
    this.entityType = props.entityType;
    this.entityIdVo = AnalyticsEntityId.create(props.entityId);
    this.period = props.period;
    this.startDate = props.startDate;
    this.endDate = props.endDate;
    this.metrics = props.metrics;
    this.createdAt = props.createdAt;
  }

  get entityId(): string {
    return this.entityIdVo.value;
  }

  static create(props: Omit<AnalyticsSnapshotProps, 'createdAt'> & { createdAt?: Date }): AnalyticsSnapshot {
    this.validate(props);

    return new AnalyticsSnapshot({
      ...props,
      createdAt: props.createdAt ?? new Date(),
    });
  }

  static createEmpty(
    id: string,
    entityType: SnapshotEntityType,
    entityId: string,
    period: SnapshotPeriod,
    startDate: Date,
    endDate: Date
  ): AnalyticsSnapshot {
    return new AnalyticsSnapshot({
      id,
      entityType,
      entityId,
      period,
      startDate,
      endDate,
      metrics: {
        pageViews: 0,
        uniqueVisitors: 0,
        avgSessionDuration: 0,
        bounceRate: 0,
        engagementScore: 0,
        sponsorClicks: 0,
        sponsorUrlClicks: 0,
        socialShares: 0,
        leagueJoins: 0,
        raceRegistrations: 0,
        exposureValue: 0,
      },
      createdAt: new Date(),
    });
  }

  private static validate(props: Omit<AnalyticsSnapshotProps, 'createdAt'>): void {
    if (!props.id || props.id.trim().length === 0) {
      throw new Error('AnalyticsSnapshot ID is required');
    }

    if (!props.entityType) {
      throw new Error('AnalyticsSnapshot entityType is required');
    }

    if (!props.entityId || props.entityId.trim().length === 0) {
      throw new Error('AnalyticsSnapshot entityId is required');
    }

    if (!props.period) {
      throw new Error('AnalyticsSnapshot period is required');
    }

    if (props.endDate < props.startDate) {
      throw new Error('AnalyticsSnapshot endDate must be after startDate');
    }
  }

  /**
   * Calculate exposure score for sponsors (weighted combination of metrics)
   */
  calculateExposureScore(): number {
    const { pageViews, uniqueVisitors, sponsorClicks, sponsorUrlClicks, socialShares } = this.metrics;
    
    return (
      pageViews * 1 +
      uniqueVisitors * 2 +
      sponsorClicks * 10 +
      sponsorUrlClicks * 25 +
      socialShares * 5
    );
  }

  /**
   * Calculate trust indicator based on engagement quality
   */
  getTrustIndicator(): 'high' | 'medium' | 'low' {
    const { bounceRate, avgSessionDuration, engagementScore } = this.metrics;
    
    if (bounceRate < 30 && avgSessionDuration > 120000 && engagementScore > 50) {
      return 'high';
    }
    if (bounceRate < 60 && avgSessionDuration > 30000 && engagementScore > 20) {
      return 'medium';
    }
    return 'low';
  }

  /**
   * Get period comparison label
   */
  getPeriodLabel(): string {
    const formatter = new Intl.DateTimeFormat('en-US', { 
      month: 'short', 
      day: 'numeric',
      year: this.period === 'monthly' ? 'numeric' : undefined 
    });
    
    return `${formatter.format(this.startDate)} - ${formatter.format(this.endDate)}`;
  }
}