package com.ghy.web.timer;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.enums.AdapayOrderType;
import com.ghy.common.utils.AdapayUtils;
import com.ghy.customer.domain.CustomerBank;
import com.ghy.customer.service.CustomerBankService;
import com.ghy.order.service.OrderDetailService;
import com.ghy.payment.domain.DrawCashRecord;
import com.ghy.payment.mapper.DrawCashRecordMapper;
import com.ghy.payment.service.AdapayService;
import com.ghy.worker.domain.WorkerBank;
import com.ghy.worker.service.WorkerBankService;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 定时器
 * 主动与Adapay同步支付、撤销支付、提现订单的状态
 */
@Slf4j
@Component
@EnableScheduling
public class AdapaySyncTimer {

    @Resource
    private AdapayService adapayService;
    @Resource
    private WorkerBankService workerBankService;
    @Resource
    private CustomerBankService customerBankService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private DrawCashRecordMapper drawCashRecordMapper;

    /**
     * 补偿提现定时器
     * 某些订单分账成功，但是提现失败，需要在这里为它重新发起提现
     */
    @Scheduled(fixedRate = 5 * 60 * 1000L)
    public void autoDrawCash() {
        List<WorkerBank> workerBanks = workerBankService.select(new WorkerBank());
        for (WorkerBank workerBank : workerBanks) {
            Long deptId = workerBank.getDeptId();
            String memberId = workerBank.getAdapayMemberId();
            String settleAccountId = workerBank.getSettleAccountId();
            if (deptId == null || StringUtils.isBlank(memberId) || StringUtils.isBlank(settleAccountId)) {
                continue;
            }
            try {
                JSONObject accountBalance = adapayService.queryAccountBalance(deptId, memberId, settleAccountId, "01");
                if (AdapayStatusEnum.succeeded.code.equals(accountBalance.getString("status"))) {
                    // 可提现金额
                    String avlBalance = accountBalance.getString("avl_balance");
                    if (BigDecimal.ZERO.compareTo(new BigDecimal(avlBalance)) > -1) {
                        continue;
                    }
                    // 提现
                    log.info("Worker[{},{}]开始提现: avlBalance={}", workerBank.getWorkerId(), workerBank.getName(), avlBalance);
                    String orderNo = AdapayUtils.createOrderNo(AdapayOrderType.DRAW_CASH);
                    JSONObject drawCash = adapayService.drawCash(deptId, orderNo, "T1", avlBalance, memberId, "提现", null);
                    log.info("Worker[{},{}]提现结果: {}", workerBank.getWorkerId(), workerBank.getName(), drawCash.toJSONString());
                } else {
                    log.error("Worker[{},{}]查询账户余额失败: {}", workerBank.getWorkerId(), workerBank.getName(), accountBalance.toJSONString());
                }
            } catch (BaseAdaPayException e) {
                log.error(e.getMessage(), e);
            }
        }

        List<CustomerBank> customerBanks = customerBankService.getCustomerBankList(new CustomerBank());
        for (CustomerBank customer : customerBanks) {
            Long deptId = customer.getDeptId();
            String memberId = customer.getAdapayMemberId();
            String settleAccountId = customer.getSettleAccountId();
            if (deptId == null || StringUtils.isBlank(memberId) || StringUtils.isBlank(settleAccountId)) {
                continue;
            }
            try {
                JSONObject accountBalance = adapayService.queryAccountBalance(deptId, memberId, settleAccountId, "01");
                if (AdapayStatusEnum.succeeded.code.equals(accountBalance.getString("status"))) {
                    // 可提现金额
                    String avlBalance = accountBalance.getString("avl_balance");
                    if (BigDecimal.ZERO.compareTo(new BigDecimal(avlBalance)) > -1) {
                        continue;
                    }
                    // 提现
                    log.info("Customer[{},{}]开始提现: avlBalance={}", customer.getCustomerId(), customer.getName(), avlBalance);
                    String orderNo = AdapayUtils.createOrderNo(AdapayOrderType.DRAW_CASH);
                    JSONObject drawCash = adapayService.drawCash(deptId, orderNo, "T1", avlBalance, memberId, "提现", null);
                    log.info("Customer[{},{}]提现结果: {}", customer.getCustomerId(), customer.getName(), drawCash.toJSONString());
                } else {
                    log.error("Customer[{},{}]查询账户余额失败: {}", customer.getCustomerId(), customer.getName(), accountBalance.toJSONString());
                }
            } catch (BaseAdaPayException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 定时同步提现状态
     */
    @Scheduled(fixedRate = 5 * 60 * 1000L)
    public void syncDrawCash() {
        List<DrawCashRecord> records = drawCashRecordMapper.selectByStatus("pending");
        if (CollectionUtils.isEmpty(records)) {
            log.debug("No pending drawCashRecord.");
            return;
        }
        for (DrawCashRecord record : records) {
            Long deptId = record.getDept_id();
            String orderNo = record.getOrder_no();
            if (deptId == null || StringUtils.isBlank(orderNo)) {
                continue;
            }
            try {
                syncDrawCashRecord(record, deptId, orderNo);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }

        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void syncDrawCashRecord(DrawCashRecord record, Long deptId, String orderNo) throws BaseAdaPayException {
        JSONObject response = adapayService.queryDrawCash(deptId, orderNo);
        // 这个status代表API调用状态 不代表提现状态
        if (AdapayStatusEnum.succeeded.code.equals(response.getString("status"))) {
            JSONArray cashList = response.getJSONArray("cash_list");
            if (!CollectionUtils.isEmpty(cashList)) {
                JSONObject cash = cashList.getJSONObject(0);
                // 这个才是提现状态
                String transStat = cash.getString("trans_stat");
                switch (transStat) {
                    // 提现成功
                    case "S":
                        log.info("DrawCashRecord[{}]提现成功", record.getId());
                        // 更新提现记录表状态
                        drawCashRecordMapper.updateStatus(record.getId(), "succeeded");
                        // 更新子订单表状态
                        orderDetailService.updateDrawCashStatus(record.getId(), 2, null, new Date());
                        break;
                    // 提现失败
                    case "F":
                        log.error("DrawCashRecord[{}]提现失败: {}", record.getId(), response.toJSONString());
                        // 更新提现记录表状态
                        drawCashRecordMapper.updateStatus(record.getId(), "failed");
                        // 更新子订单表状态
                        orderDetailService.updateDrawCashStatus(record.getId(), -1, null, null);
                        break;
                    default:
                        break;
                }
            }
        } else {
            log.error("DrawCash.query请求失败: {}", response.toJSONString());
        }
    }
}
