/**
 * Organization Entity
 *
 * Represents a business organization (freight forwarder, carrier, or shipper)
 * in the Xpeditis platform.
 *
 * Business Rules:
 * - SCAC code must be unique across all carrier organizations
 * - Name must be unique
 * - Type must be valid (FREIGHT_FORWARDER, CARRIER, SHIPPER)
 */

import { DEFAULT_LOCALE, Locale } from '../value-objects/locale.vo';

export enum OrganizationType {
  FREIGHT_FORWARDER = 'FREIGHT_FORWARDER',
  CARRIER = 'CARRIER',
  SHIPPER = 'SHIPPER',
}

export interface OrganizationAddress {
  street: string;
  city: string;
  state?: string;
  postalCode: string;
  country: string;
}

export interface OrganizationDocument {
  id: string;
  type: string;
  name: string;
  url: string;
  uploadedAt: Date;
}

export interface OrganizationProps {
  id: string;
  name: string;
  type: OrganizationType;
  scac?: string; // Standard Carrier Alpha Code (for carriers only)
  siren?: string; // French SIREN number (9 digits)
  eori?: string; // EU EORI number
  contact_phone?: string; // Contact phone number
  contact_email?: string; // Contact email address
  address: OrganizationAddress;
  logoUrl?: string;
  documents: OrganizationDocument[];
  siret?: string;
  siretVerified: boolean;
  statusBadge: 'none' | 'silver' | 'gold' | 'platinium';
  defaultLanguage: Locale;
  createdAt: Date;
  updatedAt: Date;
  isActive: boolean;
}

export class Organization {
  private readonly props: OrganizationProps;

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

  /**
   * Factory method to create a new Organization
   */
  static create(
    props: Omit<
      OrganizationProps,
      'createdAt' | 'updatedAt' | 'siretVerified' | 'statusBadge' | 'defaultLanguage'
    > & {
      siretVerified?: boolean;
      statusBadge?: 'none' | 'silver' | 'gold' | 'platinium';
      defaultLanguage?: Locale;
    }
  ): Organization {
    const now = new Date();

    // Validate SIRET if provided
    if (props.siret && !Organization.isValidSiret(props.siret)) {
      throw new Error('Invalid SIRET format. Must be 14 digits.');
    }

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

    // Validate that carriers have SCAC codes
    if (props.type === OrganizationType.CARRIER && !props.scac) {
      throw new Error('Carrier organizations must have a SCAC code.');
    }

    // Validate that non-carriers don't have SCAC codes
    if (props.type !== OrganizationType.CARRIER && props.scac) {
      throw new Error('Only carrier organizations can have SCAC codes.');
    }

    return new Organization({
      ...props,
      siretVerified: props.siretVerified ?? false,
      statusBadge: props.statusBadge ?? 'none',
      defaultLanguage: props.defaultLanguage ?? DEFAULT_LOCALE,
      createdAt: now,
      updatedAt: now,
    });
  }

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

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

  private static isValidSiret(siret: string): boolean {
    return /^\d{14}$/.test(siret);
  }

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

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

  get type(): OrganizationType {
    return this.props.type;
  }

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

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

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

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

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

  get address(): OrganizationAddress {
    return { ...this.props.address };
  }

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

  get documents(): OrganizationDocument[] {
    return [...this.props.documents];
  }

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

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

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

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

  get statusBadge(): 'none' | 'silver' | 'gold' | 'platinium' {
    return this.props.statusBadge;
  }

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

  get defaultLanguage(): Locale {
    return this.props.defaultLanguage;
  }

  updateDefaultLanguage(locale: Locale): void {
    this.props.defaultLanguage = locale;
    this.props.updatedAt = new Date();
  }

  // Business methods
  isCarrier(): boolean {
    return this.props.type === OrganizationType.CARRIER;
  }

  isFreightForwarder(): boolean {
    return this.props.type === OrganizationType.FREIGHT_FORWARDER;
  }

  isShipper(): boolean {
    return this.props.type === OrganizationType.SHIPPER;
  }

  updateName(name: string): void {
    if (!name || name.trim().length === 0) {
      throw new Error('Organization name cannot be empty.');
    }
    this.props.name = name.trim();
    this.props.updatedAt = new Date();
  }

  updateAddress(address: OrganizationAddress): void {
    this.props.address = { ...address };
    this.props.updatedAt = new Date();
  }

  updateSiret(siret: string): void {
    if (!Organization.isValidSiret(siret)) {
      throw new Error('Invalid SIRET format. Must be 14 digits.');
    }
    this.props.siret = siret;
    this.props.siretVerified = false;
    this.props.updatedAt = new Date();
  }

  markSiretVerified(): void {
    this.props.siretVerified = true;
    this.props.updatedAt = new Date();
  }

  updateStatusBadge(badge: 'none' | 'silver' | 'gold' | 'platinium'): void {
    this.props.statusBadge = badge;
    this.props.updatedAt = new Date();
  }

  updateSiren(siren: string): void {
    this.props.siren = siren;
    this.props.updatedAt = new Date();
  }

  updateEori(eori: string): void {
    this.props.eori = eori;
    this.props.updatedAt = new Date();
  }

  updateContactPhone(phone: string): void {
    this.props.contact_phone = phone;
    this.props.updatedAt = new Date();
  }

  updateContactEmail(email: string): void {
    this.props.contact_email = email;
    this.props.updatedAt = new Date();
  }

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

  addDocument(document: OrganizationDocument): void {
    this.props.documents.push(document);
    this.props.updatedAt = new Date();
  }

  removeDocument(documentId: string): void {
    this.props.documents = this.props.documents.filter(doc => doc.id !== documentId);
    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(): OrganizationProps {
    return {
      ...this.props,
      address: { ...this.props.address },
      documents: [...this.props.documents],
    };
  }
}
