/**
 * License Entity
 *
 * Represents a user license within a subscription.
 * Each active user in an organization consumes one license.
 */

import { LicenseStatus, LicenseStatusType } from '../value-objects/license-status.vo';

export interface LicenseProps {
  readonly id: string;
  readonly subscriptionId: string;
  readonly userId: string;
  readonly status: LicenseStatus;
  readonly assignedAt: Date;
  readonly revokedAt: Date | null;
}

export class License {
  private readonly props: LicenseProps;

  private constructor(props: LicenseProps) {
    this.props = props;
  }

  /**
   * Create a new license for a user
   */
  static create(props: { id: string; subscriptionId: string; userId: string }): License {
    return new License({
      id: props.id,
      subscriptionId: props.subscriptionId,
      userId: props.userId,
      status: LicenseStatus.active(),
      assignedAt: new Date(),
      revokedAt: null,
    });
  }

  /**
   * Reconstitute from persistence
   */
  static fromPersistence(props: {
    id: string;
    subscriptionId: string;
    userId: string;
    status: LicenseStatusType;
    assignedAt: Date;
    revokedAt: Date | null;
  }): License {
    return new License({
      id: props.id,
      subscriptionId: props.subscriptionId,
      userId: props.userId,
      status: LicenseStatus.create(props.status),
      assignedAt: props.assignedAt,
      revokedAt: props.revokedAt,
    });
  }

  // Getters
  get id(): string {
    return this.props.id;
  }

  get subscriptionId(): string {
    return this.props.subscriptionId;
  }

  get userId(): string {
    return this.props.userId;
  }

  get status(): LicenseStatus {
    return this.props.status;
  }

  get assignedAt(): Date {
    return this.props.assignedAt;
  }

  get revokedAt(): Date | null {
    return this.props.revokedAt;
  }

  // Business logic

  /**
   * Check if the license is currently active
   */
  isActive(): boolean {
    return this.props.status.isActive();
  }

  /**
   * Check if the license has been revoked
   */
  isRevoked(): boolean {
    return this.props.status.isRevoked();
  }

  /**
   * Revoke this license
   */
  revoke(): License {
    if (this.isRevoked()) {
      throw new Error('License is already revoked');
    }

    return new License({
      ...this.props,
      status: LicenseStatus.revoked(),
      revokedAt: new Date(),
    });
  }

  /**
   * Reactivate a revoked license
   */
  reactivate(): License {
    if (this.isActive()) {
      throw new Error('License is already active');
    }

    return new License({
      ...this.props,
      status: LicenseStatus.active(),
      revokedAt: null,
    });
  }

  /**
   * Get the duration the license was/is active
   */
  getActiveDuration(): number {
    const endTime = this.props.revokedAt ?? new Date();
    return endTime.getTime() - this.props.assignedAt.getTime();
  }

  /**
   * Convert to plain object for persistence
   */
  toObject(): {
    id: string;
    subscriptionId: string;
    userId: string;
    status: LicenseStatusType;
    assignedAt: Date;
    revokedAt: Date | null;
  } {
    return {
      id: this.props.id,
      subscriptionId: this.props.subscriptionId,
      userId: this.props.userId,
      status: this.props.status.value,
      assignedAt: this.props.assignedAt,
      revokedAt: this.props.revokedAt,
    };
  }
}
