
package com.tmerclub.cloud.payment.service.impl;

import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.payment.allinpay.member.resp.BindCard;
import com.tmerclub.cloud.api.payment.allinpay.order.resp.PayByBackSmsResp;
import com.tmerclub.cloud.api.payment.allinpay.order.resp.QueryBalanceResp;
import com.tmerclub.cloud.api.platform.config.FeignShopConfig;
import com.tmerclub.cloud.common.bean.Allinpay;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.util.IpHelper;
import com.tmerclub.cloud.payment.allinpay.OpenClient;
import com.tmerclub.cloud.payment.allinpay.constant.AllinpayPlatformAccountSet;
import com.tmerclub.cloud.payment.allinpay.member.constant.*;
import com.tmerclub.cloud.payment.allinpay.member.req.*;
import com.tmerclub.cloud.payment.allinpay.member.resp.*;
import com.tmerclub.cloud.payment.allinpay.order.req.*;
import com.tmerclub.cloud.payment.allinpay.member.constant.*;
import com.tmerclub.cloud.payment.allinpay.member.req.*;
import com.tmerclub.cloud.payment.allinpay.member.resp.*;
import com.tmerclub.cloud.payment.allinpay.order.req.*;
import com.tmerclub.cloud.payment.allinpay.order.resp.GetOrderStatusResp;
import com.tmerclub.cloud.payment.allinpay.order.resp.InExpDetail;
import com.tmerclub.cloud.payment.allinpay.order.resp.QueryInExpDetailResp;
import com.tmerclub.cloud.payment.allinpay.order.resp.ResendPaySmsResp;
import com.tmerclub.cloud.payment.allinpay.service.AllinpayMemberService;
import com.tmerclub.cloud.payment.allinpay.service.AllinpayOrderService;
import com.tmerclub.cloud.payment.config.AllinpayConfig;
import com.tmerclub.cloud.payment.dto.*;
import com.tmerclub.cloud.payment.dto.*;
import com.tmerclub.cloud.payment.service.AllinpayService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Objects;

/**
 * @author lanhai
 */
@Service
public class AllinpayServiceImpl implements AllinpayService {

    @Autowired
    private AllinpayMemberService allinpayMemberService;
    @Autowired
    private AllinpayConfig allinpayConfig;
    @Autowired
    private AllinpayOrderService allinpayOrderService;

    @Autowired
    private FeignShopConfig feignShopConfig;

    @Override
    public void createMember(String bizUserId, Integer sysType) {
        CreateMember createMember = new CreateMember(bizUserId);
        createMember.setSource(VisitSourceType.PC.value());
        allinpayMemberService.createMember(createMember);
    }

    @Override
    public UserInfo getUserInfo(String bizUserId) {
        GetMemberInfo getMemberInfo = new GetMemberInfo(bizUserId);
        UserInfo userInfo = allinpayMemberService.getMemberInfo(getMemberInfo);
        // 个人会员(身份证号解密)
        OpenClient client = allinpayConfig.getClient();
        String encryptStr = userInfo.getIdentityCardNo();
        userInfo.setIdentityCardNo(encryptStr == null ? null : client.decrypt(encryptStr));
        return userInfo;
    }

    @Override
    public void sendVerificationCode(String userId, VerificationCodeDTO verificationCodeDTO) {
        if (StrUtil.isBlank(userId)) {
            return;
        }
        SendVerificationCode svc = new SendVerificationCode(userId, verificationCodeDTO.getPhone());
        Integer type = verificationCodeDTO.getVerificationCodeType();
        if (type != null
                && VerificationCodeType.instance(type) != null) {
            svc.setVerificationCodeType(type);
        }
        allinpayMemberService.sendVerificationCode(svc);
    }

    @Override
    public void bindPhone(String userId, VerificationCodeDTO verificationCodeDTO) {
        BindPhone bindPhone = new BindPhone(
                userId,
                verificationCodeDTO.getPhone(),
                verificationCodeDTO.getVerificationCode()
        );
        allinpayMemberService.bindPhone(bindPhone);
    }

    @Override
    public void unbindPhone(String userId, VerificationCodeDTO verificationCodeDTO) {
        UnbindPhone unbindPhone = new UnbindPhone(
                userId,
                verificationCodeDTO.getPhone(),
                verificationCodeDTO.getVerificationCode()
        );
        PhoneVerificationResp phoneVerificationResp = allinpayMemberService.unbindPhone(unbindPhone);
        if (Objects.equals(Constant.ERROR, phoneVerificationResp.getResult())) {
            throw new LuckException("解绑手机失败");
        }
    }

    @Override
    public String updatePhoneByPayPwd(String bizUserId, String backUrl, UpdatePhoneByPayPwdDTO updatePhoneByPayPwdDTO) {
        UpdatePhoneByPayPwd updatePhoneByPayPwd = new UpdatePhoneByPayPwd();
        BeanUtils.copyProperties(updatePhoneByPayPwdDTO, updatePhoneByPayPwd);
        updatePhoneByPayPwd.setBizUserId(bizUserId);
        updatePhoneByPayPwd.setBackUrl(backUrl);
        OpenClient client = allinpayConfig.getClient();
        updatePhoneByPayPwd.setIdentityNo(client.encrypt(updatePhoneByPayPwd.getIdentityNo()));
        if (updatePhoneByPayPwd.getJumpPageType() == null) {
            updatePhoneByPayPwd.setJumpPageType(PageType.H5.value());
        }
        return allinpayMemberService.updatePhoneByPayPwd(updatePhoneByPayPwd);
    }

    @Override
    public void setRealName(Long userId, SetRealNameDTO setRealNameDTO) {
        OpenClient client = allinpayConfig.getClient();
        SetRealName setRealName = new SetRealName(
                String.valueOf(userId),
                setRealNameDTO.getName(),
                client.encrypt(setRealNameDTO.getIdentityNo())
        );
        allinpayMemberService.setRealName(setRealName);
    }

    @Override
    public void lockMember(LockMemberDTO lockMemberDTO) {
        LockMember lockMember = new LockMember(String.valueOf(lockMemberDTO.getUserId()));
        allinpayMemberService.lockMember(lockMember);
    }

    @Override
    public void unlockMember(LockMemberDTO lockMemberDTO) {
        UnlockMember unlockMember = new UnlockMember(String.valueOf(lockMemberDTO.getUserId()));
        allinpayMemberService.unlockMember(unlockMember);
    }

    @Override
    public CardBinInfo getBankCardBin(String cardNo) {
        GetBankCardBin getBankCardBin = new GetBankCardBin();
        OpenClient client = allinpayConfig.getClient();
        getBankCardBin.setCardNo(client.encrypt(cardNo));
        return allinpayMemberService.getBankCardBin(getBankCardBin);
    }

    @Override
    public ApplyBindBankCardResp applyBindBankCard(String userId, ApplyBankCardDTO applyBankCardDTO) {
        OpenClient client = allinpayConfig.getClient();
        ApplyBindBankCard applyBindBankCard = new ApplyBindBankCard();
        BeanUtils.copyProperties(applyBankCardDTO, applyBindBankCard);
        applyBindBankCard.setIdentityType(IdentityType.ID_CARD.value());
        applyBindBankCard.setBizUserId(userId);
        applyBindBankCard.setIdentityNo(client.encrypt(applyBankCardDTO.getIdentityNo()));
        applyBindBankCard.setCardNo(client.encrypt(applyBankCardDTO.getCardNo()));
        return allinpayMemberService.applyBindBankCard(applyBindBankCard);
    }

    @Override
    public void bindBankCard(String userId, BindBankCardDTO bindBankCardDTO) {
        BindBankCard bindBankCard = new BindBankCard();
        BeanUtils.copyProperties(bindBankCardDTO, bindBankCard);
        bindBankCard.setBizUserId(userId);
        allinpayMemberService.bindBankCard(bindBankCard);
    }

    @Override
    public void unbindBankCard(String userId, UnbindBankCardDTO unbindBankCardDTO) {
        OpenClient client = allinpayConfig.getClient();
        UnbindBankCard unbindBankCard = new UnbindBankCard();
        unbindBankCard.setBizUserId(userId);
        unbindBankCard.setCardNo(client.encrypt(unbindBankCardDTO.getCardNo()));
        allinpayMemberService.unbindBankCard(unbindBankCard);
    }

    @Override
    public List<BindCard> queryBankCard(String userId, String cardNo) {
        QueryBankCard queryBankCard = new QueryBankCard(userId);
        if (!ObjectUtils.isEmpty(cardNo)) {
            OpenClient client = allinpayConfig.getClient();
            queryBankCard.setCardNo(client.encrypt(cardNo));
        }
        return allinpayMemberService.queryBankCard(queryBankCard);
    }

    @Override
    public void applyBindAcct(String bizUserId, ApplyBindAcctDTO applyBindAcctDTO) {
        ApplyBindAcct applyBindAcct = new ApplyBindAcct();
        if (PayAcctType.instance(applyBindAcctDTO.getAcctType()) == null) {
            throw new LuckException("accType参数错误");
        }
        applyBindAcct.setBizUserId(bizUserId);
        applyBindAcct.setAcctType(applyBindAcctDTO.getAcctType());
        applyBindAcct.setAcct(applyBindAcctDTO.getAcct());
        Result result = allinpayMemberService.applyBindAcct(applyBindAcct);
        if (Objects.equals(result.getResult(), Constant.ERROR)) {
            throw new LuckException("绑定失败");
        }
    }

    @Override
    public QueryBindAcctResp queryBindAcct(String bizUserId) {
        ApplyBindAcct applyBindAcct = new ApplyBindAcct();
        applyBindAcct.setBizUserId(bizUserId);
        applyBindAcct.setOperationType("query");
        return allinpayMemberService.queryBindAcct(applyBindAcct);
    }

    @Override
    public String setPayPwd(Long userId, String backUrl, SetPayPwdDTO setPayPwdDTO) {
        OpenClient client = allinpayConfig.getClient();
        SetPayPwd setPayPwd = new SetPayPwd();
        BeanUtils.copyProperties(setPayPwdDTO, setPayPwd);
        setPayPwd.setBizUserId(String.valueOf(userId));
        setPayPwd.setIdentityType(IdentityType.ID_CARD.value());
        setPayPwd.setIdentityNo(client.encrypt(setPayPwdDTO.getIdentityNo()));
        setPayPwd.setBackUrl(backUrl);
        return allinpayMemberService.setPayPwd(setPayPwd);
    }

    @Override
    public String updatePayPwd(Long userId, String backUrl, SetPayPwdDTO setPayPwdDTO) {
        OpenClient client = allinpayConfig.getClient();
        UpdatePayPwd updatePayPwd = new UpdatePayPwd();
        BeanUtils.copyProperties(setPayPwdDTO, updatePayPwd);
        updatePayPwd.setBizUserId(String.valueOf(userId));
        updatePayPwd.setIdentityType(IdentityType.ID_CARD.value());
        updatePayPwd.setIdentityNo(client.encrypt(setPayPwdDTO.getIdentityNo()));
        updatePayPwd.setBackUrl(backUrl);
        return allinpayMemberService.updatePayPwd(updatePayPwd);
    }

    @Override
    public String resetPayPwd(Long userId, String backUrl, SetPayPwdDTO setPayPwdDTO) {
        OpenClient client = allinpayConfig.getClient();
        ResetPayPwd resetPayPwd = new ResetPayPwd();
        BeanUtils.copyProperties(setPayPwdDTO, resetPayPwd);
        resetPayPwd.setBizUserId(String.valueOf(userId));
        resetPayPwd.setIdentityType(IdentityType.ID_CARD.value());
        resetPayPwd.setIdentityNo(client.encrypt(setPayPwdDTO.getIdentityNo()));
        resetPayPwd.setBackUrl(backUrl);
        return allinpayMemberService.resetPayPwd(resetPayPwd);
    }

    @Override
    public String signAcctProtocol(String bizUserId, String backUrl, SignAcctProtocolDTO signAcctProtocolDTO) {
        SignAcctProtocol signAcctProtocol = new SignAcctProtocol();
        BeanUtils.copyProperties(signAcctProtocolDTO, signAcctProtocol);
        signAcctProtocol.setBizUserId(bizUserId);
        signAcctProtocol.setBackUrl(backUrl);
        signAcctProtocol.setSource(VisitSourceType.PC.value());
        return allinpayMemberService.signAcctProtocol(signAcctProtocol);
    }

    @Override
    public String signContractQuery(String bizUserId, SignAcctProtocolDTO signAcctProtocolDTO) {
        SignContractQuery signContractQuery = new SignContractQuery();
        BeanUtils.copyProperties(signAcctProtocolDTO, signContractQuery);
        signContractQuery.setBizUserId(bizUserId);
        signContractQuery.setSource(VisitSourceType.PC.value());
        return allinpayMemberService.signContractQuery(signContractQuery);
    }

    @Override
    public BankCardChangeBindPhoneResp bankCardChangeBindPhone(String bizUserId, BankCardChangeBindPhoneDTO bankCardChangeBindPhoneDTO) {
        BankCardChangeBindPhone bankCardChangeBindPhone = new BankCardChangeBindPhone();
        BeanUtils.copyProperties(bankCardChangeBindPhoneDTO, bankCardChangeBindPhone);
        bankCardChangeBindPhone.setBizUserId(bizUserId);
        bankCardChangeBindPhone.setIdentityType(IdentityType.ID_CARD.value());
        // 数据加密
        OpenClient client = allinpayConfig.getClient();
        bankCardChangeBindPhone.setCardNo(client.encrypt(bankCardChangeBindPhoneDTO.getCardNo()));
        bankCardChangeBindPhone.setIdentityNo(client.encrypt(bankCardChangeBindPhoneDTO.getIdentityNo()));
        if (!ObjectUtils.isEmpty(bankCardChangeBindPhoneDTO.getValidate())) {
            bankCardChangeBindPhone.setValidate(client.encrypt(bankCardChangeBindPhoneDTO.getValidate()));
        }
        if (!ObjectUtils.isEmpty(bankCardChangeBindPhoneDTO.getCvv2())) {
            bankCardChangeBindPhone.setCvv2(client.encrypt(bankCardChangeBindPhoneDTO.getCvv2()));
        }
        return allinpayMemberService.bankCardChangeBindPhone(bankCardChangeBindPhone);
    }

    @Override
    public void verifyBankCardChangeBindPhone(String bizUserId, VerifyBankCardChangeBindPhoneDTO verifyBankCardChangeBindPhoneDTO) {
        VerifyBankCardChangeBindPhone verifyBankCardChangeBindPhone = new VerifyBankCardChangeBindPhone();
        BeanUtils.copyProperties(verifyBankCardChangeBindPhoneDTO, verifyBankCardChangeBindPhone);
        verifyBankCardChangeBindPhone.setBizUserId(bizUserId);
        // 数据加密
        OpenClient client = allinpayConfig.getClient();
        if (!ObjectUtils.isEmpty(verifyBankCardChangeBindPhoneDTO.getValidate())) {
            verifyBankCardChangeBindPhone.setValidate(client.encrypt(verifyBankCardChangeBindPhoneDTO.getValidate()));
        }
        if (!ObjectUtils.isEmpty(verifyBankCardChangeBindPhoneDTO.getCvv2())) {
            verifyBankCardChangeBindPhone.setCvv2(client.encrypt(verifyBankCardChangeBindPhone.getCvv2()));
        }
        allinpayMemberService.verifyBankCardChangeBindPhone(verifyBankCardChangeBindPhone);
    }

    @Override
    public QueryBalanceResp queryBalance(String bizUserId, Integer sysType) {
        // 平台使用标准账户集，其余使用托管账户集
        String accountSetNo;
        if (Objects.equals(SysTypeEnum.PLATFORM.value(), sysType)) {
            accountSetNo = AllinpayPlatformAccountSet.STANDARD_BALANCE.toString();
        } else {
            Allinpay allinpay = feignShopConfig.getAllinpay();
            accountSetNo = allinpay.getAccountSetNo();
        }
        QueryBalance queryBalance = new QueryBalance(bizUserId, accountSetNo);
        return allinpayOrderService.queryBalance(queryBalance);
    }

    @Override
    public PageVO<InExpDetail> queryInExpDetail(String bizUserId, PageDTO pageDTO, QueryInExpDetailDTO queryInExpDetailDTO) {
        QueryInExpDetail queryInExpDetail = new QueryInExpDetail();
        BeanUtils.copyProperties(queryInExpDetailDTO, queryInExpDetail);
        queryInExpDetail.setBizUserId(bizUserId);
        // 计算分页
        queryInExpDetail.setQueryNum(pageDTO.getPageSize());
        queryInExpDetail.setStartPosition(1 + (pageDTO.getPageNum() - 1) * pageDTO.getPageSize());
        // 发送请求，并封装为分页展示类
        QueryInExpDetailResp resp = allinpayOrderService.queryInExpDetail(queryInExpDetail);
        PageVO<InExpDetail> pageVO = new PageVO<>();
        pageVO.setTotal(resp.getTotalNum());
        pageVO.setList(resp.getInExpDetail());
        int pages = Integer.parseInt(String.valueOf(pageVO.getTotal())) / pageDTO.getPageSize();
        pageVO.setPages(pageVO.getTotal() % pageDTO.getPageSize() == 0 ? pages : pages + 1);
        return pageVO;
    }

    @Override
    public String payBySms(String bizUserId, PayBySmsDTO payBySmsDTO) {
        PayBySms payBySms = new PayBySms();
        BeanUtils.copyProperties(payBySmsDTO, payBySms);
        payBySms.setBizUserId(bizUserId);
        String ipAddr = IpHelper.getIpAddr();
        payBySms.setConsumerIp(ipAddr);
        return allinpayOrderService.payBySms(payBySms);
    }

    @Override
    public String payByPwd(String bizUserId, PayByPwdDTO payByPwdDTO) {
        PayByPwd payByPwd = new PayByPwd();
        BeanUtils.copyProperties(payByPwdDTO, payByPwd);
        payByPwd.setBizUserId(bizUserId);
        String ipAddr = IpHelper.getIpAddr();
        payByPwd.setConsumerIp(ipAddr);
        return allinpayOrderService.payByPwd(payByPwd);
    }

    @Override
    public PayByBackSmsResp payByBackSms(String bizUserId, PayByBackSmsDTO payByBackSmsDTO) {
        PayByBackSmsReq payByBackSmsReq = new PayByBackSmsReq();
        BeanUtils.copyProperties(payByBackSmsDTO, payByBackSmsReq);
        payByBackSmsReq.setBizUserId(bizUserId);
        String ipAddr = IpHelper.getIpAddr();
        payByBackSmsReq.setConsumerIp(ipAddr);
        return allinpayOrderService.payByBackSms(payByBackSmsReq);
    }

    @Override
    public ResendPaySmsResp resendPaySms(String bizOrderNo) {
        ResendPaySmsReq resendPaySmsReq = new ResendPaySmsReq();
        resendPaySmsReq.setBizOrderNo(bizOrderNo);
        return allinpayOrderService.resendPaySms(resendPaySmsReq);
    }

    @Override
    public GetOrderStatusResp getOrderStatus(String bizUserId, String bizOrderNo) {
        GetOrderStatusReq getOrderStatusReq = new GetOrderStatusReq();
        getOrderStatusReq.setBizUserId(bizUserId);
        getOrderStatusReq.setBizOrderNo(bizOrderNo);
        return allinpayOrderService.getOrderStatus(getOrderStatusReq);
    }
}
