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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
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.common.domain.BusAccounts;
import org.dromara.payment.common.mapper.BusAccountsMapper;
import org.dromara.payment.merchant.domain.vo.BusMerchantAccountVo;
import org.dromara.payment.merchant.domain.vo.BusMerchantVo;
import org.dromara.payment.operator.domain.vo.BusOperatorCashoutVo;
import org.dromara.payment.operator.domain.vo.BusOperatorVo;
import org.dromara.payment.operator.mapper.BusOperatorMapper;
import org.dromara.payment.sys.domain.SysSydAccount;
import org.dromara.payment.sys.service.impl.BankAccountServiceTransactionImpl;
import org.dromara.payment.sys.service.impl.SysSydServiceTransactionImpl;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
import org.dromara.payment.operator.domain.bo.BusOperatorAccountBo;
import org.dromara.payment.operator.domain.vo.BusOperatorAccountVo;
import org.dromara.payment.operator.domain.BusOperatorAccount;
import org.dromara.payment.operator.mapper.BusOperatorAccountMapper;
import org.dromara.payment.operator.service.IBusOperatorAccountService;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.function.Function;

/**
 * 运营商资金账户Service业务层处理
 *
 * @author LionLi
 * @date 2024-03-28
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class BusOperatorAccountServiceImpl extends BaseService implements IBusOperatorAccountService {


    private final BusOperatorAccountMapper baseMapper;

    private final BusOperatorMapper operatorMapper;

    private final BusAccountsMapper accountsMapper;

    private final SysSydServiceTransactionImpl transactionImpl;

    private final BankAccountServiceTransactionImpl bankAccountTransactionImpl;

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





    @Override
    public List<BusOperatorAccountVo>  queryListFp(BusOperatorAccountBo bo, PageQuery pageQuery){
        if(bo.getOpId() == null){
            this.invalidationParamsException("运营商ID不能为空");
        }

        if(StringUtils.isEmpty(bo.getBankType())){
            this.invalidationParamsException("银行通道不能为空");
        }
        return this.baseMapper.selectOperatorAccountLists(bo,pageQuery.build());
    }


    /**
     * 查询运营商资金账户列表
     */
    @Override
    public TableDataInfo<BusOperatorAccountVo> queryPageList(BusOperatorAccountBo bo, PageQuery pageQuery) {
        QueryWrapper<BusOperatorAccount> lqw = buildQueryWrapper2(bo);
        Page<BusOperatorAccountVo> result = baseMapper.queryPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询运营商资金账户列表
     */
    @Override
    public List<BusOperatorAccountVo> queryList(BusOperatorAccountBo bo) {
        QueryWrapper<BusOperatorAccount> lqw = buildQueryWrapper2(bo);
        return baseMapper.queryList(lqw);
    }

    private LambdaQueryWrapper<BusOperatorAccount> buildQueryWrapper(BusOperatorAccountBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BusOperatorAccount> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getOpId() != null, BusOperatorAccount::getOpId, bo.getOpId());
        lqw.eq(bo.getSydId() != null, BusOperatorAccount::getSydId, bo.getSydId());
        lqw.eq(bo.getAccId() != null, BusOperatorAccount::getAccId, bo.getAccId());
        lqw.eq(StringUtils.isNotBlank(bo.getBankType()), BusOperatorAccount::getBankType, bo.getBankType());
        lqw.eq(StringUtils.isNotBlank(bo.getBankVirtualCard()), BusOperatorAccount::getBankVirtualCard, bo.getBankVirtualCard());
        lqw.eq(bo.getBalance() != null, BusOperatorAccount::getBalance, bo.getBalance());
        lqw.eq(bo.getFrozen() != null, BusOperatorAccount::getFrozen, bo.getFrozen());
        lqw.eq(bo.getCashout() != null, BusOperatorAccount::getCashout, bo.getCashout());
        lqw.eq(bo.getCashouting() != null, BusOperatorAccount::getCashouting, bo.getCashouting());
        lqw.eq(bo.getIsDefault() != null, BusOperatorAccount::getIsDefault, bo.getIsDefault());
        lqw.eq(bo.getAddTime() != null, BusOperatorAccount::getAddTime, bo.getAddTime());
        lqw.eq(bo.getStatus() != null, BusOperatorAccount::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getOutBankCard()), BusOperatorAccount::getOutBankCard, bo.getOutBankCard());
        return lqw;
    }


    private QueryWrapper<BusOperatorAccount> buildQueryWrapper2(BusOperatorAccountBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<BusOperatorAccount> lqw = Wrappers.query();
        lqw.eq(bo.getOpId() != null, "t.op_id", bo.getOpId());
        lqw.eq(bo.getSydId() != null, "t.syd_id", bo.getSydId());
        lqw.eq(bo.getAccId() != null, "t.acc_id", bo.getAccId());
        lqw.eq(StringUtils.isNotBlank(bo.getBankType()), "t.bank_type", bo.getBankType());
        lqw.eq(StringUtils.isNotBlank(bo.getBankVirtualCard()), "t.bank_virtual_card", bo.getBankVirtualCard());
        lqw.eq(bo.getBalance() != null, "t.balance", bo.getBalance());
        lqw.eq(bo.getFrozen() != null, "t.frozen", bo.getFrozen());
        lqw.eq(bo.getCashout() != null, "t.cashout", bo.getCashout());
        lqw.eq(bo.getCashouting() != null, "t.cashouting", bo.getCashouting());
        lqw.eq(bo.getIsDefault() != null,"t.is_default", bo.getIsDefault());
        lqw.eq(bo.getAddTime() != null,"t.add_time", bo.getAddTime());
        lqw.eq(bo.getStatus() != null, "t.status", bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getOutBankCard()), "t.out_bank_card", bo.getOutBankCard());
        return lqw;
    }

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

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

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

    /**
     * 批量删除运营商资金账户
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 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 BusOperatorAccountVo getCashoutAccount(Long id) {
        BusOperatorAccountVo rtn = baseMapper.selectVoById(id);
        if(rtn != null){
            BusOperatorVo vo  = operatorMapper.selectVoById(rtn.getOpId());
            rtn.setAccName(vo.getKhm());
            rtn.setBankVirtualCard(vo.getBankCard());
            rtn.setKfd(vo.getKhd());
            rtn.setKfh(vo.getKhh());
            rtn.setKhhNo(vo.getKhhNo());
        }
        return rtn;
    }

    @Override
    public Boolean createXnAccount(Long sydId, Long opId, String opName, String bankType) {

        if(sydId == null){
            this.invalidationParamsException("服务商ID不能为空");
        }
        if(opId == null){
            this.invalidationParamsException("运营商ID不能为空");
        }
        if(StringUtils.isEmpty(opName)){
            this.invalidationParamsException("运营商名称不能为空");
        }
        if(StringUtils.isEmpty(bankType)){
            this.invalidationParamsException("银行类型不能为空");
        }

        QueryWrapper  qw = Wrappers.query();
        qw.eq("t.syd_id",sydId);
        qw.eq("t.op_id",opId);
        qw.eq("t.bank_type",bankType);
        qw.eq("t.is_default",1);
        List<BusOperatorAccountVo> accs = this.baseMapper.queryList(qw);
        if(!accs.isEmpty()){
            return true;
        }
        Boolean sydRtn = creatXNnum(sydId,opId,opName, BusRole.OPERATOR.getId(),BusRole.PLATFORM.getId(),bankType, add -> {
            if(add != null) {
                if(add.getId() > 0) {
                    Integer num =  this.baseMapper.insertAccount(new BusOperatorAccount(opId,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 -> {
            QueryWrapper  qw1 = Wrappers.query();
            qw1.eq("t.syd_id",sydId);
            qw1.eq("t.op_id",opId);
            qw1.eq("t.bank_type",bankType);
            qw1.eq("t.is_default",1);
            List<BusOperatorAccountVo> accs1 = this.baseMapper.queryList(qw1);
//            List<SysSydAccount> accs = sysSydAccountMapper.selectSysSydAccountBySydId(id.intValue(), (short) 0, bankType1);
            return accs1.size() > 0 ? accs1.get(0).getBankVirtualCard() : null;
        });

        return true;
    }


    public Boolean creatXNnum(Long sydId, Long unitId, String gsmc, int roleType, int addRoleType,String bankType1, Function<BusAccounts,Boolean> saveFun, Function<String,String> existsFun) {
        String failBank = "";
        try {
            if("招商银行".equals(bankType1)){
                try {
                    transactionImpl.addZhaoShangAccount(sydId,unitId, gsmc,roleType,addRoleType,saveFun);
                } catch (Exception e) {
                    String bankType = "招商银行";
                    log.error(""+gsmc+  bankType + "虚拟户账户开通出错：" + e.getMessage(), e);
                    if (StringUtils.isNotEmpty(failBank)) {
                        failBank += "、";
                    }
                    failBank += bankType;
                }
            }else if("交通银行".equals(bankType1)){
                try {
                    transactionImpl.addJiaoTongAccount(sydId,unitId, gsmc,roleType,addRoleType,saveFun,existsFun);
                } catch (Exception e) {
                    String bankType = "交通银行";
                    log.error(""+gsmc+  bankType + "虚拟户账户开通出错：" + e.getMessage(), e);
                    if (StringUtils.isNotEmpty(failBank)) {
                        failBank += "、";
                    }
                    failBank += bankType;
                }
            }else if("支付宝".equals(bankType1)){
                try {
                    transactionImpl.addZhiFuBaoAccount(sydId,unitId, gsmc,roleType,addRoleType,saveFun);
                } catch (Exception e) {
                    String bankType = "支付宝";
                    log.error(""+gsmc+  bankType + "虚拟户账户开通出错：" + e.getMessage(), e);
                    if (StringUtils.isNotEmpty(failBank)) {
                        failBank += "、";
                    }
                    failBank += bankType;
                }
            }else if("民生银行".equals(bankType1)){
                try {
                    transactionImpl.addMinShengAccount(sydId,unitId, gsmc,roleType,addRoleType,saveFun);
                } catch (Exception e) {
                    String bankType = "民生银行";
                    log.error(""+gsmc+  bankType + "虚拟户账户开通出错：" + e.getMessage(), e);
                    if (StringUtils.isNotEmpty(failBank)) {
                        failBank += "、";
                    }
                    failBank += bankType;
                }
            }
            if (StringUtils.isNotEmpty(failBank)) {
                throw new ServiceException("开通账户失败[" + failBank + "]");
            }
            return true;
        } catch (Exception e) {
            String msgStr = "开虚拟户失败!";
            log.error(msgStr, e);
            if (e instanceof ServiceException) {
                throw new ServiceException(e.getMessage());
            } else {
                throw new ServiceException(msgStr);
            }
        }
    }
}
