/**
 * Carrier Entity
 *
 * Represents a shipping carrier (e.g., Maersk, MSC, CMA CGM)
 *
 * Business Rules:
 * - Carrier code must be unique
 * - SCAC code must be valid (4 uppercase letters)
 * - API configuration is optional (for carriers with API integration)
 */

export interface CarrierApiConfig {
  baseUrl: string;
  apiKey?: string;
  clientId?: string;
  clientSecret?: string;
  timeout: number; // in milliseconds
  retryAttempts: number;
  circuitBreakerThreshold: number;
}

export interface CarrierProps {
  id: string;
  name: string;
  code: string; // Unique carrier code (e.g., 'MAERSK', 'MSC')
  scac: string; // Standard Carrier Alpha Code
  logoUrl?: string;
  website?: string;
  apiConfig?: CarrierApiConfig;
  isActive: boolean;
  supportsApi: boolean; // True if carrier has API integration
  createdAt: Date;
  updatedAt: Date;
}

export class Carrier {
  private readonly props: CarrierProps;

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

  /**
   * Factory method to create a new Carrier
   */
  static create(props: Omit<CarrierProps, 'createdAt' | 'updatedAt'>): Carrier {
    const now = new Date();

    // Validate SCAC code
    if (!Carrier.isValidSCAC(props.scac)) {
      throw new Error('Invalid SCAC code format. Must be 4 uppercase letters.');
    }

    // Validate carrier code
    if (!Carrier.isValidCarrierCode(props.code)) {
      throw new Error(
        'Invalid carrier code format. Must be uppercase letters and underscores only.'
      );
    }

    // Validate API config if carrier supports API
    if (props.supportsApi && !props.apiConfig) {
      throw new Error('Carriers with API support must have API configuration.');
    }

    return new Carrier({
      ...props,
      createdAt: now,
      updatedAt: now,
    });
  }

  /**
   * Factory method to reconstitute from persistence
   */
  static fromPersistence(props: CarrierProps): Carrier {
    return new Carrier(props);
  }

  /**
   * Validate SCAC code format
   */
  private static isValidSCAC(scac: string): boolean {
    const scacPattern = /^[A-Z]{4}$/;
    return scacPattern.test(scac);
  }

  /**
   * Validate carrier code format
   */
  private static isValidCarrierCode(code: string): boolean {
    const codePattern = /^[A-Z_]+$/;
    return codePattern.test(code);
  }

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

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

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

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

  get logoUrl(): string | undefined {
    return this.props.logoUrl;
  }

  get website(): string | undefined {
    return this.props.website;
  }

  get apiConfig(): CarrierApiConfig | undefined {
    return this.props.apiConfig ? { ...this.props.apiConfig } : undefined;
  }

  get isActive(): boolean {
    return this.props.isActive;
  }

  get supportsApi(): boolean {
    return this.props.supportsApi;
  }

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

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

  // Business methods
  hasApiIntegration(): boolean {
    return this.props.supportsApi && !!this.props.apiConfig;
  }

  updateApiConfig(apiConfig: CarrierApiConfig): void {
    if (!this.props.supportsApi) {
      throw new Error('Cannot update API config for carrier without API support.');
    }

    this.props.apiConfig = { ...apiConfig };
    this.props.updatedAt = new Date();
  }

  updateLogoUrl(logoUrl: string): void {
    this.props.logoUrl = logoUrl;
    this.props.updatedAt = new Date();
  }

  updateWebsite(website: string): void {
    this.props.website = website;
    this.props.updatedAt = new Date();
  }

  deactivate(): void {
    this.props.isActive = false;
    this.props.updatedAt = new Date();
  }

  activate(): void {
    this.props.isActive = true;
    this.props.updatedAt = new Date();
  }

  /**
   * Convert to plain object for persistence
   */
  toObject(): CarrierProps {
    return {
      ...this.props,
      apiConfig: this.props.apiConfig ? { ...this.props.apiConfig } : undefined,
    };
  }
}
