package cn.pluss.platform.jft.impl;

import cn.hutool.core.util.DesensitizedUtil;
import cn.jiguang.common.utils.StringUtils;
import cn.pluss.platform.BankCardService;
import cn.pluss.platform.IdCardService;
import cn.pluss.platform.common.AliyunService;
import cn.pluss.platform.converter.Converter;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.jft.JftAuditService;
import cn.pluss.platform.jft.JftBankCardService;
import cn.pluss.platform.jft.JftMercBaseInfoService;
import cn.pluss.platform.jft.JftMerchantRateService;
import cn.pluss.platform.mapper.JftBankCardMapper;
import cn.pluss.platform.merchant.JftMercPaymentChannelService;
import cn.pluss.platform.notice.NoticeService;
import cn.pluss.platform.user.impl.GeneralPushUtil;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.userInfo.UserInfoService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * @author DJH
 */
@Slf4j
@Service
public class JftBankCardServiceImpl extends ServiceImpl<JftBankCardMapper, JftBankCard> implements JftBankCardService {

    @Autowired
    private BankCardService bankCardService;

    @Autowired
    private JftMercPaymentChannelService jftMercPaymentChannelService;

    @Autowired
    private UserAppService uaService;

    @Autowired
    private JftAuditService jftAuditService;

    @Autowired
    private JftMercBaseInfoService jmbiSerivce;

    @Autowired
    private JftMerchantRateService jftMerchantRateService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private GeneralPushUtil generalPushUtil;

    @Autowired
    private NoticeService noticeService;

    @Autowired
    private IdCardService idCardService;

    @Autowired
    private AliyunService aliyunService;

    @Autowired
    private UserInfoService uiService;

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public Map<String, Object> apiGetAccount() {
        final UserApp uaToken = uaService.queryUserAppByToken();

        final IdCard idCard = idCardService.getCertIdCard(uaToken.getUserId());

        final JftBankCard bankCard = getByUserId(uaToken.getUserId());

        final Map<String, Object> result = new HashMap<>();
        result.put("idCard", idCard);
        result.put("bankCard", bankCard);

        return result;
    }

    @Override
    public JftBankCard getByUserId(Long userId) {
        LambdaQueryWrapper<JftBankCard> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(JftBankCard::getUserId, userId);

        JftBankCard result = getBaseMapper().selectOne(qWrapper);

        // 没有存，默认取商户实名认证的银行卡信息
        if (result == null) {
            LambdaQueryWrapper<BankCard> qWrapper2 = Wrappers.lambdaQuery();
            qWrapper2.eq(BankCard::getUserId, userId);
            qWrapper2.eq(BankCard::getAccountType, BankCard.ACCOUNT_TYPE_CERT);
            final BankCard certBankCard = bankCardService.getOne(qWrapper2);

            if (certBankCard != null) {
                result = Converter.INSTANCE.toJftData(certBankCard);
                result.setStatus("1");
            }
        }

        return result;
    }

    @Override
    public void apiSaveBankCard(JftBankCard jftBankCard) {
        final UserApp tokenUa = uaService.queryUserAppByToken();

        final JftMercPaymentChannel jpc = jftMercPaymentChannelService.getByUserId(tokenUa.getUserId());

        if (jpc != null && !"1".equals(jpc.getStatus())) {
            throw new MsgException("当前状态不允许执行该操作");
        }

        jftBankCard.setUserId(tokenUa.getUserId());

        final IdCard certIdCard = idCardService.getCertIdCard(tokenUa.getUserId());

        aliyunService.checkBankCorrect(jftBankCard.getPhone(), jftBankCard.getBankCardNo(), certIdCard.getCertNo(), certIdCard.getCertName());

        jftBankCard.setBankHolder(certIdCard.getCertName());
        saveBankCard(jftBankCard);
    }

    @Override
    public void saveBankCard(JftBankCard jftBankCard) {
        LambdaQueryWrapper<JftBankCard> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(JftBankCard::getUserId, jftBankCard.getUserId());
        baseMapper.delete(qWrapper);
        baseMapper.insert(jftBankCard);
    }

    @Override
    public void apiChangeBankCard(JftBankCard jftBankCard) {
        final UserApp tokenUa = uaService.queryUserAppByToken();
        jftBankCard.setUserId(tokenUa.getUserId());

        final IdCard certIdCard = idCardService.getCertIdCard(tokenUa.getUserId());
        aliyunService.checkBankCorrect(jftBankCard.getPhone(), jftBankCard.getBankCardNo(), certIdCard.getCertNo(), certIdCard.getCertName());

        final JftMercPaymentChannel auditInfo = jftMercPaymentChannelService.getByUserId(tokenUa.getUserId());
        if (auditInfo != null && auditInfo.getStatus().equals(MerchantChannelStatus.AUDIT_STATUS_SUCCESS)) {
            LambdaQueryWrapper<JftBankCard> qWrapper = Wrappers.lambdaQuery();
            qWrapper.eq(JftBankCard::getUserId, jftBankCard.getUserId());
            JftBankCard exist = baseMapper.selectOne(qWrapper);


            if (Objects.equals(jftBankCard.getBankCardNo(), exist.getBankCardNo())) {
                throw new MsgException("结算卡未发生变更!");
            }

            exist.setBak((JSONObject) JSON.toJSON(jftBankCard));
            exist.setStatus("2");
            updateById(exist);

            jftAuditService.editBankCard(jftBankCard.getUserId());

            return;
        }

        saveBankCard(jftBankCard);
    }

    @Override
    public void changeRate(Long userId) {
        final JftMerchantRate auditRate = jftMerchantRateService.getAuditRate(userId);
        final JftMerchantRate current = jftMerchantRateService.getRateByUserId(userId);

        if (Objects.equals(auditRate.getAliRate(), current.getAliRate())) {
            log.info("费率无须修改");
            return;
        }

        jftAuditService.editBankCard(userId);
    }

    @Override
    public void editSuccess(JftMercPaymentChannel entity) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                final JftBankCard jftBankCard = getByUserId(entity.getUserId());

                JSONObject bak = jftBankCard.getBak();
                JftBankCard newBankCard = JSONObject.toJavaObject(bak, JftBankCard.class);
                newBankCard.setId(jftBankCard.getId());
                updateById(newBankCard);

                List<String> idList = new ArrayList<>();
                idList.add(entity.getUserId() + "");

                Notice notice = new Notice();
                notice.setUserId(entity.getUserId() + "");
                notice.setTitle("缴费通结算卡变更通知");
                notice.setNoticeCode(UUID.randomUUID().toString().replace("-", ""));
                notice.setConrtent("缴费通结算卡变更成功, 新的结算卡为" + DesensitizedUtil.bankCard(newBankCard.getBankCardNo()));
                noticeService.saveSystemNotice(notice);

                generalPushUtil.sendAllPlatByAlias(idList, "缴费通结算卡变更通知", "缴费通结算卡变更成功", "1");

            }
        });
    }

    @Override
    public void editFail(JftMercPaymentChannel entity, String failReason) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                final JftBankCard jftBankCard = getByUserId(entity.getUserId());
                jftBankCard.setBak(null);
                jftBankCard.setStatus("1");
                updateById(jftBankCard);

                Notice notice = new Notice();
                notice.setUserId(entity.getUserId() + "");
                notice.setTitle("缴费通结算卡变更通知");
                notice.setNoticeCode(UUID.randomUUID().toString().replace("-", ""));
                notice.setConrtent("缴费通结算卡变更失败: " + failReason);
                noticeService.saveSystemNotice(notice);

                generalPushUtil.sendAllPlatByAlias(Collections.singletonList(entity.getUserId() + ""), "缴费通结算卡变更通知", "缴费通结算卡变更失败", "1");

            }
        });
    }
}
