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

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

import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.enums.BusRole;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.payment.common.domain.BusAccounts;
import org.dromara.payment.common.mapper.BusAccountsMapper;
import org.dromara.payment.sys.domain.AccAccounts;
import org.dromara.payment.sys.domain.SysSyd;
import org.dromara.payment.sys.domain.SysSydAccount;
import org.dromara.payment.sys.domain.SysSydSignContent;
import org.dromara.payment.sys.mapper.SysSydAccountMapper;
import org.dromara.payment.sys.mapper.SysSydMapper;
import org.dromara.payment.sys.mapper.SysSydSignContentMapper;
import org.dromara.settlement.api.RemoteAccountService;
import org.dromara.settlement.api.domain.Account;
import org.dromara.settlement.api.domain.Result;
import org.dromara.settlement.api.domain.ResultCodeEnum;
import org.dromara.system.api.RemoteOrderNumService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


/**
 * 税源地Service业务层处理
 *
 * @author ruoyi
 * @date 2021-08-18
 */
@Service
@Slf4j
public class SysSydServiceTransactionImpl
{
    @DubboReference
    private RemoteAccountService accountService;

    @Autowired
    private BusAccountsMapper accountsMapper;

    @Autowired
    private SysSydMapper sydDao;

    @Autowired
    private SysSydSignContentMapper signDao;

    @Autowired
    private BankAccountServiceTransactionImpl bankAccountService;//银行账户业务


    @DubboReference
    private RemoteOrderNumService remoteOrderNumService;

	private String getOrderKey(int roleType){

		if(BusRole.SERVICE.getId() == roleType){
			return "service";
		}else if(BusRole.MERCHANT.getId() == roleType){
			return "merchant";
		}else if(BusRole.OPERATOR.getId() == roleType){
			return "operator";
		}else if(BusRole.PLATFORM.getId() == roleType){
			return "platform";
		}else{
			return "default";
		}


	}

    @Transactional
	public void addZhaoShangAccount(Long sydId,Long unitId, String gsmc,int roleType,int addRoleType, Function<BusAccounts,Boolean> saveFun) {
    	String bankType = "招商银行";
    	Map<String, String> configMap = bankAccountService.existsBank(sydId, bankType);
		if (configMap != null) {
			//开招商银行虚拟户
            Long code = this.remoteOrderNumService.getOrderNum(sydId+this.getOrderKey(roleType),5);
            log.info(roleType +"- 生成编号:"+code);
            if(code == null){
                throw new ServiceException("生成编号出错");
            }
			Result<Account> addAccount = accountService.addAccount(sydId, roleType, unitId,gsmc,bankType,code);
			if(addAccount !=null&&addAccount.getRtnCode() == ResultCodeEnum.SUCCESS.Code()){
                Date createTime = new Date();
                Account rtnData = addAccount.getRtnData();
                BusAccounts add = new BusAccounts(sydId,unitId,(long)rtnData.getId(),rtnData.getBankTypeName(), rtnData.getBankCard(),1l,createTime,addRoleType,rtnData.getName(),
                    rtnData.getBankName(), rtnData.getBankNo());
                accountsMapper.insertSelective(add);
                if(add.getId() == null){
                    add.setId(0l);
                }
                saveFun.apply(add);
			}else {
				throw new ServiceException("招商银行开虚拟户失败："+addAccount.getResult());
			}
		}
    }

    @Transactional
	public void addZhiFuBaoAccount(Long sydId,Long unitId, String gsmc,int roleType,int addRoleType, Function<BusAccounts,Boolean> saveFun) {
    	String bankType = "支付宝";
    	Map<String, String> configMap = bankAccountService.existsBank(sydId, bankType);
		if (configMap != null) {
			//开支付宝记账本
			Result<Account> addAccount = accountService.addAccount(sydId,roleType, unitId,gsmc,bankType,null);
			if(addAccount !=null&&addAccount.getRtnCode() == ResultCodeEnum.SUCCESS.Code()){
				Date createTime = new Date();
				Account rtnData = addAccount.getRtnData();
                BusAccounts add = new BusAccounts(sydId,unitId,(long)rtnData.getId(),rtnData.getBankTypeName(), rtnData.getBankCard(),1l,createTime,addRoleType,rtnData.getName(),rtnData.getBankName(),rtnData.getBankNo());
                accountsMapper.insertSelective(add);
                if(add.getId() == null){
                    add.setId(0l);
                }
                saveFun.apply(add);
			}else {
				throw new ServiceException("支付宝开虚拟户失败："+addAccount.getResult());
			}
		}
    }

    @Transactional
	public void addJiaoTongAccount(Long sydId,Long unitId, String gsmc,int roleType,int addRoleType, Function<BusAccounts,Boolean> saveFun, Function<String,String> existsFun) {
		//开交通银行虚拟户
		Map<String, String> configMap = bankAccountService.existsBank(sydId, "交通银行");
		if (configMap != null) {
			Account bankAcc = new Account();
			bankAcc.setBankType("交通银行");
			bankAcc.setBankCard(configMap.get("jiaotong_cloud_acc1"));
			bankAcc.setBankArgNo(configMap.get("jiaotong_cloud_acc1_busi_no"));
			bankAcc.setUnitId(sydId);
			bankAcc.setName(configMap.get("jiaotong_super_acc_name"));
			bankAcc.setType((short)1);//1:云账户
			Result<Account> addAccount = accountService.addAccount(bankAcc);
			if (addAccount.hasError() || addAccount.hasTip() || addAccount.getRtnData() == null) {
				throw new RuntimeException("交通银行开虚拟户失败："+addAccount.getResult());
			}else {
                Date createTime = new Date();
                Account rtnData = addAccount.getRtnData();
                String existsCard = existsFun.apply(rtnData.getBankTypeName());
                if (StringUtils.isBlank(existsCard)) {
                    bankAccountService.useAccount(new AccAccounts(rtnData.getBankTypeName(), rtnData.getBankCard(), (short) roleType, unitId, gsmc, rtnData.getBankArgNo()));
                    BusAccounts add = new BusAccounts(sydId,unitId,(long)rtnData.getId(),rtnData.getBankTypeName(), rtnData.getBankCard(),1l,createTime,addRoleType,rtnData.getName(),rtnData.getBankName(),rtnData.getBankNo());
                    accountsMapper.insertSelective(add);
                    if(add.getId() == null){
                        add.setId(0l);
                    }
                    if (!saveFun.apply(add)) {
                        throw new RuntimeException("不允许更换结算云账户");
                    }
                } else {
                    if (!existsCard.equals(rtnData.getBankCard())) {
                        throw new RuntimeException("不允许更换结算云账户");
                    }
                }
			}
		}
	}

	@Transactional
	public void addMinShengAccount(Long sydId,Long unitId, String gsmc,int roleType,int addRoleType, Function<BusAccounts,Boolean> saveFun) {
		String bankType = "民生银行";
		Map<String, String> configMap = bankAccountService.existsBank(sydId, bankType);
		if (configMap != null) {
			//开招商银行虚拟户
			SysSyd syd = sydDao.selectSysSydById(sydId);
			String bindAcctNo = syd.getBankCard();
			String bindAcctName = configMap.get("minsheng_bank_acctName");
			Result<Account> addAccount = accountService.addAccount(sydId, roleType, unitId, gsmc, bankType, bindAcctNo, bindAcctName,null);
			if (addAccount != null && addAccount.getRtnCode() == ResultCodeEnum.SUCCESS.Code()) {
                Date createTime = new Date();
                Account rtnData = addAccount.getRtnData();
                BusAccounts add = new BusAccounts(sydId,unitId,(long)rtnData.getId(),rtnData.getBankTypeName(), rtnData.getBankCard(),1l,createTime,addRoleType,rtnData.getName(),rtnData.getBankName(),rtnData.getBankNo());
                accountsMapper.insertSelective(add);
                if(add.getId() == null){
                    add.setId(0l);
                }
                saveFun.apply(add);
			} else {
				throw new ServiceException(bankType + "开虚拟户失败：" + addAccount.getResult());
			}
		}
	}

	@Transactional
	public void saveWorkerSignInfo(SysSydSignContent sign) {
		SysSyd syd = new SysSyd();
		syd.setId(sign.getId().longValue());
		syd.setSignMode(sign.getSignMode());
		syd.setSignValidTime(sign.getSignValidTime());
		sydDao.updateSysSyd(syd);
		SysSydSignContent old = signDao.selectByPrimaryKey(sign.getId());
		if (old != null) {
			signDao.updateByPrimaryKeySelective(sign);
		} else {
			signDao.insertSelective(sign);
		}
	}
}
