import axios from 'axios';
import { Injectable } from '@nestjs/common';
import { ConfigurationService } from '../../config/configuration.service';
// import { SocksProxyAgent } from 'socks-proxy-agent';

@Injectable()
export class SnappPayService {
  private axios;

  constructor(private config: ConfigurationService) {
    this.axios = axios.create({
      baseURL:
        config.gateway.zarinpalMode === 'sandbox'
          ? 'https://fms-gateway-staging.apps.public.okd4.teh-1.snappcloud.io'
          : 'https://api.snapppay.ir',
      // ...(config.app.nodeEnv === 'development' && {
      //   httpsAgent: new SocksProxyAgent({
      //     hostname: '127.0.0.1',
      //     port: '1060',
      //   }),
      // }),
    });
  }

  /**
   * @param amount Amount based on Rial
   */
  async getEligibility(amount: number) {
    try {
      const token = await this.getToken();

      const { data } = await this.axios.get('/api/online/offer/v1/eligible', {
        params: { amount },
        headers: { Authorization: `Bearer ${token}` },
      });

      console.log('getEligibility', data.response);

      return {
        success: data.response.eligible,
        title: data.response.title_message,
        description: data.response.description,
      };
    } catch (e) {
      const error = e?.response?.data?.errorData;
      console.log('getEligibility SNAP PAY', e);
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }

  /**
   * @param finalAmount Amount based on Rial
   */
  async paymentRequest(
    cartList,
    finalAmount: number,
    callbackURL: string,
    businessPartnerCode: string,
    mobile: string,
    discountAmount = 0,
    shippingAmount = 0,
    externalSourceAmount = 0,
  ) {
    try {
      const token = await this.getToken();

      const payload = {
        cartList,
        amount: finalAmount,
        mobile: `+98${mobile.substring(1)}`,
        paymentMethodTypeDto: 'INSTALLMENT',
        returnURL: callbackURL,
        transactionId: businessPartnerCode,
        discountAmount,
        shippingAmount,
        externalSourceAmount,
      };

      console.log('SNAPP PAY TOKEN', JSON.stringify(payload));

      const { data } = await this.axios.post(
        '/api/online/payment/v1/token',
        payload,
        { headers: { Authorization: `Bearer ${token}` } },
      );

      console.log('SNAPP PAY TOKEN RESPONSE', data);

      return {
        authority: data.response.paymentToken,
        url: data.response.paymentPageUrl,
      };
    } catch (e) {
      console.log('SNAPP PAY TOKEN ERROR', e?.response?.data);
      const error = e?.response?.data?.errorData;
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }

  /**
   * **********************************
   */
  async paymentVerification(authority: string) {
    try {
      const token = await this.getToken();

      const { data } = await this.axios.post(
        '/api/online/payment/v1/verify',
        { paymentToken: authority },
        { headers: { Authorization: `Bearer ${token}` } },
      );

      console.log('SNAPP PAY VERIFY RESPONSE', data);

      return data.response.transactionId;
    } catch (e) {
      console.log('SNAPP PAY VERIFY RESPONSE', e?.response?.data);
      const error = e?.response?.data?.errorData;
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }

  /**
   * **********************************
   */
  async settleRequest(authority: string) {
    try {
      const token = await this.getToken();

      const { data } = await this.axios.post(
        '/api/online/payment/v1/settle',
        { paymentToken: authority },
        { headers: { Authorization: `Bearer ${token}` } },
      );

      console.log('SNAPP PAY SETTLE RESPONSE', data);

      return data.response.transactionId;
    } catch (e) {
      console.log('SNAPP PAY SETTLE RESPONSE', e?.response?.data);
      const error = e?.response?.data?.errorData;
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }

  /**
   * **********************************
   */
  async revertRequest(authority: string) {
    try {
      const token = await this.getToken();

      const { data } = await this.axios.post(
        '/api/online/payment/v1/revert',
        { paymentToken: authority },
        { headers: { Authorization: `Bearer ${token}` } },
      );

      console.log('SNAPP PAY REVERT RESPONSE', data);

      return data.response.transactionId;
    } catch (e) {
      console.log('SNAPP PAY REVERT ERROR', e?.response?.data);
      const error = e?.response?.data?.errorData;
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }

  /**
   * **********************************
   */
  async cancelRequest(authority: string) {
    try {
      const token = await this.getToken();

      const { data } = await this.axios.post(
        '/api/online/payment/v1/cancel',
        { paymentToken: authority },
        { headers: { Authorization: `Bearer ${token}` } },
      );

      console.log('SNAPP PAY CANCEL RESPONSE', data);

      return data.response.transactionId;
    } catch (e) {
      console.log('SNAPP PAY CANCEL ERROR', e?.response?.data);
      const error = e?.response?.data?.errorData;
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }

  /**
   * @param finalAmount Amount based on Rial
   */
  async updateRequest(
    authority: string,
    cartList,
    finalAmount: number,
    discountAmount = 0,
    shippingAmount = 0,
    externalSourceAmount = 0,
  ) {
    try {
      const token = await this.getToken();

      const payload = {
        cartList,
        amount: finalAmount,
        paymentMethodTypeDto: 'INSTALLMENT',
        discountAmount,
        shippingAmount,
        externalSourceAmount,
        paymentToken: authority,
      };

      console.log('SNAPP PAY UPDATE', JSON.stringify(payload));

      const { data } = await this.axios.post(
        '/api/online/payment/v1/update',
        payload,
        { headers: { Authorization: `Bearer ${token}` } },
      );

      console.log('SNAPP PAY UPDATE RESPONSE', data);

      return data.response.transactionId;
    } catch (e) {
      console.log('SNAPP PAY UPDATE ERROR', e?.response?.data);
      const error = e?.response?.data?.errorData;
      console.log(error);
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }

  /**
   * **********************************
   */
  private async getToken() {
    const authString = Buffer.from(
      `${this.config.gateway.snappPayClientId}:${this.config.gateway.snappPayClientSecret}`,
    ).toString('base64');

    const body = new URLSearchParams();
    body.append('grant_type', 'password');
    body.append('scope', 'online-merchant');
    body.append('username', this.config.gateway.snappPayUsername);
    body.append('password', this.config.gateway.snappPayPassword);

    try {
      const { data } = await this.axios.post(
        '/api/online/v1/oauth/token',
        body,
        {
          headers: {
            Authorization: `Basic ${authString}`,
            'Content-Type': 'application/x-www-form-urlencoded',
          },
        },
      );

      return data.access_token;
    } catch (e) {
      console.log('SNAPP PAY getToken ERROR', e);
      const error = e?.response?.data?.errorData;
      console.log(error);
      throw typeof error?.message === 'string'
        ? error.message
        : 'خطایی رخ داده است';
    }
  }
}
