import type { ValueObject } from '@core/shared/domain/ValueObject';
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';

export interface ExternalRatingProvenanceProps {
  source: string;
  lastSyncedAt: Date;
  verified?: boolean;
}

export class ExternalRatingProvenance implements ValueObject<ExternalRatingProvenanceProps> {
  readonly source: string;
  readonly lastSyncedAt: Date;
  readonly verified: boolean;

  private constructor(source: string, lastSyncedAt: Date, verified: boolean) {
    this.source = source;
    this.lastSyncedAt = lastSyncedAt;
    this.verified = verified;
  }

  static create(props: ExternalRatingProvenanceProps): ExternalRatingProvenance {
    if (!props.source || props.source.trim().length === 0) {
      throw new IdentityDomainValidationError('Provenance source cannot be empty');
    }

    if (!props.lastSyncedAt || isNaN(props.lastSyncedAt.getTime())) {
      throw new IdentityDomainValidationError('Provenance lastSyncedAt must be a valid date');
    }

    const trimmedSource = props.source.trim();
    const verified = props.verified ?? false;

    return new ExternalRatingProvenance(trimmedSource, props.lastSyncedAt, verified);
  }

  static restore(props: ExternalRatingProvenanceProps): ExternalRatingProvenance {
    return new ExternalRatingProvenance(props.source, props.lastSyncedAt, props.verified ?? false);
  }

  get props(): ExternalRatingProvenanceProps {
    return {
      source: this.source,
      lastSyncedAt: this.lastSyncedAt,
      verified: this.verified,
    };
  }

  equals(other: ValueObject<ExternalRatingProvenanceProps>): boolean {
    return (
      this.source === other.props.source &&
      this.lastSyncedAt.getTime() === other.props.lastSyncedAt.getTime() &&
      this.verified === other.props.verified
    );
  }

  toString(): string {
    return `${this.source}:${this.lastSyncedAt.toISOString()}:${this.verified ? 'verified' : 'unverified'}`;
  }

  markVerified(): ExternalRatingProvenance {
    return new ExternalRatingProvenance(this.source, this.lastSyncedAt, true);
  }

  updateLastSyncedAt(date: Date): ExternalRatingProvenance {
    return new ExternalRatingProvenance(this.source, date, this.verified);
  }
}