package org.dromara.payment.merchant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.enums.BusRole;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.BaseService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.payment.api.merchant.domain.RemoteBusMerchantAccountVo;
import org.dromara.payment.common.domain.BusAccounts;
import org.dromara.payment.common.mapper.BusAccountsMapper;
import org.dromara.payment.merchant.domain.BusMerchant;
import org.dromara.payment.merchant.domain.vo.BusMerchantRechargeVo;
import org.dromara.payment.merchant.domain.vo.BusMerchantVo;
import org.dromara.payment.merchant.mapper.BusMerchantMapper;
import org.dromara.payment.operator.domain.BusOperatorAccount;
import org.dromara.payment.operator.domain.vo.BusOperatorAccountVo;
import org.dromara.payment.operator.service.IBusOperatorAccountService;
import org.dromara.payment.sys.domain.vo.SysSydAccountVo;
import org.dromara.payment.sys.domain.vo.SysSydVo;
import org.dromara.payment.sys.mapper.SysSydMapper;
import org.dromara.settlement.api.RemoteAccountService;
import org.dromara.settlement.api.domain.Account;
import org.dromara.settlement.api.domain.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.payment.merchant.domain.bo.BusMerchantAccountBo;
import org.dromara.payment.merchant.domain.vo.BusMerchantAccountVo;
import org.dromara.payment.merchant.domain.BusMerchantAccount;
import org.dromara.payment.merchant.mapper.BusMerchantAccountMapper;
import org.dromara.payment.merchant.service.IBusMerchantAccountService;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 商户资金账户Service业务层处理
 *
 * @author LionLi
 * @date 2024-04-03
 */
@RequiredArgsConstructor
@Service
public class BusMerchantAccountServiceImpl extends BaseService implements IBusMerchantAccountService {

    private final BusMerchantAccountMapper baseMapper;

    private final BusAccountsMapper accountsMapper;

    private final BusMerchantMapper merchantMapper;

    private final SysSydMapper sydMapper;

    private final IBusOperatorAccountService busOperatorAccountService;

    @DubboReference
    private RemoteAccountService accountService;

    @Autowired
    private BusAccountsMapper busAccountsMapper;

    /**
     * 查询商户资金账户
     */
    @Override
    public BusMerchantAccountVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询商户资金账户列表
     */
    @Override
    public TableDataInfo<BusMerchantAccountVo> queryPageList(BusMerchantAccountBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BusMerchantAccount> lqw = buildQueryWrapper(bo);
        Page<BusMerchantAccountVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询商户资金账户列表
     */
    @Override
    public List<BusMerchantAccountVo> queryList(BusMerchantAccountBo bo) {
        LambdaQueryWrapper<BusMerchantAccount> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BusMerchantAccount> buildQueryWrapper(BusMerchantAccountBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BusMerchantAccount> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getMerId() != null, BusMerchantAccount::getMerId, bo.getMerId());
        lqw.eq(bo.getSydId() != null, BusMerchantAccount::getSydId, bo.getSydId());
        lqw.eq(bo.getAccId() != null, BusMerchantAccount::getAccId, bo.getAccId());
        lqw.eq(StringUtils.isNotBlank(bo.getBankType()), BusMerchantAccount::getBankType, bo.getBankType());
        lqw.eq(StringUtils.isNotBlank(bo.getBankVirtualCard()), BusMerchantAccount::getBankVirtualCard, bo.getBankVirtualCard());
        lqw.eq(bo.getBalance() != null, BusMerchantAccount::getBalance, bo.getBalance());
        lqw.eq(bo.getFrozen() != null, BusMerchantAccount::getFrozen, bo.getFrozen());
        lqw.eq(bo.getIsDefault() != null, BusMerchantAccount::getIsDefault, bo.getIsDefault());
        lqw.eq(bo.getAddTime() != null, BusMerchantAccount::getAddTime, bo.getAddTime());
        lqw.eq(bo.getSettlement() != null, BusMerchantAccount::getSettlement, bo.getSettlement());
        lqw.eq(bo.getInvoiceSettlement() != null, BusMerchantAccount::getInvoiceSettlement, bo.getInvoiceSettlement());
        lqw.eq(bo.getInvoice() != null, BusMerchantAccount::getInvoice, bo.getInvoice());
        lqw.eq(bo.getStatus() != null, BusMerchantAccount::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getOutBankCard()), BusMerchantAccount::getOutBankCard, bo.getOutBankCard());
        return lqw;
    }

    /**
     * 新增商户资金账户
     */
    @Override
    public Boolean insertByBo(BusMerchantAccountBo bo) {
        BusMerchantAccount add = MapstructUtils.convert(bo, BusMerchantAccount.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改商户资金账户
     */
    @Override
    public Boolean updateByBo(BusMerchantAccountBo bo) {
        BusMerchantAccount update = MapstructUtils.convert(bo, BusMerchantAccount.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BusMerchantAccount entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除商户资金账户
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<BusMerchantAccountVo> getAccByMerIdAndSydId(Long merId, Long sydId) {
        return baseMapper.getAccByMerIdAndSydId(merId,sydId);
    }

    @Override
    public BusMerchantAccountVo getDefaultAccByMerIdAndSydId(Long merId, Long sydId) {
        List<BusMerchantAccountVo> list = baseMapper.getAccByMerIdAndSydId(merId,sydId);
        for (BusMerchantAccountVo acc:
            list) {
            if(acc.getIsDefault() == 1){
                return acc;
            }
        }
        return list.size() > 0 ? list.get(0) : null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateBalance(Long sydId, long unitId, long amount, String bankType) {
        Integer baseNum = accountsMapper.updateBalance(sydId,unitId,amount,bankType);
        Integer curNum = baseMapper.updateBalance(sydId,unitId,amount,bankType);
        return baseNum > 0 && curNum > 0 ? 1 : 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateFrozen(Long sydId, long unitId, long amount, String bankType) {
        Integer baseNum = accountsMapper.updateFrozen(sydId,unitId,amount,bankType);
        Integer curNum = baseMapper.updateFrozen(sydId,unitId,amount,bankType);
        return baseNum > 0 && curNum > 0 ? 1 : 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateBalanceByAccId(int accId, long amount) {
        Integer baseNum = accountsMapper.updateBalanceByAccId(accId,amount);
        Integer curNum = baseMapper.updateBalanceByAccId(accId,amount);
        return baseNum > 0 && curNum > 0 ? 1 : 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateFrozenByAccId(int accId, long amount) {
        Integer baseNum = accountsMapper.updateFrozenByAccId(accId,amount);
        Integer curNum = baseMapper.updateFrozenByAccId(accId,amount);
        return baseNum > 0 && curNum > 0 ? 1 : 0;
    }

    @Override
    public BusMerchantRechargeVo getRechargeAccount(int id) {
        BusMerchantRechargeVo rtn = new BusMerchantRechargeVo();
        BusMerchantAccountVo acc = baseMapper.selectByAccId(id);
        if(acc != null){
            BusMerchantVo merVo = merchantMapper.selectVoById(acc.getMerId());
            SysSydVo sydVo = sydMapper.selectVoById(acc.getSydId());
            rtn.setMerBankCard(merVo.getBankCard());
            rtn.setMerKhh(merVo.getKhh());
            rtn.setBankCard(acc.getBankVirtualCard());
            if (acc.getBankType().equals("支付宝")) {
                rtn.setAccName(merVo.getKhm());
                rtn.setBankType("支付机构备付金集中存管账户");
                rtn.setKhh("支付宝-备付金账户");
                rtn.setKhd("上海市-上海市");
                rtn.setKhhNo("991290000015");
            }else{
//                rtn.setAccName(sydVo.getGsmc());
//                rtn.setBankType(acc.getBankType());
//                rtn.setKhh(sydVo.getKfh());
//                rtn.setKhd(sydVo.getKfd());
//                rtn.setKhhNo(sydVo.getKhhNo());

                rtn.setAccName(acc.getName());
                rtn.setBankType(acc.getBankType());
                rtn.setKhh(acc.getKhh());
//                rtn.setKhd(sydVo.getKfd());
                rtn.setKhhNo(acc.getLhh());
            }
        }
        return rtn;
    }

    @Override
    public BusMerchantAccountVo getCashoutAccount(Long id) {
        BusMerchantAccountVo rtn = baseMapper.selectVoById(id);
        if(rtn != null){
            BusMerchantVo vo  = merchantMapper.selectVoById(rtn.getMerId());
            rtn.setAccName(vo.getKhm());
            rtn.setBankVirtualCard(vo.getBankCard());
            rtn.setKfd(vo.getKhd());
            rtn.setKfh(vo.getKhh());
            rtn.setKhhNo(vo.getKhhNo());
        }
        return rtn;
    }

    @Override
    public List<BusMerchantAccountVo> getMerAccountList(BusMerchantAccountBo bo, PageQuery pageQuery) {
        if(bo.getMerId() == null){
            this.invalidationParamsException("企业ID不能为空");
        }
        if(StringUtils.isEmpty(bo.getBankType())){
            this.invalidationParamsException("银行通道不能为空");
        }
        return this.baseMapper.selectMerAccountLists(bo,pageQuery.build());
    }

    @Override
    public Boolean createXnAccount(Long sydId, Long merId, String merName, String bankType) {
        if(sydId == null){
            this.invalidationParamsException("服务商ID不能为空");
        }
        if(merId == null){
            this.invalidationParamsException("运营商ID不能为空");
        }
        if(StringUtils.isEmpty(merName)){
            this.invalidationParamsException("企业名称不能为空");
        }
        if(StringUtils.isEmpty(bankType)){
            this.invalidationParamsException("银行类型不能为空");
        }
        List<BusMerchantAccountVo> accs = this.baseMapper.selectByMerIdAndSydId(sydId,merId,bankType);
        if(!accs.isEmpty()){
            return true;
        }
        Boolean sydRtn = busOperatorAccountService.creatXNnum(sydId,merId,merName, BusRole.MERCHANT.getId(),BusRole.PLATFORM.getId(),bankType, add -> {
            if(add != null) {
                if(add.getId() > 0) {
                    Integer num =  this.baseMapper.insertAccount(new BusMerchantAccount(null,merId,sydId,add.getAccId(),add.getBankType(), add.getBankCard(),0L,0L,1L, add.getAddTime(),add.getName(),
                        add.getKhh(),add.getLhh()));
                    return num > 0;
                }
                return true;
            }
            return false;
        }, bankType1 -> {
            List<BusMerchantAccountVo> accs1 = this.baseMapper.selectByMerIdAndSydId(sydId,merId,bankType);
            return accs1.size() > 0 ? accs1.get(0).getBankVirtualCard() : null;
        });
        return sydRtn;
    }

    @Override
    public Boolean createThirdXnAccount(Long sydId, Long merId, String merName, String bankType,String bankCard,String accName) {

        List<BusMerchantAccountVo> accs = this.baseMapper.selectByMerIdAndSydId(sydId,merId,bankType);
        if(!accs.isEmpty()){
            return true;
        }

        Account bankAcc = new Account();
        bankAcc.setType((short)1);//2:真实个人账户
        bankAcc.setBankCard(bankCard);
        bankAcc.setBankType(bankType);
        bankAcc.setUnitId(merId);
        bankAcc.setName(accName);
        bankAcc.setBankName(bankType);
        bankAcc.setStatus((short)1);
        Result<Account> addAccount = this.accountService.addAccount(bankAcc);

        Date createTime = new Date();
        Account rtnData = addAccount.getRtnData();
        BusAccounts add = new BusAccounts(sydId,merId,(long)rtnData.getId(),rtnData.getBankTypeName(), rtnData.getBankCard(),1l,createTime,BusRole.PLATFORM.getId(),rtnData.getName(),
            rtnData.getBankName(), rtnData.getBankNo());
        busAccountsMapper.insertSelective(add);
        if(add.getId() == null){
            add.setId(0l);
        }

        if(add.getId() > 0) {
            Integer num =  this.baseMapper.insertAccount(new BusMerchantAccount(null,merId,sydId,add.getAccId(),add.getBankType(), add.getBankCard(),0L,0L,1L, add.getAddTime(),add.getName(),
                add.getKhh(),add.getLhh()));
        }
        return true;
    }

}
