/**
 * PortCode Value Object
 *
 * Encapsulates UN/LOCODE port code validation and behavior
 *
 * Business Rules:
 * - Port code must follow UN/LOCODE format (2-letter country + 3-letter/digit location)
 * - Port code is always uppercase
 * - Port code is immutable
 *
 * Format: CCLLL
 * - CC: ISO 3166-1 alpha-2 country code
 * - LLL: 3-character location code (letters or digits)
 *
 * Examples: NLRTM (Rotterdam), USNYC (New York), SGSIN (Singapore)
 */

export class PortCode {
  private readonly value: string;

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

  static create(code: string): PortCode {
    if (!code || code.trim().length === 0) {
      throw new Error('Port code cannot be empty.');
    }

    const normalized = code.trim().toUpperCase();

    if (!PortCode.isValid(normalized)) {
      throw new Error(
        `Invalid port code format: ${code}. Must follow UN/LOCODE format (e.g., NLRTM, USNYC).`
      );
    }

    return new PortCode(normalized);
  }

  private static isValid(code: string): boolean {
    // UN/LOCODE format: 2-letter country code + 3-character location code
    const unlocodePattern = /^[A-Z]{2}[A-Z0-9]{3}$/;
    return unlocodePattern.test(code);
  }

  getValue(): string {
    return this.value;
  }

  getCountryCode(): string {
    return this.value.substring(0, 2);
  }

  getLocationCode(): string {
    return this.value.substring(2);
  }

  equals(other: PortCode): boolean {
    return this.value === other.value;
  }

  toString(): string {
    return this.value;
  }
}
