import {
  CreateInvoiceData,
  DataContainer,
  Invoice,
  InvoiceID,
  InvoiceStats,
  InvoiceUpdate,
} from '../models/invoice';

/** Provider is an interface
 * representing objects that interact with backend services (e.g., via http)
 * that manage invoices.
 **/
export interface Provider {
  createInvoice(data: CreateInvoiceData): Promise<DataContainer<Invoice>>;
  cancelInvoice(invoiceId: InvoiceID): Promise<DataContainer<Invoice>>;
  getInvoiceInfo(invoiceId: InvoiceID): Promise<DataContainer<Invoice>>;
  getInvoiceStats(): Promise<DataContainer<InvoiceStats>>;
  isUpdateValid(data: InvoiceUpdate): boolean;
}

/** InvoiceManager is used to manipulate invoices. */
export class InvoiceManager {
  private _provider: Provider;

  constructor(provider: Provider) {
    this._provider = provider;
  }

  /** Create new Invoice. */
  async create(data: CreateInvoiceData): Promise<DataContainer<Invoice>> {
    return this._provider.createInvoice(data);
  }

  /** Cancel existing Invoice. */
  async cancel(invoiceId: InvoiceID): Promise<DataContainer<Invoice>> {
    return this._provider.cancelInvoice(invoiceId);
  }

  /** Get information about Invoice. */
  async info(invoiceId: InvoiceID): Promise<DataContainer<Invoice>> {
    return this._provider.getInvoiceInfo(invoiceId);
  }

  /** Get Merchant statistics. */
  async stats(): Promise<DataContainer<InvoiceStats>> {
    return this._provider.getInvoiceStats();
  }

  /** Process WebHook data. */
  processUpdate(update: InvoiceUpdate): DataContainer<Omit<Invoice, 'id'>> {
    const isValid = this._provider.isUpdateValid(update);
    if (!isValid) {
      return {
        data: null,
        isValid: false,
        error: new Error('Invalid data received'),
      };
    }
    return {
      data: {
        status: update.data.status,
        code: update.data.code,
        amount: BigInt(update.data.amount),
        order_id: BigInt(update.data.order_id),
      },
      isValid: true,
    };
  }
}
