/**
 * Domain Entity: PageView
 *
 * Represents a single page view event for analytics tracking.
 * Captures visitor interactions with leagues, drivers, teams, races.
 */

import type { IEntity } from '@core/shared/domain';
import type { EntityType, VisitorType, PageViewProps } from '../types/PageView';

export type { EntityType, VisitorType } from '../types/PageView';
import { AnalyticsEntityId } from '../value-objects/AnalyticsEntityId';
import { AnalyticsSessionId } from '../value-objects/AnalyticsSessionId';
import { PageViewId } from '../value-objects/PageViewId';

export class PageView implements IEntity<string> {
  readonly entityType: EntityType;
  readonly visitorId: string | undefined;
  readonly visitorType: VisitorType;
  readonly referrer: string | undefined;
  readonly userAgent: string | undefined;
  readonly country: string | undefined;
  readonly timestamp: Date;
  readonly durationMs: number | undefined;

  private readonly idVo: PageViewId;
  private readonly entityIdVo: AnalyticsEntityId;
  private readonly sessionIdVo: AnalyticsSessionId;

  private constructor(props: PageViewProps) {
    this.idVo = PageViewId.create(props.id);
    this.entityType = props.entityType;
    this.entityIdVo = AnalyticsEntityId.create(props.entityId);
    this.visitorId = props.visitorId;
    this.visitorType = props.visitorType;
    this.sessionIdVo = AnalyticsSessionId.create(props.sessionId);
    this.referrer = props.referrer;
    this.userAgent = props.userAgent;
    this.country = props.country;
    this.timestamp = props.timestamp;
    this.durationMs = props.durationMs;
  }

  get id(): string {
    return this.idVo.value;
  }

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

  get sessionId(): string {
    return this.sessionIdVo.value;
  }

  static create(props: Omit<PageViewProps, 'timestamp'> & { timestamp?: Date }): PageView {
    this.validate(props);

    const baseProps: PageViewProps = {
      id: props.id,
      entityType: props.entityType,
      entityId: props.entityId,
      visitorType: props.visitorType,
      sessionId: props.sessionId,
      timestamp: props.timestamp ?? new Date(),
      ...(props.visitorId !== undefined ? { visitorId: props.visitorId } : {}),
      ...(props.referrer !== undefined ? { referrer: props.referrer } : {}),
      ...(props.userAgent !== undefined ? { userAgent: props.userAgent } : {}),
      ...(props.country !== undefined ? { country: props.country } : {}),
      ...(props.durationMs !== undefined ? { durationMs: props.durationMs } : {}),
    };

    return new PageView(baseProps);
  }

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

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

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

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

  /**
   * Update duration when visitor leaves page
   */
  withDuration(durationMs: number): PageView {
    if (durationMs < 0) {
      throw new Error('Duration must be non-negative');
    }

    return PageView.create({
      id: this.id,
      entityType: this.entityType,
      entityId: this.entityId,
      visitorType: this.visitorType,
      sessionId: this.sessionId,
      timestamp: this.timestamp,
      ...(this.visitorId !== undefined ? { visitorId: this.visitorId } : {}),
      ...(this.referrer !== undefined ? { referrer: this.referrer } : {}),
      ...(this.userAgent !== undefined ? { userAgent: this.userAgent } : {}),
      ...(this.country !== undefined ? { country: this.country } : {}),
      durationMs,
    });
  }

  /**
   * Check if this is a meaningful view (not a bounce)
   */
  isMeaningfulView(): boolean {
    return this.durationMs !== undefined && this.durationMs >= 5000; // 5+ seconds
  }

  /**
   * Check if view came from external source
   */
  isExternalReferral(): boolean {
    if (!this.referrer) return false;
    return !this.referrer.includes('gridpilot');
  }
}