package com.cpop.pay.framewok.handler.ecpp;

import com.alibaba.fastjson.JSONObject;
import com.cpop.common.utils.StringUtils;
import com.cpop.core.base.exception.ServiceException;
import com.cpop.core.base.exception.UtilException;
import com.cpop.pay.framewok.config.ecpp.EcppConfiguration;
import com.cpop.pay.framewok.core.constant.EcppApiConstant;
import com.cpop.pay.framewok.core.request.ecpp.*;
import com.cpop.pay.framewok.core.response.ecpp.*;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

/**
 * @author DB
 * @version 1.0.0
 * @since 2024-01-29 16:00
 */
@Component
@Slf4j
public class EcppHandler {

    @Autowired
    private EcppConfiguration ecppConfiguration;

    /**
     * 获取安全密钥
     * @author DB
     * @since 2024/1/29
     */
    public void getSecurityKey() {
        if (ecppConfiguration.checkKeyTime()) {
            return;
        }
        log.info("======================= 获取速达会话密钥 ========================");
        Response response = null;
        String s1 = UUID.randomUUID().toString().replaceAll("-", "");
        try {
            Map<String, String> data = new HashMap<>();
            data.put("content", ecppConfiguration.encrypt(ecppConfiguration.getEcppProperties().getPublicKey(), s1));
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.SECURITY_KEY, JSONObject.toJSONString(data));
            JSONObject result = JSONObject.parseObject(response.body().string());
            String code = result.getString("code");
            if (StringUtils.equals(code, "402.2")) {
                log.error("获取速达会话密钥header出错：" + result);
                return;
            }
            if (StringUtils.equals(code, "200") && result.getJSONObject("data") != null) {
                String resolve = ecppConfiguration.decrypt(ecppConfiguration.getEcppProperties().getPrivateKey(), result.getJSONObject("data").getString("content"));
                String[] argv = resolve.split(":");
                String s2 = argv[0];
                ecppConfiguration.setSessionIv(argv[1]);
                ecppConfiguration.setJSessionId(argv[2]);
                ecppConfiguration.setSessionKey(hexXor(s1, s2));
                log.info("速达会话密钥：{} , 速达密钥iv向量：{}，速达JSessionId: {}", ecppConfiguration.getSessionKey(), ecppConfiguration.getSessionIv(), ecppConfiguration.getJSessionId());
                log.info("======================= 获取速达会话密钥成功 ========================");
                ecppConfiguration.setNextExpireTime(System.currentTimeMillis() + ecppConfiguration.getEXPIRE_TIME());
            } else {
                throw new UtilException("获取速达会话密钥失败：" + result.getString("msg"));
            }
        } catch (Exception e) {
            throw new UtilException(e);
        } finally {
            assert response != null;
            response.close();
        }
    }

    private String hexXor(String str1, String str2) {
        try {
            String[] arr1 = str1.split("");
            String[] arr2 = str2.split("");
            int length = Math.max(str1.length(), str2.length());
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++) {
                Integer a = arr1.length > i ? Integer.parseInt(arr1[i], 16) : 0;
                Integer b = arr2.length > i ? Integer.parseInt(arr2[i], 16) : 0;
                sb.append(Long.toHexString(a ^ b).toUpperCase(Locale.ROOT));
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 获取短信验证码
     * @author DB
     * @since 2024/1/29
     * @param dto 请求
     */
    public EcppSmsCodeResponse sendEcppMsmCode(EcppSmsCodeRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.SEND_MSG, request);
            return ecppConfiguration.parseEcppResponse(response,EcppSmsCodeResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 预付服务登记，签订预付服务，获得预付卡售卡资格；进行预付服务登记前，先完成预付商户登记
     * @author DB
     * @since 2024/1/30
     * @param request 请求
     * @return EcppServiceEntryResponse 响应
     */
    public EcppServiceEntryResponse serviceEntry(EcppServiceEntryRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.SERVICE_ENTRY, request);
            return ecppConfiguration.parseEcppResponse(response, EcppServiceEntryResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 预付服务查询
     * @author DB
     * @since 2024/1/30
     * @param request 请求
     * @return EcppServiceQueryResponse 响应
     */
    public EcppServiceQueryResponse serviceQuery(EcppServiceQueryRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.SERVICE_QUERY, request);
            return ecppConfiguration.parseEcppResponse(response, EcppServiceQueryResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 签约查询
     * @author DB
     * @since 2024/1/30
     * @param request 请求
     * @return EcppSigningQueryResponse 响应
     */
    public EcppSigningQueryResponse signingQuery(EcppSigningQueryRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.SIGNING_QUERY, request);
            return ecppConfiguration.parseEcppResponse(response, EcppSigningQueryResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 客户身份校验
     * @author DB
     * @since 2024/1/30
     * @param request 请求
     * @return EcppCustomerVerifyResponse 响应
     */
    public EcppCustomerVerifyResponse customerVerify(EcppCustomerVerifyRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.CUSTOMER_VERIFY, request);
            return ecppConfiguration.parseEcppResponse(response, EcppCustomerVerifyResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 核销确认
     * @author DB
     * @since 2024/1/30
     * @param request 请求
     * @return EcppWriteOffConfirmResponse 响应
     */
    public EcppWriteOffConfirmResponse writeOffConfirm(EcppWriteOffConfirmRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.WRITE_OFF_CONFIRM, request);
            return ecppConfiguration.parseEcppResponse(response, EcppWriteOffConfirmResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 核销查询
     * @author DB
     * @since 2024/1/30
     * @param request 请求
     * @return EcppWriteOffQueryResponse
     */
    public EcppWriteOffQueryResponse writeOffQuery(EcppWriteOffQueryRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.WRITE_OFF_QUERY, request);
            return ecppConfiguration.parseEcppResponse(response, EcppWriteOffQueryResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 注销退卡
     * @author DB
     * @since 2024/1/30
     * @param request 请求
     * @return EcppLogoutReturnCardResponse
     */
    public EcppLogoutReturnCardResponse logoutReturnCard(EcppLogoutReturnCardRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.LOGOUT_RETURN_CARD, request);
            return ecppConfiguration.parseEcppResponse(response, EcppLogoutReturnCardResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }

    /**
     * 交易列表
     * @author DB
     * @since 2024/1/31
     * @param request 请求
     * @return EcppTradeListResponse
     */
    public EcppTradeListResponse tradeList(EcppTradeListRequest request) {
        Response response = null;
        try {
            response = ecppConfiguration.sendEcppPost(ecppConfiguration.getEcppProperties().getBaseUrl() + EcppApiConstant.TRADE_LIST, request);
            return ecppConfiguration.parseEcppResponse(response, EcppTradeListResponse.class);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        } finally {
            assert response != null;
            response.close();
        }
    }
}
