package com.jeequan.jeepay.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.converter.TransferConverter;
import com.jeequan.jeepay.core.entity.AccountOperate;
import com.jeequan.jeepay.core.interfaces.paychannel.ITransferService;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.AccountFundInfo;
import com.jeequan.jeepay.db.entity.TransferOrderEntity;
import com.jeequan.jeepay.db.entity.TransferWalletEntity;
import com.jeequan.jeepay.service.mapper.TransferOrderMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 转账订单表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2021-08-11
 */
@Service
public class TransferOrderService extends ServiceImpl<TransferOrderMapper, TransferOrderEntity> {


    @Autowired
    private TransferConverter transferConverter;

    @Autowired
    private TransferOrderMapper transferOrderMapper;

    @Autowired
    private AccountInfoService accountInfoService;
    @Autowired
    private TransferWalletService transferWalletService;

    /**
     * 更新转账订单状态  【转账订单生成】 --》 【转账中】
     **/
    public boolean updateInit2Ing(String transferId) {

        TransferOrderEntity updateRecord = new TransferOrderEntity();
        updateRecord.setState(TransferOrderEntity.STATE_ING);

        return update(updateRecord, new LambdaUpdateWrapper<TransferOrderEntity>()
                .eq(TransferOrderEntity::getTransferId, transferId).eq(TransferOrderEntity::getState, TransferOrderEntity.STATE_INIT));
    }


    /**
     * 更新转账订单状态  【转账中】 --》 【转账成功】
     */
    @Transactional
    public boolean updateIng2Success(String transferId, String channelOrderNo) {

        TransferOrderEntity updateRecord = new TransferOrderEntity();
        updateRecord.setState(TransferOrderEntity.STATE_SUCCESS);
        updateRecord.setChannelOrderNo(channelOrderNo);
        updateRecord.setSuccessTime(new Date());
        //扣除手续费账户余额
        accountInfoService.tranferFeeAccount(transferId);

        // 刷新记账本余额
        TransferOrderEntity existData = getById(transferId);
        TransferWalletEntity transferWallet = transferWalletService.getByApplyId(existData.getTransferSubjectIdFq(), null);
        ITransferService transferService = SpringBeansUtil.getBean(existData.getIfCode() + "TransferService", ITransferService.class);

        // 查询更新余额
        MutablePair<String, Long> walletBalance = transferService.queryBalanceAmount(transferConverter.toModel(transferWallet));
        transferWallet.setAccountBookBalance(walletBalance.right);
        transferWalletService.updateById(transferWallet);

        //更新转账订单表数据
        if (!update(updateRecord, new LambdaUpdateWrapper<TransferOrderEntity>()
                .eq(TransferOrderEntity::getTransferId, transferId).eq(TransferOrderEntity::getState, TransferOrderEntity.STATE_ING))
        ) {
            return false;
        }

        return true;
    }


    /**
     * 更新转账订单状态  【转账中】 --》 【转账失败】
     */
    @Transactional
    public boolean updateIng2Fail(String transferId, String channelOrderNo, String channelErrCode, String channelErrMsg) {

        // 预扣手续费
        AccountOperate operate = new AccountOperate(transferId,true, AccountFundInfo.FAIL);
        accountInfoService.upAccount(operate);

        TransferOrderEntity updateRecord = new TransferOrderEntity();
        updateRecord.setState(TransferOrderEntity.STATE_FAIL);
        updateRecord.setErrCode(channelErrCode);
        updateRecord.setErrMsg(channelErrMsg);
        updateRecord.setChannelOrderNo(channelOrderNo);

        return update(updateRecord, new LambdaUpdateWrapper<TransferOrderEntity>()
                .eq(TransferOrderEntity::getTransferId, transferId).eq(TransferOrderEntity::getState, TransferOrderEntity.STATE_ING));

    }


    /**
     * 更新转账订单状态  【转账中】 --》 【转账成功/转账失败】
     */
    @Transactional
    public boolean updateIng2SuccessOrFail(String transferId, Byte updateState, String channelOrderNo, String channelErrCode, String channelErrMsg) {

        if (updateState == TransferOrderEntity.STATE_ING) {
            return true;
        } else if (updateState == TransferOrderEntity.STATE_SUCCESS) {
            return updateIng2Success(transferId, channelOrderNo);
        } else if (updateState == TransferOrderEntity.STATE_FAIL) {
            return updateIng2Fail(transferId, channelOrderNo, channelErrCode, channelErrMsg);
        }
        return false;
    }


    /**
     * 查询商户订单
     */
    public TransferOrderEntity queryMchOrder(String mchNo, String mchOrderNo, String transferId) {

        if (StringUtils.isNotEmpty(transferId)){
            return getOne(TransferOrderEntity.gw().eq(TransferOrderEntity::getMchNo, mchNo).eq(TransferOrderEntity::getTransferId, transferId));
        } else if (StringUtils.isNotEmpty(mchOrderNo)) {
            return getOne(TransferOrderEntity.gw().eq(TransferOrderEntity::getMchNo, mchNo).eq(TransferOrderEntity::getMchOrderNo, mchOrderNo));
        } else {
            return null;
        }
    }


    public IPage<TransferOrderEntity> pageList(IPage<TransferOrderEntity> iPage, TransferOrderEntity transferOrder) {

        // 时间范围条件
        Date[] dateRange = transferOrder.buildQueryDateRange();
        if (dateRange[0] != null) {
            transferOrder.setFirstDate(dateRange[0]);
        }
        if (dateRange[1] != null) {
            transferOrder.setLastDate(dateRange[1]);
        }
        iPage.orders().add(OrderItem.desc("tra.created_at"));
        IPage<TransferOrderEntity> ipageList = transferOrderMapper.selectPageList(iPage, transferOrder);

        return ipageList;
    }

    public void selectParams(LambdaQueryWrapper<TransferOrderEntity> wrapper, TransferOrderEntity transferOrder) {
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getTransferId()), TransferOrderEntity::getTransferId, transferOrder.getTransferId());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getMchOrderNo()), TransferOrderEntity::getMchOrderNo, transferOrder.getMchOrderNo());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getChannelOrderNo()), TransferOrderEntity::getChannelOrderNo, transferOrder.getChannelOrderNo());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getMchNo()), TransferOrderEntity::getMchNo, transferOrder.getMchNo());
        wrapper.eq(transferOrder.getState() != null, TransferOrderEntity::getState, transferOrder.getState());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getAppId()), TransferOrderEntity::getAppId, transferOrder.getAppId());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getIfCode()), TransferOrderEntity::getIfCode, transferOrder.getIfCode());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getTransferSubjectIdFq()), TransferOrderEntity::getTransferSubjectIdFq,transferOrder.getTransferSubjectIdFq());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getTransferSubjectIdJs()), TransferOrderEntity::getTransferSubjectIdJs,transferOrder.getTransferSubjectIdJs());
        wrapper.eq(transferOrder.getTransferType() != null, TransferOrderEntity::getTransferType,transferOrder.getTransferType());
        wrapper.eq(StringUtils.isNotEmpty(transferOrder.getAgentNo()), TransferOrderEntity::getAgentNo,transferOrder.getAgentNo());
        wrapper.in(!Objects.isNull(transferOrder.getSubAgentNoList()),TransferOrderEntity::getAgentNo,transferOrder.getSubAgentNoList());

        // 时间范围条件
        Date[] dateRange = transferOrder.buildQueryDateRange();
        if (dateRange[0] != null) {
            wrapper.ge(TransferOrderEntity::getCreatedAt, dateRange[0]);
        }
        if (dateRange[1] != null) {
            wrapper.le(TransferOrderEntity::getCreatedAt, dateRange[1]);
        }

    }

    /**
     * 转账统计
     */
    public Map queryCount(LambdaQueryWrapper<TransferOrderEntity> wrapper) {
        return baseMapper.queryCount(wrapper);
    }

    /**
     * 查询累计交易额
     *
     * @param dateType            时间类型 <br/>
     *                            DateField.DAY_OF_YEAR、DateField.DAY_OF_MONTH 日
     *                            DateField.MONTH 月
     * @param date                查询日期
     * @param transferType        交易类型
     * @param transferSubjectFqId 发起方的ID
     * @param state               状态列表
     * @return
     */
    public Map<String, Long> accumulated(DateField dateType, Date date,
                            Integer transferType, String transferSubjectFqId, Object... state) {
        Assert.notEmpty(state, "查询订单状态值不能为空");

        boolean isDayType = DateField.DAY_OF_YEAR.equals(dateType) || DateField.DAY_OF_MONTH.equals(dateType);
        LambdaQueryWrapper<TransferOrderEntity> qWrapper = Wrappers.<TransferOrderEntity>query()
                .select("IFNULL(SUM(amount), 0) amount, entryType")
                .lambda()
                .eq(TransferOrderEntity::getTransferSubjectIdFq, transferSubjectFqId)
                .eq(TransferOrderEntity::getTransferType, transferType)
                .in(TransferOrderEntity::getState, state)
                .groupBy(TransferOrderEntity::getEntryType);

        // 查询月
        if (DateField.MONTH.equals(dateType)) {
            qWrapper.ge(TransferOrderEntity::getCreatedAt, DateUtil.beginOfMonth(date));
        }

        // 查询天
        if (isDayType) {
            qWrapper.ge(TransferOrderEntity::getCreatedAt, DateUtil.beginOfDay(date));
        }

        List<TransferOrderEntity> transferOrderEntities = baseMapper.selectList(qWrapper);

        Map<String, Long> resultMap = new HashMap<>();

        transferOrderEntities.forEach(it -> resultMap.put(it.getEntryType(), it.getAmount()));

        return resultMap;
    }

    public Long accumulated(DateField dateType, Date date,
                                         Integer transferType, String entryType, String transferSubjectFqId, Object... state) {
        Assert.notEmpty(state, "查询订单状态值不能为空");

        boolean isDayType = DateField.DAY_OF_YEAR.equals(dateType) || DateField.DAY_OF_MONTH.equals(dateType);
        LambdaQueryWrapper<TransferOrderEntity> qWrapper = Wrappers.<TransferOrderEntity>query()
                .select("IFNULL(SUM(amount), 0) amount, entryType")
                .lambda()
                .eq(TransferOrderEntity::getTransferSubjectIdFq, transferSubjectFqId)
                .eq(TransferOrderEntity::getTransferType, transferType)
                .eq(TransferOrderEntity::getEntryType, entryType)
                .in(TransferOrderEntity::getState, state)
                .groupBy(TransferOrderEntity::getEntryType);

        // 查询月
        if (DateField.MONTH.equals(dateType)) {
            qWrapper.ge(TransferOrderEntity::getCreatedAt, DateUtil.beginOfMonth(date));
        }

        // 查询天
        if (isDayType) {
            qWrapper.ge(TransferOrderEntity::getCreatedAt, DateUtil.beginOfDay(date));
        }

        return baseMapper.selectOne(qWrapper).getAmount();
    }
}
