package com.yn.bftl.thirdparty.modules.chinaums.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.yn.bftl.common.common.exception.YnceError;
import com.yn.bftl.common.common.util.ByxRouteUtil;
import com.yn.bftl.common.common.util.RouteUtil;
import com.yn.bftl.common.modules.base.entity.BankLineNumber;
import com.yn.bftl.common.modules.company.entity.ChinaumsAuthInfo;
import com.yn.bftl.common.modules.company.entity.ChinaumsBankCard;
import com.yn.bftl.common.modules.company.entity.Company;
import com.yn.bftl.common.modules.company.enums.ChinaumsBankCardStatus;
import com.yn.bftl.thirdparty.common.constants.Constant;
import com.yn.bftl.thirdparty.common.service.ByxTradeWayService;
import com.yn.bftl.thirdparty.common.vo.BaseResponseVO;
import com.yn.bftl.thirdparty.common.exception.YnceErrorException;
import com.yn.bftl.thirdparty.common.service.BaseMemberService;
import com.yn.bftl.thirdparty.common.util.SequenceUtil;
import com.yn.bftl.thirdparty.modules.chinaums.dto.BankCardAmountValidateDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.byx.ByxChinaumsAcctBindBankCardDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.byx.ByxChinaumsQueryBindBankCardDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.chinaums.ChinaumsAddBankCardDTO;
import com.yn.bftl.thirdparty.modules.chinaums.dto.chinaums.ChinaumsAmountValidate;
import com.yn.bftl.thirdparty.modules.chinaums.enums.OprtTypeEnum;
import com.yn.bftl.thirdparty.modules.chinaums.repository.BankLineNumberRepository;
import com.yn.bftl.thirdparty.modules.chinaums.repository.ChinaumsAuthInfoRepository;
import com.yn.bftl.thirdparty.modules.chinaums.repository.ChinaumsBankCardRepository;
import com.yn.bftl.thirdparty.modules.chinaums.service.BankCardService;
import com.yn.bftl.thirdparty.modules.chinaums.util.ByxChinaumsUtil;
import com.yn.bftl.thirdparty.modules.chinaums.util.ChinaumsUtil;
import com.yn.bftl.thirdparty.modules.chinaums.vo.ChinaumsBankCardDetailVO;
import com.yn.bftl.thirdparty.modules.chinaums.vo.ChinaumsBankCardVO;
import com.yn.bftl.thirdparty.modules.chinaums.vo.chinaums.ChinaumsAddBankCardVO;
import com.yn.bftl.thirdparty.modules.chinaums.vo.byx.ByxChinaumsQueryBindBankCardVO;
import com.yn.bftl.thirdparty.modules.chinaums.vo.byx.ByxQueryBindBankRow;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 银行卡服务实现类
 *
 * @author huabiao
 * @create 2023/2/15  14:59
 **/
@Service
public class BankCardServiceImpl extends BaseMemberService implements BankCardService {

    private static final Logger log = LoggerFactory.getLogger(BankCardServiceImpl.class);
    @Resource
    private ChinaumsBankCardRepository chinaumsBankCardRepository;
    @Resource
    private ChinaumsAuthInfoRepository chinaumsAuthInfoRepository;
    @Resource
    private ChinaumsUtil chinaumsUtil;
    @Resource
    private ByxChinaumsUtil byxChinaumsUtil;
    @Resource
    private SequenceUtil sequenceUtil;
    @Resource
    private BankLineNumberRepository bankLineNumberRepository;

    @Resource
    private ByxTradeWayService byxTradeWayService;

    @Override
    public List<ChinaumsBankCardVO> bankCardList(ChinaumsBankCardStatus status) {
        List<ChinaumsBankCardVO> chinaumsBankCardVOList = new ArrayList<>();
        Company company = getUser().getCompany();
        if (company != null && company.getChinaumsAuthInfo() != null) {
            ChinaumsAuthInfo chinaumsAuthInfo = company.getChinaumsAuthInfo();
            if (CollectionUtils.isNotEmpty(chinaumsAuthInfo.getChinaumsBankCard())) {
//                List<Long> chinaumsBankCardIdList = chinaumsAuthInfo.getChinaumsBankCard().stream().filter(chinaumsBankCard -> chinaumsBankCard.getStatus().equals(ChinaumsBankCardStatus.PROCESSING)).map(ChinaumsBankCard::getId).collect(Collectors.toList());
//                if (CollectionUtils.isNotEmpty(chinaumsBankCardIdList)) {
//                    for (Long chinaumsBankCardId : chinaumsBankCardIdList) {
//                        handleBankCardStatus(chinaumsBankCardRepository.findById(chinaumsBankCardId).orElse(null));
//                    }
//                }
                // 获取银联的已绑定银行卡列表
                List<String> bankAcctNoList = queryBindBankCard(chinaumsAuthInfo.getBalanceAcctId());
                for (ChinaumsBankCard chinaumsBankCard : chinaumsAuthInfo.getChinaumsBankCard()) {
                    // 不在银联接口返回的银行卡不显示
                    if ((status == null || chinaumsBankCard.getStatus().equals(status) && bankAcctNoList.contains(chinaumsBankCard.getBankAcctNo()))) {
                        ChinaumsBankCardVO chinaumsBankCardVO = new ChinaumsBankCardVO();
                        chinaumsBankCardVO.setId(chinaumsBankCard.getId());
                        chinaumsBankCardVO.setBankName(chinaumsBankCard.getBankName());
                        chinaumsBankCardVO.setBankAcctNo(chinaumsBankCard.getBankAcctNo());
                        chinaumsBankCardVO.setStatus(chinaumsBankCard.getStatus());
                        chinaumsBankCardVO.setFailureMsg(chinaumsBankCard.getAcctValidationFailureMsg());
                        chinaumsBankCardVOList.add(chinaumsBankCardVO);
                    }
                }
            }
        }
        return chinaumsBankCardVOList;
    }

    /**
     * 查询账户银行卡列表
     * @param balanceAcctId
     * @return
     */
    private List<String> queryBindBankCard(String balanceAcctId) {
        List<String> bankAcctNoList = new ArrayList<>();
        if (ObjectUtil.isEmpty(balanceAcctId)) {
            return bankAcctNoList;
        }
        ByxChinaumsQueryBindBankCardDTO byxChinaumsQueryBindBankCardDTO = new ByxChinaumsQueryBindBankCardDTO();
        byxChinaumsQueryBindBankCardDTO.setWalletId(balanceAcctId);

        ByxChinaumsQueryBindBankCardVO chinaumsQueryBindBankCardVO = byxChinaumsUtil.execute(ByxRouteUtil.ROUTE_WALLET_UPAPI_SETTLE_ACCTS_BY_ACCT_NO, (JSONObject) JSONObject.toJSON(byxChinaumsQueryBindBankCardDTO), ByxChinaumsQueryBindBankCardVO.class);

        if(ObjectUtil.isNotNull(chinaumsQueryBindBankCardVO)&&ObjectUtil.isNotEmpty(chinaumsQueryBindBankCardVO.getRowList())){
            for (ByxQueryBindBankRow byxQueryBindBankRow :chinaumsQueryBindBankCardVO.getRowList()){
                bankAcctNoList.add(byxQueryBindBankRow.getBankAcctNo());
            }
        }
        return bankAcctNoList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBankCard(@Valid ChinaumsAddBankCardDTO chinaumsAddBankCardDTO) {
        Company company = getUser().getCompany();
        if (company == null) {
            throw new YnceErrorException(YnceError.YNCE_201009);
        }
        ChinaumsAuthInfo chinaumsAuthInfo = chinaumsAuthInfoRepository.findFirstByCompanyId(company.getId());
        if (chinaumsAuthInfo == null) {
            throw new YnceErrorException(YnceError.YNCE_218009);
        }
        if (CollectionUtils.isNotEmpty(chinaumsAuthInfo.getChinaumsBankCard()) && chinaumsAuthInfo.getChinaumsBankCard().size() >= 10) {
            throw new YnceErrorException(YnceError.YNCE_218027);
        }
        if (ObjectUtil.isEmpty(chinaumsAuthInfo.getSettleAcctBankName())) {
            throw new YnceErrorException(YnceError.YNCE_201044);
        }

        ByxChinaumsAcctBindBankCardDTO byxChinaumsAcctBindBankCardDTO = new ByxChinaumsAcctBindBankCardDTO();
        BeanUtil.copyProperties(chinaumsAddBankCardDTO, byxChinaumsAcctBindBankCardDTO);
        byxChinaumsAcctBindBankCardDTO.setMobileNo(chinaumsAddBankCardDTO.getMobileNumber());
//        byxChinaumsAcctBindBankCardDTO.setBankNo(chinaumsAddBankCardDTO.getBankBranchCode());
        byxChinaumsAcctBindBankCardDTO.setSmsAuthCode(chinaumsAddBankCardDTO.getSmsCode());
        byxChinaumsAcctBindBankCardDTO.setOprtType(OprtTypeEnum.BINDING.getValue());
        if("2".equals(chinaumsAddBankCardDTO.getBankAcctType()) ){
            byxChinaumsAcctBindBankCardDTO.setBankAcctType("0");
        }
        // 根据bankCode 查询对应的银行信息
        BankLineNumber bankLineNumber = bankLineNumberRepository.findFirstByBankCode(chinaumsAddBankCardDTO.getBankCode());
        // 赋值银行卡
        ChinaumsBankCard chinaumsBankCard = new ChinaumsBankCard();
        if (chinaumsAddBankCardDTO.getId() != null) {
            chinaumsBankCard = chinaumsBankCardRepository.findById(chinaumsAddBankCardDTO.getId()).orElse(null);
            if (chinaumsBankCard == null) {
                throw new YnceErrorException(YnceError.YNCE_218023);
            }
//            byxChinaumsAcctBindBankCardDTO.setOutRequestNo(chinaumsBankCard.getOutRequestNo());
        } else {
            // 判断该银行卡号是否存在当前用户列表中
            if(CollectionUtils.isNotEmpty(chinaumsAuthInfo.getChinaumsBankCard()) && chinaumsAuthInfo.getChinaumsBankCard().stream().anyMatch(filterChinaumsBankCard -> filterChinaumsBankCard.getBankAcctNo().equals(chinaumsAddBankCardDTO.getBankAcctNo()))){
                throw new YnceErrorException(YnceError.YNCE_218029);
            }
            chinaumsBankCard.setChinaumsAuthInfo(chinaumsAuthInfo);
            chinaumsBankCard.setBankBranchCode(chinaumsAuthInfo.getSettleAcctBankBranchCode());
//            chinaumsBankCard.setBankAcctNo(chinaumsAuthInfo.getSettleAcctBankAcctNo());
            chinaumsBankCard.setMobileNumber(chinaumsAuthInfo.getMobileNumber());
//            chinaumsBankCard.setOutRequestNo(chinaumsAuthInfo.getOutRequestNo());
            chinaumsBankCard.setBankAcctType(chinaumsAuthInfo.getSettleAcctType());
            chinaumsBankCard.setSettleAcctId(chinaumsAuthInfo.getSettleAcctId());


            if(ObjectUtil.isNotEmpty(bankLineNumber)){
                chinaumsBankCard.setBankName(bankLineNumber.getBankName());
                chinaumsBankCard.setBankCode(bankLineNumber.getBankCode());
//                chinaumsBankCard.setBankBranchCode(bankLineNumber.getDrecCode());
            }
        }
        BeanUtils.copyProperties(byxChinaumsAcctBindBankCardDTO, chinaumsBankCard);
//        byxChinaumsAcctBindBankCardDTO.setCusId(chinaumsAuthInfo.getCusId());
//        byxChinaumsAcctBindBankCardDTO.setMchId(chinaumsAuthInfo.getMchId());
        byxChinaumsAcctBindBankCardDTO.setElecBankNo(chinaumsAuthInfo.getElecBankNo());
        byxChinaumsAcctBindBankCardDTO.setIdCard(chinaumsAuthInfo.getIdCardNumber());
        byxChinaumsAcctBindBankCardDTO.setWalletId(company.getWalletId());
        // 对公账户 取开户名
        byxChinaumsAcctBindBankCardDTO.setBankAcctName(chinaumsAuthInfo.getSettleAcctName());
        byxChinaumsAcctBindBankCardDTO.setBankNo(bankLineNumber.getThreeDigitBranchCode());

        try {
            if(ObjectUtil.isEmpty(byxChinaumsAcctBindBankCardDTO.getBankAcctNo())){
                // 银行账户
                byxChinaumsAcctBindBankCardDTO.setBankAcctNo(chinaumsBankCard.getBankAcctNo());
            }

            if(ObjectUtil.isEmpty(byxChinaumsAcctBindBankCardDTO.getMobileNo())){
                // 手机号
                byxChinaumsAcctBindBankCardDTO.setMobileNo(chinaumsBankCard.getMobileNumber());
            }
        } catch (Exception exception) {
            throw new YnceErrorException(YnceError.YNCE_218014);
        }
        byxTradeWayService.setCert(byxChinaumsAcctBindBankCardDTO, company.getWalletId());
//        log.info("{}",(JSONObject) JSONObject.toJSON(byxChinaumsAcctBindBankCardDTO));
        BaseResponseVO baseResponseVO = byxChinaumsUtil.execute(ByxRouteUtil.ROUTE_WALLET_UPAPI_ACCT_BIND_BANK_CARD, (JSONObject) JSONObject.toJSON(byxChinaumsAcctBindBankCardDTO), BaseResponseVO.class);
        // 绑定后根据返回的状态码更新状态
        if(Constant.RETURN_SUCCESS_CODE.equals(baseResponseVO.getRspCode())){
            chinaumsBankCard.setStatus(ChinaumsBankCardStatus.SUCCEEDED);
            chinaumsAuthInfo.setBankCardNo(byxChinaumsAcctBindBankCardDTO.getBankAcctNo());
            chinaumsAuthInfo.setBindAcctName(byxChinaumsAcctBindBankCardDTO.getBankAcctName());
            chinaumsAuthInfoRepository.save(chinaumsAuthInfo);

            chinaumsBankCard.setBankAcctNo(byxChinaumsAcctBindBankCardDTO.getBankAcctNo());
        }
        else {
            chinaumsBankCard.setStatus(ChinaumsBankCardStatus.FAILED);
            chinaumsBankCard.setAcctValidationFailureMsg(baseResponseVO.getRspResult());
        }
        chinaumsBankCardRepository.save(chinaumsBankCard);
//        chinaumsBankCard.setOutRequestNo(chinaumsAddBankCardVO.getOutRequestNo());
//        chinaumsBankCard.setSettleAcctId(chinaumsAddBankCardVO.getSettleAcctId());
//        handleBankCardStatus(chinaumsBankCard);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteBankCard(@NotNull Long id) {
        ChinaumsBankCard chinaumsBankCard = chinaumsBankCardRepository.findById(id).orElse(null);
        if (chinaumsBankCard == null) {
            throw new YnceErrorException(YnceError.YNCE_218023);
        }
        List<ChinaumsBankCardVO> chinaumsBankCardVOList = this.bankCardList(null);
        if (CollectionUtils.isNotEmpty(chinaumsBankCardVOList) && chinaumsBankCardVOList.stream().filter(chinaumsBankCardVO -> chinaumsBankCardVO.getStatus().equals(ChinaumsBankCardStatus.SUCCEEDED)).count() == 1) {
            throw new YnceErrorException(YnceError.YNCE_218024);
        }
        if (!chinaumsBankCard.getStatus().equals(ChinaumsBankCardStatus.SUCCEEDED)) {
            throw new YnceErrorException(YnceError.YNCE_218025);
        }
        if(chinaumsBankCard.getBankAcctNo().equals(chinaumsBankCard.getChinaumsAuthInfo().getSettleAcctBankAcctNo())){
            throw new YnceErrorException(YnceError.YNCE_218025.getStatus(),YnceError.YNCE_218025.getMsg() + "认证绑定的卡不允许解绑");
        }
//        ChinaumsDeleteBankCardDTO chinaumsDeleteBankCardDTO = ChinaumsDeleteBankCardDTO.builder().settleAcctId(chinaumsBankCard.getSettleAcctId()).build();
        ByxChinaumsAcctBindBankCardDTO byxChinaumsAcctBindBankCardDTO = new ByxChinaumsAcctBindBankCardDTO();
        byxChinaumsAcctBindBankCardDTO.setWalletId(chinaumsBankCard.getChinaumsAuthInfo().getBalanceAcctId());
        byxChinaumsAcctBindBankCardDTO.setOprtType(OprtTypeEnum.UNBIND.getValue());
        byxChinaumsAcctBindBankCardDTO.setBankAcctNo(chinaumsBankCard.getChinaumsAuthInfo().getBankCardNo());

        byxTradeWayService.setCert(byxChinaumsAcctBindBankCardDTO, byxChinaumsAcctBindBankCardDTO.getWalletId());
        byxTradeWayService.setTradeWayInCert(byxChinaumsAcctBindBankCardDTO, byxChinaumsAcctBindBankCardDTO.getWalletId());
        BaseResponseVO baseResponseVO = byxChinaumsUtil.execute(ByxRouteUtil.ROUTE_WALLET_UPAPI_ACCT_BIND_BANK_CARD, (JSONObject) JSONObject.toJSON(byxChinaumsAcctBindBankCardDTO), BaseResponseVO.class);
        if (Constant.RETURN_SUCCESS_CODE.equals(baseResponseVO.getRspCode()) ) {
            List<ChinaumsBankCard> chinaumsBankCardList = chinaumsBankCard.getChinaumsAuthInfo().getChinaumsBankCard();
            chinaumsBankCardList.removeIf(deleteChinaumsBankCard -> deleteChinaumsBankCard.getId().equals(id));
            chinaumsBankCard.setChinaumsAuthInfo(null);
            chinaumsBankCardRepository.delete(chinaumsBankCard);
            return true;
        } else {
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean amountValidate(BankCardAmountValidateDTO bankCardAmountValidateDTO) {
        ChinaumsBankCard chinaumsBankCard = chinaumsBankCardRepository.findById(bankCardAmountValidateDTO.getId()).orElse(null);
        if (chinaumsBankCard == null) {
            throw new YnceErrorException(YnceError.YNCE_218023);
        }
        if (chinaumsBankCard.getBankAcctType().equals("1")) {
            throw new YnceErrorException(YnceError.YNCE_218026);
        }
        ChinaumsAmountValidate chinaumsAmountValidate = ChinaumsAmountValidate
                .builder()
                .settleAcctId(chinaumsBankCard.getSettleAcctId())
                .payAmount(bankCardAmountValidateDTO.getAmount().multiply(new BigDecimal(100)).intValue())
                .build();
        chinaumsUtil.execute(RouteUtil.ROUTE_WALLET_ACCTS_VALIDATE, (JSONObject) JSONObject.toJSON(chinaumsAmountValidate), null);
        return true;
    }

    @Override
    public ChinaumsBankCardDetailVO getBankCardDetail(Long id) {
        ChinaumsBankCard chinaumsBankCard = chinaumsBankCardRepository.findById(id).orElse(null);
        if (chinaumsBankCard == null) {
            throw new YnceErrorException(YnceError.YNCE_218023);
        }
        ChinaumsBankCardDetailVO chinaumsBankCardDetailVO = new ChinaumsBankCardDetailVO();
        BeanUtils.copyProperties(chinaumsBankCard, chinaumsBankCardDetailVO);
        return chinaumsBankCardDetailVO;
    }

    /**
     * 处理银联银行卡状态
     *
     * @param chinaumsBankCard 银联银行卡
     * @author huabiao
     * @create 2023/2/20  16:12
     */
    private void handleBankCardStatus(ChinaumsBankCard chinaumsBankCard) {
        if (chinaumsBankCard == null) {
            return;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("settleAcctId", chinaumsBankCard.getSettleAcctId());
        ChinaumsAddBankCardVO chinaumsAddBankCardVO = chinaumsUtil.execute(RouteUtil.ROUTE_WALLET_UPAPI_SETTLE_ACCTS_BY_ACCT_NO, (JSONObject) JSONObject.toJSON(jsonObject), ChinaumsAddBankCardVO.class);
        // 查询完状态后需要将银联银行卡信息中的状态更新
        switch (chinaumsAddBankCardVO.getVerifyStatus()) {
            case "processing":
                chinaumsBankCard.setStatus(ChinaumsBankCardStatus.PROCESSING);
                break;
            case "needless":
                chinaumsBankCard.setStatus(ChinaumsBankCardStatus.NEEDLESS);
                break;
            case "blocked":
                chinaumsBankCard.setStatus(ChinaumsBankCardStatus.BLOCKED);
                break;
            case "succeeded":
                chinaumsBankCard.setStatus(ChinaumsBankCardStatus.SUCCEEDED);
                break;
            case "failed":
                chinaumsBankCard.setAcctValidationFailureMsg(chinaumsAddBankCardVO.getAcctValidationFailureMsg());
                chinaumsBankCard.setStatus(ChinaumsBankCardStatus.FAILED);
                break;
        }
        chinaumsBankCardRepository.save(chinaumsBankCard);
    }
}
