import { DomainValidationError, ValueObject } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";

interface ICustomerInvoiceStatusProps {
  value: string;
}

export enum INVOICE_STATUS {
  DRAFT = "draft", // <- Proforma
  SENT = "sent", // <- Proforma
  APPROVED = "approved", // <- Proforma
  REJECTED = "rejected", // <- Proforma

  // status === "issued" <- (si is_proforma === true) => Es una proforma (histórica)
  // status === "issued" <- (si is_proforma === false) => Factura y enviará/enviada a Veri*Factu
  ISSUED = "issued",
}

const INVOICE_TRANSITIONS: Record<string, string[]> = {
  draft: [INVOICE_STATUS.SENT],
  sent: [INVOICE_STATUS.APPROVED, INVOICE_STATUS.REJECTED],
  approved: [INVOICE_STATUS.ISSUED],
  rejected: [INVOICE_STATUS.DRAFT],
  issued: [],
};

export class CustomerInvoiceStatus extends ValueObject<ICustomerInvoiceStatusProps> {
  private static readonly ALLOWED_STATUSES = ["draft", "sent", "approved", "rejected", "issued"];
  private static readonly FIELD = "invoiceStatus";
  private static readonly ERROR_CODE = "INVALID_INVOICE_STATUS";

  static create(value: string): Result<CustomerInvoiceStatus, Error> {
    if (!CustomerInvoiceStatus.ALLOWED_STATUSES.includes(value)) {
      const detail = `Estado de la factura no válido: ${value}`;
      return Result.fail(
        new DomainValidationError(
          CustomerInvoiceStatus.ERROR_CODE,
          CustomerInvoiceStatus.FIELD,
          detail
        )
      );
    }

    return Result.ok(
      value === "rejected"
        ? CustomerInvoiceStatus.createRejected()
        : value === "sent"
          ? CustomerInvoiceStatus.createSent()
          : value === "issued"
            ? CustomerInvoiceStatus.createIssued()
            : value === "approved"
              ? CustomerInvoiceStatus.createApproved()
              : CustomerInvoiceStatus.createDraft()
    );
  }

  public static createDraft(): CustomerInvoiceStatus {
    return new CustomerInvoiceStatus({ value: INVOICE_STATUS.DRAFT });
  }

  public static createIssued(): CustomerInvoiceStatus {
    return new CustomerInvoiceStatus({ value: INVOICE_STATUS.ISSUED });
  }

  public static createSent(): CustomerInvoiceStatus {
    return new CustomerInvoiceStatus({ value: INVOICE_STATUS.SENT });
  }

  public static createApproved(): CustomerInvoiceStatus {
    return new CustomerInvoiceStatus({ value: INVOICE_STATUS.APPROVED });
  }

  public static createRejected(): CustomerInvoiceStatus {
    return new CustomerInvoiceStatus({ value: INVOICE_STATUS.REJECTED });
  }

  isDraft(): boolean {
    return this.props.value === INVOICE_STATUS.DRAFT;
  }

  isApproved(): boolean {
    return this.props.value === INVOICE_STATUS.APPROVED;
  }

  getProps(): string {
    return this.props.value;
  }

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

  canTransitionTo(nextStatus: string): boolean {
    return INVOICE_TRANSITIONS[this.props.value].includes(nextStatus);
  }

  toString() {
    return String(this.props.value);
  }
}
