import { Provide, Inject } from '@midwayjs/decorator';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import * as _ from 'lodash';
import { WithdrawEntity } from '../entity/withdraw';
import { DispatchService } from './channels/dispatch';
import { CoolCommException } from '@cool-midway/core';
import { Utils } from '../../../comm/utils';
import moment = require('moment');
import { MerchantEntity } from '../entity/merchant';
import { WithdrawStateService } from './withdrawState';
import { WithdrawNotifyService } from './withdrawNotify';

@Provide()
export class WithdrawService extends BaseService {
  @InjectEntityModel(WithdrawEntity)
  withdrawEntity: Repository<WithdrawEntity>;

  @Inject()
  dispatchService: DispatchService;

  @Inject()
  utils: Utils;

  @Inject()
  ctx;

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

  @Inject()
  withdrawStateService: WithdrawStateService;

  @Inject()
  withdrawNotifyService: WithdrawNotifyService

  async summary(query) {
    let {
      orderNo = '',
      outOrderNo = '',
      traceNo = '',
      mchId = '',
      code = '',
      status = '',
      createTime = [],
    } = query;
    if (!createTime || createTime.length !== 2) {
      return {
        num1: 0,
        num2: 0,
        num3: 0,
        num4: 0
      };
    }
    if (moment(createTime[1]).diff(moment(createTime[0]), 'days') > 30) {
      return {
        num1: 0,
        num2: 0,
        num3: 0,
        num4: 0
      };
    }
    const { roleIds, userId } = this.ctx.admin;
    if (this.utils.isMerchant(roleIds)) {
      const merchant = await this.merchantEntity.findOneBy({ userId });
      if (merchant) {
        mchId = merchant.mchId;
      } else {
        mchId = '-1';
      }
    }
    const sql = `SELECT 
    SUM(IF(a.status = 8, a.amount, 0)) as num1,
    SUM(IF(a.status = 8, a.charge, 0)) as num2,
    SUM(IF(a.status = 8, 1, 0)) as num3
    ${this.utils.isMerchant(roleIds)
        ? ''
        : ',SUM(IF(a.status = 8, a.channelCharge, 0)) as num4'
      }
    FROM dj_withdraw a WHERE 1=1
      ${this.setSql(orderNo, 'and a.orderNo like ?', [`%${orderNo}%`])}
      ${this.setSql(outOrderNo, 'and a.outOrderNo like ?', [`%${outOrderNo}%`])}
      ${this.setSql(traceNo, 'and a.traceNo like ?', [`%${traceNo}%`])}
      ${this.utils.isMerchant(roleIds)
        ? this.setSql(mchId, 'and a.mchId = ?', [`${mchId}`])
        : this.setSql(mchId, 'and a.mchId like ?', [`%${mchId}%`])
      }
      ${this.setSql(code, 'and a.code = ?', [code])}
      ${this.setSql(status, 'and a.status = ?', [status])}
      ${this.setSql(
        createTime && createTime.length === 2,
        'and (a.createTime between ? and ?)',
        createTime
      )}
    `;
    return this.nativeQuery(sql);
  }

  async page(query) {
    let {
      orderNo = '',
      outOrderNo = '',
      traceNo = '',
      mchId = '',
      code = '',
      status = '',
      createTime = [],
    } = query;
    if (!createTime || createTime.length !== 2) {
      throw new CoolCommException('请选择日期范围');
    }
    if (moment(createTime[1]).diff(moment(createTime[0]), 'days') > 30) {
      throw new CoolCommException('日期范围最大只能30天');
    }
    const { roleIds, userId } = this.ctx.admin;
    if (this.utils.isMerchant(roleIds)) {
      const merchant = await this.merchantEntity.findOneBy({ userId });
      if (merchant) {
        mchId = merchant.mchId;
      } else {
        mchId = '-1';
      }
    }
    const sql = `SELECT a.id, a.orderNo, a.outOrderNo, a.traceNo, a.mchId,  a.code, a.amount, a.currency, 
    ${this.utils.isMerchant(roleIds) ? '' : 'a.channelCharge,'} 
    a.charge, a.status, a.notifyUrl,  a.remark, a.createTime, a.updateTime, a.personIdType, a.personId, a.accountNo, a.personName, a.bankName, a.bankCode 
    FROM dj_withdraw a WHERE 1=1
      ${this.setSql(orderNo, 'and a.orderNo like ?', [`%${orderNo}%`])}
      ${this.setSql(outOrderNo, 'and a.outOrderNo like ?', [`%${outOrderNo}%`])}
      ${this.setSql(traceNo, 'and a.traceNo like ?', [`%${traceNo}%`])}
      ${this.utils.isMerchant(roleIds)
        ? this.setSql(mchId, 'and a.mchId = ?', [`${mchId}`])
        : this.setSql(mchId, 'and a.mchId like ?', [`%${mchId}%`])
      }
      ${this.setSql(code, 'and a.code = ?', [code])}
      ${this.setSql(status, 'and a.status = ?', [status])}
      ${this.setSql(
        createTime && createTime.length === 2,
        'and (a.createTime between ? and ?)',
        createTime
      )}
    `;
    return this.sqlRenderPage(sql, query);
  }

  async findByOutOrderNo(outOrderNo: any) {
    return await this.withdrawEntity.findOneBy({ outOrderNo });
  }

  async create(withdraw: WithdrawEntity) {
    withdraw.createTime = new Date();
    withdraw.updateTime = new Date();
    return await this.withdrawEntity.insert(withdraw);
  }

  async update(param) {
    const { roleIds } = this.ctx.admin;
    if (this.utils.isMerchant(roleIds)) {
      return;
    }
    const withdraw = await this.withdrawEntity.findOneBy({ id: param.id });
    if (!withdraw) {
      throw new Error('订单不存在');
    }
    withdraw.personIdType = param.personIdType;
    withdraw.personId = param.personId;
    withdraw.personName = param.personName;
    withdraw.accountNo = param.accountNo;
    withdraw.bankCode = param.bankCode;
    withdraw.bankName = param.bankName;
    withdraw.remark = param.remark;
    const status = +param.status;
    if (status === this.withdrawStateService.STATUS.PROCESSIONG) {
      withdraw.code = param.code;
    }
    if (status === this.withdrawStateService.STATUS.SUCCESS) {
      withdraw.code = param.code;
      withdraw.traceNo = param.traceNo;
    }
    return await this.withdrawStateService.stateTo(withdraw.status, status, withdraw);
  }

  async queryByApi(id) {
    const withdraw = await this.withdrawEntity.findOneBy({ id });
    if (!withdraw) {
      throw new CoolCommException('订单不存在');
    }
    if (+withdraw.status === this.withdrawStateService.STATUS.PROCESSIONG) {
      const data = await this.dispatchService.queryWithdraw(withdraw);
      if (+data.status === this.withdrawStateService.STATUS.SUCCESS
        || +data.status === this.withdrawStateService.STATUS.FAIL) {
        // 更新订单和更新余额
        if (data.traceNo) {
          withdraw.traceNo = data.traceNo
        }
        if (data.message) {
          withdraw.remark = data.message;
        }
        await this.withdrawStateService.stateTo(+withdraw.status, +data.status, withdraw);
      }
      return data;
    } else {
      return {
        status: 1,
        message: '订单状态异常'
      };
    }
  }

  async handleWithdrawNotify(code, payload, headers) {
    const data = await this.dispatchService.handleWithdrawNotify(code, payload, headers);
    const withdraw = await this.withdrawEntity.findOneBy({
      orderNo: data.orderNo,
    });
    if (data.traceNo) {
      withdraw.traceNo = data.traceNo
    }
    if (data.message) {
      withdraw.remark = data.message + '\n' + withdraw.remark;
    }
    await this.withdrawStateService.stateTo(withdraw.status, +data.status, withdraw);
  }

  async notify(id) {
    const withdraw = await this.withdrawEntity.findOneBy({ id });
    if (withdraw && +withdraw.status === this.withdrawStateService.STATUS.SUCCESS
      || withdraw && +withdraw.status === this.withdrawStateService.STATUS.FAIL) {
      return await this.withdrawNotifyService.notify(withdraw, true);
    }
  }
}
