import { Inject, Logger, Provide } from '@midwayjs/decorator';
import { BaseService } from '@cool-midway/core';
import { HttpService } from '@midwayjs/axios';
import { ILogger } from '@midwayjs/logger';
import * as _ from 'lodash';
import { Utils } from '../../../comm/utils';
import * as md5 from 'md5';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { MerchantEntity } from '../entity/merchant';
import { Repository } from 'typeorm';
import { WithdrawEntity } from '../entity/withdraw';

const notifyTimes = [5, 10, 15, 30, 60, 120, 300, 600, 1200];

@Provide()
export class WithdrawNotifyService extends BaseService {
  @Inject()
  httpService: HttpService;

  @Logger()
  logger: ILogger;

  @Inject()
  utils: Utils;

  @InjectEntityModel(MerchantEntity)
  merchantEntity: Repository<MerchantEntity>;

  async notifyReq(url, data, idx = 1) {
    try {
      this.logger.info(`第${idx}次代付回调通知`, url, JSON.stringify(data));
      const result = await this.httpService.post(url, data);
      if (result.data === 'success') {
        return {
          status: 1,
        };
      } else {
        this.logger.error(
          `第${idx}次代付回调通知失败`,
          url,
          JSON.stringify(data),
          result.data
        );
        return {
          status: 0,
          msg: result.data,
        };
      }
    } catch (err) {
      this.logger.error(
        `第${idx}次代付回调通知失败`,
        url,
        JSON.stringify(data),
        err.message
      );
      return {
        status: 0,
        msg: err.message,
      };
    }
  }

  async notify(withdrawOrder: WithdrawEntity, isOnce = false) {
    try {
      const merchant = await this.merchantEntity.findOneBy({
        mchId: withdrawOrder.mchId,
      });
      if (!merchant) {
        throw new Error('商户不存在');
      }
      const url = withdrawOrder.notifyUrl;
      const params: any = {
        mchId: withdrawOrder.mchId,
        orderNo: withdrawOrder.orderNo,
        outOrderNo: withdrawOrder.outOrderNo,
        amount: withdrawOrder.amount,
        charge: withdrawOrder.charge,
        currency: withdrawOrder.currency,
        status: withdrawOrder.status,
        message: withdrawOrder.remark
      };
      const signStr = this.utils.signSort(params);
      params.sign = md5(signStr + `&key=${merchant.key}`);
      if (isOnce) {
        return await this.notifyReq(url, params);
      } else {
        this.notifySchedule(url, params);
        return {
          status: 1,
        };
      }
    } catch (err) {
      this.logger.error('代付回调通知失败', withdrawOrder.orderNo, err.message);
    }
  }

  async notifySchedule(url, params, idx = -1) {
    if (idx >= notifyTimes.length) {
      return;
    }
    const res = await this.notifyReq(url, params, idx + 2);
    if (res && +res.status === 0) {
      setTimeout(
        (url, params, idx) => {
          this.notifySchedule(url, params, idx + 1);
        },
        notifyTimes[idx + 1] * 1000,
        url,
        params,
        idx
      );
    }
  }
}
