import { DomainError } from '../errors/domain.error';

export class EncryptedData {
  private readonly _ciphertext: string;
  private readonly _iv: string;
  private readonly _authTag: string;
  private readonly _keyId: string;

  private constructor(
    ciphertext: string,
    iv: string,
    authTag: string,
    keyId: string,
  ) {
    this._ciphertext = ciphertext;
    this._iv = iv;
    this._authTag = authTag;
    this._keyId = keyId;
  }

  static create(params: {
    ciphertext: string;
    iv: string;
    authTag: string;
    keyId: string;
  }): EncryptedData {
    if (!params.ciphertext || params.ciphertext.length === 0) {
      throw new DomainError('Ciphertext cannot be empty');
    }
    if (!params.iv || params.iv.length === 0) {
      throw new DomainError('IV cannot be empty');
    }
    if (!params.authTag || params.authTag.length === 0) {
      throw new DomainError('Auth tag cannot be empty');
    }
    if (!params.keyId || params.keyId.length === 0) {
      throw new DomainError('Key ID cannot be empty');
    }
    return new EncryptedData(
      params.ciphertext,
      params.iv,
      params.authTag,
      params.keyId,
    );
  }

  static fromSerializedString(serialized: string, keyId: string): EncryptedData {
    const parts = serialized.split(':');
    if (parts.length !== 3) {
      throw new DomainError('Invalid encrypted data format');
    }
    return new EncryptedData(parts[0], parts[1], parts[2], keyId);
  }

  get ciphertext(): string {
    return this._ciphertext;
  }

  get iv(): string {
    return this._iv;
  }

  get authTag(): string {
    return this._authTag;
  }

  get keyId(): string {
    return this._keyId;
  }

  toSerializedString(): string {
    return `${this._ciphertext}:${this._iv}:${this._authTag}`;
  }
}
