import {
  City,
  Country,
  Name,
  PostalCode,
  Province,
  Street,
  TINNumber,
  ValueObject,
  toEmptyString,
} from "@repo/rdx-ddd";
import { Maybe, Result } from "@repo/rdx-utils";

export interface InvoiceRecipientProps {
  name: Name;
  tin: TINNumber;
  street: Maybe<Street>;
  street2: Maybe<Street>;
  city: Maybe<City>;
  postalCode: Maybe<PostalCode>;
  province: Maybe<Province>;
  country: Maybe<Country>;
}

export class InvoiceRecipient extends ValueObject<InvoiceRecipientProps> {
  protected static validate(values: InvoiceRecipientProps) {
    return Result.ok(values);
  }

  static create(values: InvoiceRecipientProps): Result<InvoiceRecipient, Error> {
    const valueIsValid = InvoiceRecipient.validate(values);

    if (valueIsValid.isFailure) {
      return Result.fail(valueIsValid.error);
    }

    return Result.ok(new InvoiceRecipient(values));
  }

  public update(partial: Partial<InvoiceRecipientProps>): Result<InvoiceRecipient, Error> {
    const updatedProps = {
      ...this.props,
      ...partial,
    } as InvoiceRecipientProps;

    return InvoiceRecipient.create(updatedProps);
  }

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

  public get tin(): TINNumber {
    return this.props.tin;
  }

  get street(): Maybe<Street> {
    return this.props.street;
  }

  get street2(): Maybe<Street> {
    return this.props.street2;
  }

  get city(): Maybe<City> {
    return this.props.city;
  }

  get postalCode(): Maybe<PostalCode> {
    return this.props.postalCode;
  }

  get province(): Maybe<Province> {
    return this.props.province;
  }

  get country(): Maybe<Country> {
    return this.props.country;
  }

  getProps(): InvoiceRecipientProps {
    return this.props;
  }

  toPrimitive() {
    return this.getProps();
  }

  toObjectString() {
    return {
      tin: this.tin.toString(),
      name: this.name.toString(),
      street: toEmptyString(this.street, (value) => value.toString()),
      street2: toEmptyString(this.street2, (value) => value.toString()),
      city: toEmptyString(this.city, (value) => value.toString()),
      postal_code: toEmptyString(this.postalCode, (value) => value.toString()),
      province: toEmptyString(this.province, (value) => value.toString()),
      country: toEmptyString(this.country, (value) => value.toString()),
    };
  }
}
