/**
 * RootId - Value Object for root identity
 *
 * A root is the namespace boundary. It uniquely identifies an administrative domain.
 * With DNS hierarchical addressing, roots can contain dots (e.g., 'com.nimbletec.richard.santomauro').
 *
 * This Value Object enforces:
 * - Validation (non-empty, valid characters)
 * - Equality semantics (two RootId with same value are equal)
 */

// ROOT_ID_PATTERN: Valid root characters.
// Lowercase alphanumeric, hyphens, and dots (for DNS hierarchy).
export const ROOT_ID_PATTERN = /^[a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?$/;

export class RootId {
  private readonly _value: string;

  private constructor(value: string) {
    this._value = value;
  }

  /**
   * Create a RootId from a string.
   * Throws if the value is invalid.
   */
  static of(value: string): RootId {
    if (typeof value !== 'string') {
      throw new Error('RootId must be a string');
    }

    const normalized = value.trim();

    if (normalized.length === 0) {
      throw new Error('RootId cannot be empty');
    }

    if (!ROOT_ID_PATTERN.test(normalized)) {
      throw new Error(
        `Invalid RootId: "${value}". Must be alphanumeric with hyphens, dots, and underscores only.`
      );
    }

    return new RootId(normalized);
  }

  /**
   * Create a RootId, returning null if invalid instead of throwing.
   */
  static tryOf(value: string): RootId | null {
    try {
      return RootId.of(value);
    } catch {
      return null;
    }
  }

  /**
   * Get the raw string value.
   */
  get value(): string {
    return this._value;
  }

  /**
   * Check equality with another RootId.
   */
  equals(other: RootId | null | undefined): boolean {
    if (!other) return false;
    return this._value === other._value;
  }

  /**
   * For use as Map/Set key or in comparisons.
   */
  toString(): string {
    return this._value;
  }

  /**
   * JSON serialization support.
   */
  toJSON(): string {
    return this._value;
  }
}

/**
 * Type guard to check if a value is a RootId.
 */
export function isRootId(value: unknown): value is RootId {
  return value instanceof RootId;
}

/**
 * @deprecated Use ROOT_ID_PATTERN instead.
 */
export const REALM_ID_PATTERN = ROOT_ID_PATTERN;

/**
 * @deprecated Use RootId instead.
 */
export const RealmId = RootId;
/** @deprecated Use RootId instead. */
export type RealmId = RootId;

/**
 * @deprecated Use isRootId instead.
 */
export const isRealmId = isRootId;

/**
 * @deprecated Use isValidRootId instead.
 */
export function isValidRealmId(value: string): boolean {
  return RootId.tryOf(value) !== null;
}

/**
 * Check if a string is a valid root ID.
 */
export function isValidRootId(value: string): boolean {
  return RootId.tryOf(value) !== null;
}
