package nc.bs.so.m32.maintain.rule.delete;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.yonyou.cloud.utils.StringUtils;
import nc.bs.dao.DAOException;
import nc.bs.logging.Logger;
import nc.bs.trade.business.HYSuperDMO;
import nc.bs.uapbd.util.IgnoreSslUtil;
import nc.impl.pubapp.pattern.rule.IRule;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.pub.BusinessException;
import nc.vo.so.m32.entity.SaleInvoiceBVO;
import nc.vo.so.m32.entity.SaleInvoiceHVO;
import nc.vo.so.m32.entity.SaleInvoiceVO;
import nccloud.baseapp.core.log.NCCForUAPLogger;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 删除后同步修改BIP的开票申请存的NCC信息
 * 2005适配2312
 *
 * @author mzr
 * @date 2025/3/20
 */
public class SyncBipBillRuleForDelete implements IRule<SaleInvoiceVO> {
    private HYSuperDMO superDMO = null;
    private String appKey = "";
    private String appSecret = "";
    private String baseUrl = "https://www.tkkfbip.com";
    private String tokenUrl = "/iuap-api-auth/open-auth/selfAppAuth/getAccessToken";
    private String toBipUrl = "";

    @Override
    public void process(SaleInvoiceVO[] vos) {
        try {
            boolean hasVdef38 = Arrays.stream(vos)
                    .map(SaleInvoiceVO::getParentVO)
                    .anyMatch(hvo -> StringUtils.isNotEmpty(hvo.getVdef38()));
            // 如果vos里边都没有存BIP合同的开票申请的主键，则不往下执行
            if (!hasVdef38) {
                return;
            }
            // 从自定义档案中获取
            Map<String, String> bipParamMap = checkBipParam();
            if (bipParamMap.isEmpty()) {
                return;
            }
            baseUrl = bipParamMap.get("baseUrl");
            appKey = bipParamMap.get("appKey");
            appSecret = bipParamMap.get("appSecret");
            toBipUrl = bipParamMap.get("updateInvoice");
            NCCForUAPLogger.debug(String.format("SyncBipBillRuleForDelete-baseUrl = [%s],appKey = [%s],appSecret = [%s],",
                    baseUrl, appKey, appSecret));
            Logger.error(String.format("SyncBipBillRuleForDelete-baseUrl = [%s],appKey = [%s],appSecret = [%s],",
                    baseUrl, appKey, appSecret));
            String access_token = getAccessToken();
            for (SaleInvoiceVO invoiceVO : vos) {
                SaleInvoiceHVO hvo = invoiceVO.getParentVO();
                SaleInvoiceBVO[] bvos = invoiceVO.getChildrenVO();
                if (access_token.isEmpty()) {
                    Logger.error("SyncBipBillRuleForDelete-token获取失败");
                    throw new BusinessException("token获取失败");
                }
                // bip旗舰版发票主键
                String vdef38 = hvo.getVdef38();
                Logger.error("SyncBipBillRuleForDelete-vdef38 = " + vdef38);
                if (StringUtils.isNotEmpty(vdef38)) {
                    List<JSONObject> childrenList = new ArrayList<>();
                    for (SaleInvoiceBVO bvo : bvos) {
                        JSONObject jsonObject = new JSONObject();
                        if (StringUtils.isNotEmpty(bvo.getVbdef14())) {
                            jsonObject.put("id", bvo.getVbdef14());
                            jsonObject.put("saleInvoiceDetailId", "");
                            childrenList.add(jsonObject);
                        }
                    }
                    JSONObject updateJson = new JSONObject();
                    updateJson.put("id", vdef38);
                    updateJson.put("saleInvoiceId", "");
                    updateJson.put("contractInvoiceApplicationDetailList", childrenList);
                    String url = baseUrl + toBipUrl + "?access_token=" + access_token;
                    String bipRes = doPost(url, updateJson);
                    NCCForUAPLogger.debug("SyncBipBillRuleForDelete-bipRes = " + bipRes);
                }
            }
        } catch (Exception e) {
            Logger.error("SyncBipBillRuleForDelete-exp:" + e.getMessage(), e);
        }
    }

    public HYSuperDMO getSuperDMO() {
        if (superDMO == null) {
            superDMO = new HYSuperDMO();
        }
        return superDMO;
    }

    /**
     * 获取旗舰版的token
     *
     * @return token
     * @author mzr
     * @date 2025/3/20
     */
    private String getAccessToken() throws NoSuchAlgorithmException, InvalidKeyException, IOException {
        String access_token = "";
        // 获取旗舰版的token
        Map<String, String> params = new HashMap<>();
        // 除签名外的其他参数
        params.put("appKey", appKey);
        String timestamp = String.valueOf(System.currentTimeMillis());
        params.put("timestamp", timestamp);
        // 计算签名
        Map<String, String> treeMap = new TreeMap<>(params);
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : treeMap.entrySet()) {
            stringBuilder.append(entry.getKey()).append(entry.getValue());
        }
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        String base64String = Base64.getEncoder().encodeToString(signData);
        String signature = URLEncoder.encode(base64String, "UTF-8");
        params.put("signature", signature);
        String responseString = doGet(baseUrl + tokenUrl, params);
        Logger.error("SyncBipBillRuleForDelete-responseString = " + responseString);
        Gson gson = new Gson();
        Map result = gson.fromJson(responseString, Map.class);
        if (StringUtils.equals("00000", result.getOrDefault("code", "") + "")) {
            Map<String, Object> tokenInfo = (Map<String, Object>) result.get("data");
            access_token = (String) tokenInfo.getOrDefault("access_token", "");
        }
        Logger.error("SyncBipBillRuleForDelete-getAccessToken = " + access_token);
        return access_token;
    }

    private String doGet(String requestUrl, Map<String, String> paramMap) throws IOException {

        StringBuilder param = new StringBuilder("?");
        if (paramMap != null) {
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                param.append(entry.getKey());
                param.append("=");
                param.append(entry.getValue());
                param.append("&");
            }
            param.deleteCharAt(param.length() - 1);
        }
        String url = requestUrl + param;
        URL u = new URL(url);
        try {
            if ("https".equalsIgnoreCase(u.getProtocol())) {// 判定网址是否信任，不信任则调用忽略信任工具类SslUtil
                IgnoreSslUtil.ignoreSsl();
            }
            HttpsURLConnection connection = (HttpsURLConnection) u.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.connect();
            StringBuilder response = new StringBuilder();
            int responsecode = connection.getResponseCode();
            if (responsecode == HttpsURLConnection.HTTP_OK) {
                InputStream inputstream = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputstream));
                String line;

                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
            }
            connection.disconnect();
            return response.toString();
        } catch (Exception e) {
            Logger.error("SyncBipBillRuleForDelete-doGet:" + e.getMessage(), e);
        }


        return null;
    }

    private String doPost(String requestUrl, JSONObject json) throws IOException {
        URL u = new URL(requestUrl);
        try {
            if ("https".equalsIgnoreCase(u.getProtocol())) {// 判定网址是否信任，不信任则调用忽略信任工具类SslUtil
                IgnoreSslUtil.ignoreSsl();
            }
            HttpsURLConnection connection = (HttpsURLConnection) u.openConnection();
            // 设置请求方法
            connection.setRequestMethod("POST");
            // 设置请求属性
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            // 发送POST请求必须设置如下两行
            connection.setDoOutput(true);
            connection.setDoInput(true);
            byte[] outputInBytes = json.toJSONString().getBytes(StandardCharsets.UTF_8);
            // 写入数据到请求体
            OutputStream os = connection.getOutputStream();
            os.write(outputInBytes);
            // 获取响应码
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
            // 读取响应
            String response = "";
            try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                br.readLine();
                // System.out.println("Response: " + response);
            }
            // 关闭连接
            connection.disconnect();
            return response;
        } catch (Exception e) {
            Logger.error("SyncBipBillRuleForDelete-doPost:" + e.getMessage(), e);
        }
        return null;
    }

    /**
     * 检查bip参数是否完整
     */
    private Map<String, String> checkBipParam() {
        Map<String, String> map = new HashMap<String, String>();
        String strWhere = " pk_defdoclist in (select pk_defdoclist from bd_defdoclist where code='BIP-sq' and dr=0 ) and dr=0";
        try {
            DefdocVO[] defdocVOs = (DefdocVO[]) getSuperDMO().queryByWhereClause(DefdocVO.class, strWhere);
            if (defdocVOs != null && defdocVOs.length > 0) {
                for (DefdocVO defdocVO : defdocVOs) {
                    map.put(defdocVO.getCode().trim(), defdocVO.getName());
                }
            }
        } catch (DAOException e) {
            e.printStackTrace();
        }
        return map;

    }

}
