package cn.pluss.platform.common.impl;

import cn.pluss.platform.common.AliyunService;
import cn.pluss.platform.config.OssConfig;
import cn.pluss.platform.config.StsConfig;
import cn.pluss.platform.dict.Bank4CacheService;
import cn.pluss.platform.entity.Bank4Cache;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.util.HttpResult;
import cn.pluss.platform.util.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.cloudauth20200618.models.VerifyBankElementResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.geoip.model.v20200101.DescribeIpv4LocationRequest;
import com.aliyuncs.geoip.model.v20200101.DescribeIpv4LocationResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import com.aliyun.tea.*;
import com.aliyun.cloudauth20200618.Client;

import javax.xml.ws.Response;
import java.util.*;

@Service
@RequiredArgsConstructor
@Slf4j
public class AliyunServiceImpl implements AliyunService {

    @Autowired
    private Bank4CacheService bank4CacheService;

    private final OssConfig ossConfig;

    private final StsConfig stsConfig;

    @Value("${aliyun.bankcard.app-code}")
    private String appCode;

    @Value("${aliyun.bankcard.bank-url}")
    private String bankCheckUrl;
    /**
     *场景id
     */
    @Value("${aliyun.bankcard.SceneId}")
    private Long SceneId;
    /**
     * 阿里云key
     */
    @Value("${aliyun.keyid}")
    private String ACCESSKEYID;
    /**
     * 阿里云secret
     */
    @Value("${aliyun.keysecret}")
    private String ACCESSKEYSECRET;

    /**
     * 不好用
     * @param ip    ip
     * @return
     */
    @Override
    public DescribeIpv4LocationResponse getLocation(String ip) {
        log.info("顾客 remote ip: {}", ip);
        //
        //
        DefaultProfile profile = DefaultProfile.getProfile(ossConfig.getRegionId(), ossConfig.getKeyid(), ossConfig.getKeysecret());
        IAcsClient client = new DefaultAcsClient(profile);

        DescribeIpv4LocationRequest request = new DescribeIpv4LocationRequest();
        request.setIp(ip);

        try {
            DescribeIpv4LocationResponse response = client.getAcsResponse(request);
            log.info(new Gson().toJson(response));
            return response;
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            log.error("ErrCode:" + e.getErrCode());
            log.error("ErrMsg:" + e.getErrMsg());
            log.error("RequestId:" + e.getRequestId());
        }

        return null;
    }

    @Override
    public void checkBankCorrect(String phone, String bankCardNo, String certNo, String realName) {
        Bank4Cache bank4Cache = new Bank4Cache();
        bank4Cache.setPhone(phone);
        bank4Cache.setBankCardNo(bankCardNo);
        bank4Cache.setIdCardNo(certNo);
        bank4Cache.setName(realName);
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DAY_OF_MONTH, -1);
        bank4Cache.setCreateTimeStart(instance.getTime());

        Bank4Cache one = bank4CacheService.getOne(new QueryWrapper<>(bank4Cache).orderByDesc("createTime").last("limit 1"));
        if (one != null) {
            if (one.getStatus().equals(Bank4Cache.STATUS_PASS)) {
                return;
            } else {
                log.error("银行卡四要素检查：" + one.getRemark());
                throw new MsgException("身份证、银行卡或预留手机号信息不正确");
            }
        }

        // 调用阿里云银行卡认证接口
        Map<String, String> headers = new HashMap<>();
       // headers.put("Authorization", "APPCODE " + appCode);
        Map<String, Object> querys = new HashMap<>();
        querys.put("Mobile", phone);
//        querys.put("bankcard", BankCardNo);
        //querys.put("cardNo", certNo);
//        querys.put("realName", realName);
        querys.put("Mode", "VERIFY_BANK_CARD");
        querys.put("OuterOrderNo", appCode);
        querys.put("BankCardNo", bankCardNo);
        querys.put("IdName", realName);
        querys.put("IdNo", certNo);
        querys.put("SceneId", SceneId);

        HttpResult response = null;
        try {
        //    response = HttpUtil.doGet(bankCheckUrl, querys);
          response = HttpUtil.doGet(bankCheckUrl, headers, querys);
            log.info(response.toString());
        } catch (Exception e) {
            e.printStackTrace();
            try {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            } catch (Exception ignored) {
            }
        }

        JSONObject jsonObject = JSON.parseObject(response.getBody());

        if (200 != response.getCode()) {
            if (403 == response.getCode()) {
                throw new MsgException("银行卡认证接口已欠费，请联系平台");
            } else {
                throw new MsgException("银行卡认证失败");
            }
        }
        if (!"0".equalsIgnoreCase(jsonObject.getString("error_code"))) {
            log.error("银行卡四要素检查：" + jsonObject.getString("reason"));
            bank4Cache.setRemark(jsonObject.getString("reason"));
            bank4Cache.setStatus(Bank4Cache.STATUS_FAIL);
            throw new MsgException("身份证、银行卡或预留手机号信息不正确");
        } else {
            bank4Cache.setStatus(Bank4Cache.STATUS_PASS);
            bank4CacheService.save(bank4Cache);
        }
    }



    @Override
    public void checkBankCorrect(String phone, String bankCardNo, String certNo, String realName, String errorMsg) {
        try {
            checkBankCorrect(phone, bankCardNo, certNo, realName);
        } catch (Exception e) {
            throw new MsgException(errorMsg);
        }
    }

    @Override
    public void checkBankCorrectNow(String phone, String bankCardNo, String certNo, String realName, String errorMsg) {
        try {
            checkBankCorrectNow(phone, bankCardNo, certNo, realName);
        } catch (Exception e) {
            throw new MsgException(errorMsg);
        }
    }

    @Override
    public AssumeRoleResponse.Credentials stsToken(String userId) {
        String endpoint = stsConfig.getEndpoint().replace("https://", "");
        String accessKeyId = stsConfig.getKeyid();
        String accessKeySecret = stsConfig.getKeysecret();
        String roleArn = stsConfig.getRoleArn();
        String roleSessionName = "-" + userId;

        // 允许所有目录权限
        JSONObject policyMap  = new JSONObject();
        List<JSONObject> statementList= new LinkedList<>();
        policyMap.put("Version", "1");
        JSONObject statementMap = new JSONObject();
        statementMap.put("Action", new String[] {"oss:*"});
        statementMap.put("Resource", new String[] {"acs:oss:*:*:*"});
        statementMap.put("Effect", "Allow");
        statementList.add(statementMap);
        policyMap.put("Statement", statementList);

        try {
            // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
            DefaultProfile.addEndpoint( "", "Sts", endpoint);
            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setSysMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            // 若policy为空，则用户将获得该角色下所有权限
            request.setPolicy(policyMap.toJSONString());
            // 设置凭证有效时间
            request.setDurationSeconds(3600L);
            final AssumeRoleResponse response = client.getAcsResponse(request);
            return response.getCredentials();
        } catch (ClientException e) {
            e.printStackTrace();
            log.error("无法获取oss上传token");
            throw new MsgException("无法获取oss上传凭证");
        }
    }

    public static com.aliyun.cloudauth20200618.Client createClient(String accessKeyId, String accessKeySecret) throws Exception{
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填，您的 AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 必填，您的 AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = "cloudauth.aliyuncs.com";
        return new com.aliyun.cloudauth20200618.Client(config);
    }

    @Override
    public void checkBankCorrectNow(String phone, String bankCardNo, String certNo, String realName) {
       // java.util.List<String> args = java.util.Arrays.asList(args_);

        //com.aliyun.cloudauth20200618.Client client = Sample.createClient("accessKeyId", "accessKeySecret");
        Client client = null;
        try {
            client = createClient(ACCESSKEYID,ACCESSKEYSECRET);
        } catch (Exception e) {
            e.printStackTrace();
        }
        com.aliyun.cloudauth20200618.models.VerifyBankElementRequest verifyBankElementRequest = new com.aliyun.cloudauth20200618.models.VerifyBankElementRequest()
                .setMode("VERIFY_BANK_CARD")
                .setBankCardNo(bankCardNo)
                .setIdNo(certNo)
                .setIdName(realName)
                .setMobile(phone)
                .setSceneId(SceneId)
                .setOuterOrderNo(appCode);

        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();

        VerifyBankElementResponse verifyBankElementResponse = null;
        try {
            // 复制代码运行请自行打印 API 的返回值
            assert client != null;
            verifyBankElementResponse = client.verifyBankElementWithOptions(verifyBankElementRequest, runtime);
            log.info(verifyBankElementResponse.toString());
        } catch (TeaException error) {
            // 如有需要，请打印 error
            com.aliyun.teautil.Common.assertAsString(error.message);
            throw new MsgException("银行卡认证失败");
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 如有需要，请打印 error
            com.aliyun.teautil.Common.assertAsString(error.message);
            throw new MsgException("银行卡认证失败");
        }

        if ("403".equals(verifyBankElementResponse.getBody().getCode())){
            throw new MsgException("24小时内重复查询相同信息超过10次，已锁定，请在12小时后重试。");
        }
        if ("428".equals(verifyBankElementResponse.getBody().getCode())){
            throw new MsgException("请正确输入相关信息");
            
        }
        if (!"200".equals(verifyBankElementResponse.getBody().getResultObject().getSubCode())) {
            if ("403".equals(verifyBankElementResponse.getBody().getResultObject().getSubCode())) {
                throw new MsgException("银行卡认证接口已欠费，请联系平台");
            }else if ("201".equals(verifyBankElementResponse.getBody().getResultObject().getSubCode())){
                throw new MsgException("用户的身份信息不匹配");
            }else {
                throw new MsgException("银行卡认证失败");
            }
        }
    }
}
