import { Inject, Logger, Provide } from '@midwayjs/decorator';
import { BaseService } from '@cool-midway/core';
import * as _ from 'lodash';
import * as moment from 'moment';
import { Utils } from '../../../../comm/utils';
import { HttpService } from '@midwayjs/axios';
import * as md5 from 'md5';
import { ILogger } from '@midwayjs/logger';
import * as FormData from 'form-data';
import * as fs from 'fs';
import { KycService } from '../kyc';

// const HOST = 'https://sandbox-oapi.sunpay.pro'
const HOST = 'https://oapi.sunpay.pro';

const URL = HOST + '/api/v3-2/Fiat/Direct/PayIn';
const BASIC_KEY_URL = HOST + '/api/v3-2/Fiat/Kyc/CreateBasicUser';
const ADVANCED_KEY_URL = HOST + '/api/v3-2/Fiat/Kyc/CreateAdvancedUser';
const PREMINUM_KEY_URL = HOST + '/api/v3-2/Fiat/Kyc/CreatePremiumUser';
const COUNTRIES_URL = HOST + '/api/v3-2/Fiat/Countries';
const REFUND_URL = HOST + '/api/v3-2/Fiat/Direct/Refund';
const QUERY_REFUND_URL = HOST + '/api/v3-2/Fiat/x/Refund'
const KYC_QUERY = HOST + '/api/v3-2/Fiat/Kyc/GetCustomer'

// const API_KEY = '08dcd396-a91a-486a-8ca5-02150819d7ae';
// const API_SERECT = 'e0ce942cc6255e31578a753a4b0bfc2a7b9200837371cfa47c0c89ec143386e0';
const API_KEY = '08dd0477-8676-4f68-83c1-215dceeffa2e';
const API_SERECT = 'c87e8df7bfd93887c2c0f8dfa2e9190ef1d010fb0de5bca0615138e318767b36';
const NOTIFY_HOST = `http://157.175.73.225/api/admin/dj/open/SunCard/notifyOrder`;

@Provide()
export class SunPayService extends BaseService {
  @Inject()
  utils: Utils;
  @Inject()
  httpService: HttpService;
  @Logger()
  logger: ILogger;
  @Inject()
  kycService: KycService

  async createPremium(payload: any, files: any) {
    const form = new FormData();
    form.append('customer_id', payload.customerId);
    form.append('residential_address', fs.createReadStream(files.residentialAddress.data));
    form.append('income', fs.createReadStream(files.income.data));
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const signData = timestamp + nonce;
    const sign = this.utils.signBySha256(signData, API_SERECT).toUpperCase();
    const res = await this.httpService.post(PREMINUM_KEY_URL, form, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign,
        ...form.getHeaders()
      }
    });
    this.logger.info('高级KYC接口返回', JSON.stringify(res.data));
    const { is_success, msg, data } = res.data;
    if (is_success && data) {
      return {
        customerId: payload.customerId
      };
    } else if (!is_success && msg === 'Server Error: Cannot premium repeatedly') {
      return {
        customerId: payload.customerId
      };
    } else {
      throw new Error(msg);
    }
  }

  async createAdvanced(payload: any, files: any) {
    const form = new FormData();
    form.append('customer_id', payload.customerId);
    form.append('document_type', payload.documentType);
    form.append('document_number', payload.documentNumber);
    form.append('front_side_document', fs.createReadStream(files.frontSideDocument.data));
    form.append('back_side_document', fs.createReadStream(files.backSideDocument.data));
    form.append('customer_photo', fs.createReadStream(files.customerPhoto.data));
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const signData = timestamp + nonce;
    const sign = this.utils.signBySha256(signData, API_SERECT).toUpperCase();
    const res = await this.httpService.post(ADVANCED_KEY_URL, form, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign,
        ...form.getHeaders()
      }
    });
    this.logger.info('进阶KYC接口返回', JSON.stringify(res.data));
    const { is_success, msg, data } = res.data;
    if (is_success && data) {
      return {
        customerId: payload.customerId
      };
    } else if (!is_success && msg === 'Server Error: Cannot advance repeatedly') {
      return {
        customerId: payload.customerId
      };
    } else {
      throw new Error(msg);
    }
  }

  async createBasic(payload: any) {
    const param = {
      "out_user_id": payload.outUserId,
      "customer_name": payload.customerName,
      "customer_email": payload.customerEmail,
      "country_code": payload.countryCode,
      "residence_country": payload.residenceCountry,
      "birth_date": moment(payload.birthDate).format('YYYY-MM-DD HH:mm:ss'),
    }
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const data = timestamp + nonce + JSON.stringify(param);
    const sign = this.utils.signBySha256(data, API_SERECT).toUpperCase();
    const res = await this.httpService.post(BASIC_KEY_URL, param, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign
      }
    });
    this.logger.info('基础KYC接口返回', param, JSON.stringify(res.data));
    const { is_success, msg } = res.data;
    if (is_success && res.data.data.customer_id) {
      return {
        customerId: res.data.data.customer_id
      };
    } else {
      throw new Error(msg);
    }
  }

  async getCountries() {
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const data = timestamp + nonce;
    const sign = this.utils.signBySha256(data, API_SERECT).toUpperCase();
    const res = await this.httpService.get(COUNTRIES_URL, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign
      }
    });
    const { is_success, msg } = res.data;
    if (is_success) {
      return res.data.data;
    } else {
      throw new Error(msg);
    }
  }

  async order(payload, extra) {
    const data = await this.kycService.getLevel(payload.orderNo);
    if(data && data.payUrl) {
      return {
        payUrl: data.payUrl,
        isDone: true
      }
    } else {
      return {
        payUrl: `https://kyc.fusionpay.one/?t=${payload.orderNo}`,
        isDone: false
      };
    }
  }

  async createOrder(payload) {
    const param = {
      out_order_no: payload.orderNo,
      customer_id: payload.customerId,
      currency: payload.currency,
      amount: +payload.amount,
      payment_type: "CARD",
      client_ip: payload.userIp || "127.0.0.0",
      billing_address_country_code: payload.country,
      webhook_url: NOTIFY_HOST,
      cancel_url: payload.returnUrl || 'https://www.baidu.com',
    };
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const data = timestamp + nonce + JSON.stringify(param);
    const sign = this.utils.signBySha256(data, API_SERECT).toUpperCase();
    const res = await this.httpService.post(URL, param, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign
      }
    });
    this.logger.info('下单接口返回', param, JSON.stringify(res.data));
    const { is_success, msg } = res.data;
    if (is_success && res.data.data.check_out_url) {
      return {
        payUrl: res.data.data.check_out_url,
        traceNo: res.data.data.order_no
      };
    } else {
      throw new Error(msg);
    }
  }

  async query(payload) {
    if (!payload.traceNo) {
      return {
        status: 0,
        msg: 'traceNo is no exits'
      }
    }
    const param = {
      orderNo: payload.traceNo
    };
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const data = timestamp + nonce;
    const sign = this.utils.signBySha256(data, API_SERECT).toUpperCase();
    const res = await this.httpService.get(`${URL}/${param.orderNo}`, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign
      }
    });
    this.logger.info('查询接口返回', JSON.stringify(res.data));
    const { is_success, msg } = res.data;
    if (is_success) {
      if (res.data.data.order_status === 'SUCCESS') {
        return {
          status: 1,
          traceNo: res.data.data.order_no,
          date: new Date()
        };
      } else if (res.data.data.order_status === 'FAIL') {
        return {
          status: 3,
          traceNo: res.data.data.order_no,
          date: new Date()
        };
      } else {
        return {
          status: 0,
          msg,
        };
      }
    } else {
      return {
        status: 0,
        msg,
      };
    }
  }

  async handleOrderNotify(payload, headers) {
    const { data } = payload;
    const sign = headers['sunpay-sign'];
    const timestamp = headers['sunpay-timestamp'];
    const nonce = headers['sunpay-nonce'];
    const str = timestamp + nonce + JSON.stringify(payload);
    const validSign = this.utils.signBySha256(str, API_SERECT).toUpperCase();
    if (sign !== validSign) {
      throw new Error('sign error');
    }
    if (data.status !== 'SUCCESS' && data.status !== 'FAIL') {
      throw new Error('order no result');
    }
    return {
      date: new Date(),
      orderNo: data.out_order_no,
      traceNo: data.order_no,
      status: data.status === 'SUCCESS' ? 1 : 3
    };
  }

  async refund(refund) {
    const param = {
      order_no: refund.traceNo,
      amount: refund.amount,
      out_refund_order_no: refund.refundNo,
      webhook_url: "",
      Reason: refund.reason,
    };
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const data = timestamp + nonce + JSON.stringify(param);
    const sign = this.utils.signBySha256(data, API_SERECT).toUpperCase();
    const res = await this.httpService.post(REFUND_URL, param, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign
      }
    });
    this.logger.info('退款接口返回', param, JSON.stringify(res.data));
    const { is_success, msg } = res.data;
    if (is_success && res.data.data.refund_no) {
      return {
        refundTraceNo: res.data.data.refund_no,
      };
    } else {
      throw new Error(msg);
    }
  }

  async queryRefund(refund) {
    const param = {
      order_no: refund.traceNo,
    };
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const signData = timestamp + nonce;
    const sign = this.utils.signBySha256(signData, API_SERECT).toUpperCase();
    const res = await this.httpService.get(QUERY_REFUND_URL.replace('{orderNo}', param.order_no), {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign
      }
    });
    this.logger.info('退款接口查询返回', QUERY_REFUND_URL.replace('{orderNo}', param.order_no), JSON.stringify(res.data));
    const { is_success, msg, data = {} } = res.data;
    if (is_success) {
      const { refund_details = [] } = data;
      const bean = refund_details.find(item => {
        return item.out_refund_no === refund.refundNo
      });
      if (bean && bean.status === 'SUCCESS') {
        return {
          status: 1,
          refundTraceNo: bean.refund_no,
          date: new Date(),
          message: ''
        }
      } else if (bean && bean.status === 'FAIL') {
        return {
          status: 2,
          refundTraceNo: bean.refund_no,
          date: new Date(),
          message: ''
        }
      } else {
        return {
          status: 0,
          message: ''
        }
      }
    } else {
      throw new Error(msg);
    }
  }

  async queryKyc(outUserId) {
    const timestamp = +moment();
    const nonce = md5(timestamp);
    const data = timestamp + nonce;
    const sign = this.utils.signBySha256(data, API_SERECT).toUpperCase();
    const URL = KYC_QUERY + '?out_user_id=' + outUserId;
    const res = await this.httpService.get(URL, {
      headers: {
        'SunPay-Key': API_KEY,
        'SunPay-Timestamp': timestamp,
        'SunPay-Nonce': nonce,
        'SunPay-Sign': sign
      }
    });
    this.logger.info('查询KYC用户信息', URL, JSON.stringify(res.data));
    const { is_success, msg } = res.data;
    if (is_success && res.data && res.data.data && res.data.data.customer_id) {
      return {
        customerId: res.data.data.customer_id,
        kycUserId: res.data.data.out_user_id,
        countryCode: res.data.data.country_code,
        customerEmail: res.data.data.customer_email
      };
    } else {
      throw new Error(msg);
    }
  }
}