package com.sqx.modules.app.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.dytnsapi20200217.Client;
import com.aliyun.dytnsapi20200217.models.CertNoTwoElementVerificationRequest;
import com.aliyun.dytnsapi20200217.models.CertNoTwoElementVerificationResponse;
import com.aliyun.teautil.models.RuntimeOptions;
import com.sqx.common.exception.SqxException;
import com.sqx.modules.app.dto.AuthRespDTO;
import com.sqx.modules.app.service.AliService;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.common.service.CommonInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

@Service
@Slf4j
public class AliServiceImpl implements AliService {
    private final CommonInfoService commonInfoService;
    private Client client;

    public AliServiceImpl(CommonInfoService commonInfoService) {
        this.commonInfoService = commonInfoService;
    }

    @PostConstruct
    public void init() throws Exception {
        CommonInfo keyIdInfo = commonInfoService.findOne(85);
        CommonInfo securityInfo = commonInfoService.findOne(86);

        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
                .setAccessKeyId(keyIdInfo.getValue())
                // 必填，请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
                .setAccessKeySecret(securityInfo.getValue());
        config.endpoint = "dytnsapi.aliyuncs.com";
        this.client = new Client(config);
    }


    @Override
    public void authCertNo(String name, String idCard) {
        log.info("阿里云二要素认证请求参数: {} {}", name, idCard);
        CertNoTwoElementVerificationRequest certNoTwoElementVerificationRequest = new com.aliyun.dytnsapi20200217.models.CertNoTwoElementVerificationRequest()
                .setAuthCode("t92K8i9ae6")
                .setCertName(name)
                .setCertNo(idCard);
        RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            CertNoTwoElementVerificationResponse resp = client.certNoTwoElementVerificationWithOptions(certNoTwoElementVerificationRequest, runtime);
            log.info("阿里云二要素认证响应参数: {}", resp);
            if (resp.getStatusCode() != 200) {
                throw new SqxException("请求失败");
            }

            if (!"OK".equals(resp.getBody().getCode())) {
                throw new SqxException(resp.getBody().getMessage());
            }

            if (!"1".equals(resp.getBody().getData().getIsConsistent())) {
                throw new SqxException("身份证信息不匹配，认证失败");
            }
        } catch (Exception e) {
            throw new SqxException(e.getMessage());
        }
    }

    public static final Pattern CHINESE_NAME = Pattern.compile("^[\u2E80-\u9FFF·]{2,60}$");

    /**
     * 阿里云四要素认证
     *
     * @param name
     * @param idCard
     * @param accountNo
     * @param bankPreMobile
     */
    @Override
    public AuthRespDTO auth(String name, String idCard, String accountNo, String bankPreMobile) {
        log.info("阿里云四要素认证请求参数: {} {} {} {}", name, idCard, accountNo, bankPreMobile);
        if (StrUtil.isBlank(name)) {
            throw new SqxException("持卡人姓名不能为空");
        }
        if (StrUtil.isBlank(idCard)) {
            throw new SqxException("身份证号码不能为空");
        }
        if (StrUtil.isBlank(accountNo)) {
            throw new SqxException("银行卡卡号不能为空");
        }
        if (StrUtil.isBlank(bankPreMobile)) {
            throw new SqxException("银行预留手机号码不能为空");
        }
        if (!Validator.isMactchRegex(CHINESE_NAME, name)) {
            throw new SqxException("持卡人姓名不合法");
        }
        boolean validCard = IdcardUtil.isValidCard(idCard);
        if (!validCard) {
            throw new SqxException("身份证号码不合法");
        }
        validCard = Validator.isMobile(bankPreMobile);
        if (!validCard) {
            throw new SqxException("银行预留手机号码格式不正确");
        }
        String appcode = "f98606b602564d209f37fc02b0bd590c";
        Map<String, String> headers = new HashMap<>(2);
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, Object> params = new HashMap<>();
        params.put("accountNo", accountNo);
        params.put("name", name);
        params.put("idCardCode", idCard);
        params.put("bankPreMobile", bankPreMobile);
        String reqBody = URLUtil.encode(StrUtil.format("accountNo={}&name={}&idCardCode={}&bankPreMobile={}", accountNo, name, idCard, bankPreMobile), Charset.defaultCharset());
        String respBody = HttpUtil.createPost("https://bkvip.market.alicloudapi.com/v3/bcheck").headerMap(headers, true).body(reqBody).timeout(15 * 1000).execute().body();
        // {"error_code":0,"reason":"成功","result":{"respCode":"0","respMsg":"银行卡鉴权成功","bancardInfor":{"bankName":"招商银行","BankCode":"03080000","BankId":5,"type":"借记卡","cardname":"一卡通(银联卡)","tel":"95555","Icon":"2014121619271052743.gif"}},"sn":"010817431025283426800706871"}
        // {"error_code":10028,"reason":"成功","result":{"respCode":"6","respMsg":"身份证格式有误","bancardInfor":{"bankName":"招商银行","BankCode":"03080000","BankId":5,"type":"借记卡","cardname":"一卡通(银联卡)","tel":"95555","Icon":"2014121619271052743.gif"}},"sn":"010817575524183118006799233"}
        JSONObject ret = JSONUtil.parseObj(respBody);
        JSONObject result = ret.getJSONObject("result");
        Integer errorCode = ret.getInt("error_code");
        String respCode = result.getStr("respCode");
        if (errorCode == 0 && "0".equals(respCode)) {
        } else {
            throw new SqxException(result.getStr("respMsg"));
        }
        String bankName = null;
        boolean isExist = result.containsKey("bancardInfor");
        if (isExist) {
            bankName = result.getJSONObject("bancardInfor").getStr("bankName");
        }
        AuthRespDTO dto = new AuthRespDTO();
        dto.setBankName(bankName);
        dto.setRespJson(respBody);
        return dto;
    }
}
