import { Injectable } from '@angular/core';
import { ServerRestApiService } from '../services/server-rest-api.service';
import {
  deletePaymentBillingQuery,
  editBuyCodeQuery,
  getBuyCodeQuery,
  getPaymentBillingsQuery,
  getPaymentShopDataQuery,
  paymentOrderQuery,
  paymentParseBackQuery,
  preparePaymentOrderQuery,
  savePaymentBillingQuery,
} from './querys';
import {
  BackDataRecord,
  PaymentBillings,
  PaymentBillingsData,
  PaymentBuyCodeRecord,
  PaymentPreapreResult,
  PaymentPrepareData,
  PaymentPrepareResultRecord,
  PaymentRecordOrder,
  PaymentShopData,
} from './query-records/payment-records';

export class PaymentServerError extends Error {
  public error;
  constructor(message) {
    super(JSON.stringify(message.error));

    this.error = message;
    this.name = 'PaymentServerError';
  }
}

export class PaymentValidationError extends Error {
  public error;
  constructor(message) {
    super(JSON.stringify(message.error));

    this.error = message;
    this.name = 'PaymentValidationError';
  }
}

@Injectable({
  providedIn: 'root',
})
export class PaymentService {
  constructor(private serverRestApiService: ServerRestApiService) {}

  private restHandle(p: Promise<any>): Promise<any> {
    return p
      .catch((err) => {
        throw new PaymentServerError(err);
      })
      .then((res) => {
        if (res.response.error !== undefined) {
          throw new PaymentValidationError(res.response);
        } else {
          return res;
        }
      });
  }

  public getPaymentShopData(): Promise<PaymentShopData> {
    return this.restHandle(
      this.serverRestApiService.query({
        query: getPaymentShopDataQuery,
      })
    );
  }

  public getPaymentBillings(): Promise<PaymentBillings> {
    return this.restHandle(
      this.serverRestApiService.query({
        query: getPaymentBillingsQuery,
      })
    );
  }

  /**
   *
   * @param {PaymentBillingsData} data
   * @returns billing_id
   */
  public savePaymentBilling(data: PaymentBillingsData): Promise<number> {
    return this.restHandle(
      this.serverRestApiService.mutate({
        query: savePaymentBillingQuery,
        variables: { billing: data },
      })
    ).then((res) => {
      return res.billing_id;
    });
  }

  /**
   *
   * @param billingId
   * @param data
   * @returns billing_id
   */
  public editPaymentBilling(billingId, data: PaymentBillingsData): Promise<number> {
    return this.restHandle(
      this.serverRestApiService.mutate({
        query: savePaymentBillingQuery,
        variables: { billing: Object.assign(data, { billing_id: billingId }) },
      })
    ).then((res) => {
      return res.billing_id;
    });
  }

  /**
   *
   * @param billingId
   * @returns billing_id
   */
  public deletePaymentBilling(billingId): Promise<number> {
    return this.restHandle(
      this.serverRestApiService.mutate({
        query: deletePaymentBillingQuery,
        variables: { billing_id: billingId },
      })
    ).then((res) => {
      return res.billing_id;
    });
  }

  public preparePaymentOrder(data: PaymentPrepareData): Promise<PaymentPreapreResult> {
    return this.restHandle(
      this.serverRestApiService.mutate({
        query: preparePaymentOrderQuery,
        variables: { order: data },
      })
    );
  }

  public getBuyCode(): Promise<PaymentBuyCodeRecord> {
    return this.serverRestApiService.query({
      query: getBuyCodeQuery,
    });
  }

  public editBuyCode(buyCode: string): Promise<boolean> {
    return this.serverRestApiService.mutate({
      query: editBuyCodeQuery,
      variables: {
        buyCode,
      },
    });
  }

  public startPaymentOrder(paymentOrder: PaymentRecordOrder): Promise<string> {
    return this.serverRestApiService.mutate({
      query: paymentOrderQuery,
      variables: {
        order: paymentOrder.order,
        orderHash: paymentOrder.orderHash,
        language: paymentOrder.language,
      },
    });
  }

  public paymentParseBack(result: string, signature: string): Promise<BackDataRecord> {
    return this.serverRestApiService.query({
      query: paymentParseBackQuery,
      variables: {
        result: result,
        signature: signature,
      },
    });
  }
}
