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 { ILogger } from '@midwayjs/logger';
import { v4 as uuidv4 } from 'uuid';

const HOST = "https://apis.hambit.co";
const ACCESS_KEY = 'o1tbXAdd';
const SECRET_KEY = 'cc2355c62627a1a437cf54d8b491aa6f82d30b31'
const PAY_URL = '/api/v3/bra/createCollectingOrder';
const QUERY_URL = '/api/v3/bra/query/collectingOrder'
const BALANCE_URL = '/api/v3/bra/query/balance'
const BANK_URL = '/api/v3/bra/query/bank';
const WITHDRAW_URL = '/api/v3/bra/createTransferOrder';
const QUERY_WITHDRAW_URL = '/api/v3/bra/query/transferOrder'

const NOTIFY_HOST = `http://157.175.73.225/api/admin/dj/open/hambit/bra/notifyOrder`;
const WITHDRAW_NOTIFY_HOST = `http://157.175.73.225/api/admin/dj/open/hambit/bra/notifyWithdraw`;

const CHANNEL_TYPE = "PIX";

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

  async order(payload, extra) {
    const param = {
      "amount": payload.amount.toFixed(2),
      "channelType": CHANNEL_TYPE,
      "externalOrderId": payload.orderNo,
      "notifyUrl": NOTIFY_HOST,
      "remark": "",
      "returnUrl": payload.returnUrl || "",
      "userIdentity": "",
      "inputCpf": 0,
    };
    const timestamp = +moment();
    const nonce = uuidv4();
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...param
    });
    const sign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    const res = await this.httpService.post(HOST + PAY_URL, param, {
      headers: {
        'access_key': ACCESS_KEY,
        'timestamp': timestamp,
        'nonce': nonce,
        'sign': sign
      }
    });
    this.logger.info('下单接口返回', param, JSON.stringify(res.data));
    const { success, msg, data } = res.data;
    if (success && data.cashierUrl) {
      return {
        payUrl: data.cashierUrl,
        traceNo: data?.currencyOrderVo?.orderId
      };
    } else {
      throw new Error(msg);
    }
  }

  async query(payload) {
    const param = {
      externalOrderId: payload.orderNo
    };
    const timestamp = +moment();
    const nonce = uuidv4();
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...param
    });
    const sign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    const res = await this.httpService.post(HOST + QUERY_URL, param, {
      headers: {
        'access_key': ACCESS_KEY,
        'timestamp': timestamp,
        'nonce': nonce,
        'sign': sign
      }
    });
    this.logger.info('查询接口返回', JSON.stringify(res.data));
    const { success, msg, data = [] } = res.data;
    const orderData = data.find(item => item.externalOrderId === payload.orderNo)
    if (success && orderData && +orderData.orderStatus === 2) {
      return {
        status: 1,
        traceNo: orderData.orderId,
        date: new Date()
      };
    } else {
      return {
        status: 0,
        msg,
      };
    }
  }

  async handleOrderNotify(payload, headers) {
    const sign = headers['sign'];
    const timestamp = headers['timestamp'];
    const nonce = headers['nonce'];
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...payload
    });
    const validSign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    if (sign !== validSign) {
      throw new Error('sign error');
    }
    if (+payload.orderStatusCode !== 2) {
      throw new Error('order no success');
    }
    return {
      date: new Date(),
      orderNo: payload.externalOrderId,
      traceNo: payload.orderId,
      status: 1,
    };
  }

  async queryBalance() {
    const param = {};
    const timestamp = +moment();
    const nonce = uuidv4();
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...param
    });
    const sign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    const res = await this.httpService.get(HOST + BALANCE_URL, {
      headers: {
        'access_key': ACCESS_KEY,
        'timestamp': timestamp,
        'nonce': nonce,
        'sign': sign
      }
    });
    this.logger.info('查询余额接口返回', param, JSON.stringify(res.data));
    const { success, msg, data } = res.data;
    if (success && data[0]) {
      return {
        balance: data[0].accountBalance,
        freeze: data[0].accountFreezeAmount
      }
    } else {
      throw new Error(msg);
    }
  }

  async queryBanks(payload) {
    const param = {
      currencyType: 'BRL',
    };
    const timestamp = +moment();
    const nonce = uuidv4();
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...param
    });
    const sign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    const res = await this.httpService.post(HOST + BANK_URL, param, {
      headers: {
        'access_key': ACCESS_KEY,
        'timestamp': timestamp,
        'nonce': nonce,
        'sign': sign
      }
    });
    this.logger.info('查询银行接口返回', param, JSON.stringify(res.data));
    const { success, msg, data } = res.data;
    if (success) {
      return data.map(item => {
        return {
          bankName: item.bankNames,
          bankCode: ''
        }
      })
    } else {
      throw new Error(msg);
    }
  }

  async withdraw(payload) {
    const param = {
      currencyAmount: (+payload.amount).toFixed(2),
      channelType: CHANNEL_TYPE,
      externalOrderId: payload.orderNo,
      personIdType: payload.personIdType,
      personId: payload.personId,
      personName: payload.personName,
      accountType: payload.bankCode,
      accountId: payload.accountNo,
      notifyUrl: WITHDRAW_NOTIFY_HOST
    };
    const timestamp = +moment();
    const nonce = uuidv4();
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...param
    });
    const sign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    const res = await this.httpService.post(HOST + WITHDRAW_URL, param, {
      headers: {
        'access_key': ACCESS_KEY,
        'timestamp': timestamp,
        'nonce': nonce,
        'sign': sign
      }
    });
    this.logger.info('代付接口返回', param, JSON.stringify(res.data));
    const { success, msg, desc, data } = res.data;
    if (success && data.orderId) {
      return {
        status: 2,
        traceNo: data.orderId
      };
    } else {
      return {
        status: 3,
        message: desc || msg
      }
    }
  }

  async handleWithdrawNotify(payload, headers) {
    const sign = headers['sign'];
    const timestamp = headers['timestamp'];
    const nonce = headers['nonce'];
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...payload
    });
    const validSign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    if (sign !== validSign) {
      throw new Error('sign error');
    }
    if (+payload.orderStatusCode !== 8 && +payload.orderStatusCode !== 4 && +payload.orderStatusCode !== 16) {
      throw new Error('order no result');
    }
    let status = 2;
    if (+payload.orderStatusCode === 8) {
      status = 8;
    } else if (+payload.orderStatusCode === 4 || +payload.orderStatusCode === 16) {
      status = 3;
    }
    return {
      date: new Date(),
      status: status,
      message: payload.errorMsg,
      orderNo: payload.externalOrderId
    };
  }

  async queryWithdraw(payload) {
    const param = {
      externalOrderId: payload.orderNo
    };
    const timestamp = +moment();
    const nonce = uuidv4();
    const signStr = this.utils.signSort({
      timestamp,
      nonce,
      access_key: ACCESS_KEY,
      ...param
    });
    const sign = this.utils.signByHmacSha1(signStr, SECRET_KEY);
    const res = await this.httpService.post(HOST + QUERY_WITHDRAW_URL, param, {
      headers: {
        'access_key': ACCESS_KEY,
        'timestamp': timestamp,
        'nonce': nonce,
        'sign': sign
      }
    });
    this.logger.info('查询代付接口返回', JSON.stringify(res.data));
    const { success, msg, data = [] } = res.data;
    const orderData = data.find(item => item.externalOrderId === payload.orderNo)
    if (success && orderData) {
      if(+orderData.orderStatus === 4 || +orderData.orderStatus === 16) {
        return {
          date: new Date(),
          status: 3,
          message: orderData.errorMsg,
          orderNo: orderData.externalOrderId
        };
      } else if(+orderData.orderStatus === 8) {
        return {
          date: new Date(),
          status: 8,
          message: orderData.errorMsg,
          orderNo: orderData.externalOrderId
        };
      }
      return {
        status: 1,
        traceNo: orderData.orderId,
        date: new Date()
      };
    } else {
      return {
        status: 3,
        message: '渠道订单不存在'
      };
    }
  }
}
