package nccloud.web.cmp.informer.informer.action;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import nc.bs.logging.Logger;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.JdbcSession;
import nc.jdbc.framework.PersistenceManager;
import nc.jdbc.framework.exception.DbException;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.web.cmp.informer.action.InformerAction;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

/**
 * 到账通知发布-推送按钮-推送合同平台的到账通知单
 * 2005适配2312
 *
 * @author mzr
 * @date 2025/04/02
 */
public class myBtnClickAction extends InformerAction implements ICommonAction {

    @Override
    public Object doAction(IRequest request) {


        // 初始化结果映射，用于存储处理结果
        HashMap<String, String> resultMap = new HashMap<String, String>();
        // 读取请求中的JSON数据

        String json = request.read();
        Map<String, Object> maps = JSON.parseObject(json, Map.class);
        if (maps.get("pks") == null) {
            resultMap.put("result", "请选择行");
            return resultMap;
        }
        JSONArray jsonArray = (JSONArray) maps.get("pks");
        ArrayList<Object> pks = new ArrayList<>(Arrays.asList(jsonArray.toArray()));

        // 使用 String.join 进行字符串拼接
        String result = "";
        StringBuilder sb = new StringBuilder();
        if (pks.size() > 1) {
            for (int i = 0; i < pks.size(); i++) {
                sb.append("'").append(pks.get(i)).append("'");
                if (i < pks.size() - 1) {
                    sb.append(",");
                }
            }

            result = sb.toString();
        } else {
            result = "'" + (String) pks.get(0) + "'";

        }
        Logger.error(result);
        // 解析JSON数据为JSONObject对象
        // 从JSON对象中提取账单编号
        Logger.error(json);
        String urlpath;
        String appKey;
        String appSecret;
        String tenant;

        // 如果账单编号为空，则返回失败结果

        try {
            String urlsql = "select code,name from bd_defdoc  where  code='baseUrl'";
            String appksql = "select code,name from bd_defdoc  where  code='appKey'";
            String uappssql = "select code,name from bd_defdoc  where  code='appSecret'";
            String tenantsql = "select code,name from bd_defdoc  where  code='tenant'";

            Map<String, Object> urls = (Map<String, Object>) getQueryService().executeQuery(urlsql, new MapProcessor());
            Map<String, Object> appks = (Map<String, Object>) getQueryService().executeQuery(appksql, new MapProcessor());
            Map<String, Object> appses = (Map<String, Object>) getQueryService().executeQuery(uappssql, new MapProcessor());
            Map<String, Object> tenants = (Map<String, Object>) getQueryService().executeQuery(tenantsql, new MapProcessor());

            if (urls.get("code") != null) {
                urlpath = (String) urls.get("name");
            } else {
                resultMap.put("result", "未配置url");
                return resultMap;
            }
            if (appks.get("code") != null) {
                appKey = (String) appks.get("name");
            } else {
                resultMap.put("result", "未配置appKey");
                return resultMap;
            }
            if (appses.get("code") != null) {
                appSecret = (String) appses.get("name");
            } else {
                resultMap.put("result", "未配置appSecret");
                return resultMap;
            }
            if (tenants.get("code") != null) {
                tenant = (String) tenants.get("name");
            } else {
                resultMap.put("result", "未配置tenant");
                return resultMap;
            }
            long timestampMillis = System.currentTimeMillis();
            Logger.error("当前时间戳（毫秒）：" + timestampMillis);
            String dai = "appKey" + appKey + "timestamp" + timestampMillis;
            String signature = calculateHmacSHA256(dai, appSecret);
            SSLUtilities sas = new SSLUtilities();
            sas.disableCertificateValidation();

            String urlstr = "appKey=" + appKey + "&timestamp=" + timestampMillis + "&signature=" + signature;
            URL url = new URL(urlpath + "/iuap-api-auth/open-auth/selfAppAuth/getAccessToken?" + urlstr);
            // 打开连接
            HttpURLConnection con = (HttpURLConnection) url.openConnection();

            // 设置请求方法为 GET
            con.setRequestMethod("GET");


            // 获取响应代码
            BufferedReader ins = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();

            while ((inputLine = ins.readLine()) != null) {
                response.append(inputLine);
            }

            Logger.error(response);

            String jsonString = response.toString();
            Map<String, Object> map = JSON.parseObject(jsonString, Map.class);
            Logger.error("jsonString = " + jsonString);

            Logger.error("url = " + url);

            // 获取当前年份
            String sql = " select bz.code as nzcode,jstype.code as pk_balatype,ban.code bancode,ban.name as banname,bankname,bank.accnum as  accnum,infodate,CASE direction " +
                    "WHEN 'paymoney'  THEN '付款' " +
                    "WHEN 'receivemoney'  THEN '收款' " +
                    "ELSE '不存在' " +
                    "END as direction, 'CNY' as currencyCode,moneyy , bant.code as  dfcode,bant.name as dfname,oppbankaccount,bankt.accnum dfaccnum " +
                    ",pk_oppunit,org.code as orgcode,org.name as orgname,cmp.pk_informer " +
                    ",cmp.memo,cmp.transerial,df.name as  ksmc,df.code as  ksbm,cmp.note_no,vdef1,cmp.oppunitname, cmp.bankrelated_code " +
                    "from cmp_informer cmp " +
                    "left join bd_bankaccbas bank on cmp.pk_bankacc=bank.pk_bankaccbas " +
                    "left join bd_bankdoc ban on cmp.pk_bank=ban.pk_bankdoc " +
                    "left join bd_bankdoc bant on cmp.pk_oppbank=bant.pk_bankdoc " +
                    "left join bd_bankaccbas bankt on cmp.pk_oppacc=bankt.pk_bankaccbas " +
                    "left join bd_cust_supplier df  on cmp.pk_oppunit=df.pk_cust_sup " +
                    "left join org_financeorg org on cmp.pk_org = org.pk_financeorg " +
                    "left join bd_balatype jstype on jstype.pk_balatype =cmp.pk_balatype " +
                    "left join bd_currtype bz on cmp.pk_currtype=bz.pk_currtype" +
                    " where  cmp.pk_informer in(" + result + ") ";
            List<Map<String, String>> results = (List<Map<String, String>>) getQueryService().executeQuery(sql, new MapListProcessor());

            ArrayList lists = new ArrayList();
            for (int i = 0; i < results.size(); i++) {
                Map vmao = new HashMap();
                Map<String, String> row = results.get(i);
                String vdef1 = (String) row.get("vdef1");
                if ("已推送".equals(vdef1)) {
                    resultMap.put("flag", "false");
                    resultMap.put("message", "已推送无法再次推送");
                    return resultMap;
                }
                if ("撤回".equals(vdef1)) {
                    vmao.put("publishStatus", "再次发布");
                } else {
                    vmao.put("publishStatus", "");
                }


                String pjlsh;
                if (row.get("transerial") != null) {
                    pjlsh = row.get("transerial");
                } else if (row.get("note_no") != null) {
                    pjlsh = row.get("note_no");
                } else {
                    resultMap.put("flag", "false");
                    resultMap.put("message", "票据与流水号不可同时为空");
                    return resultMap;
                }


                vmao.put("accountName", row.get("bancode"));
                vmao.put("bankNum", row.get("accnum"));
                vmao.put("transactionDate", row.get("infodate"));
                vmao.put("paymentReceiptStatus", row.get("direction"));
                vmao.put("currencyCode", row.get("nzcode"));
                vmao.put("transactionAmount", row.get("moneyy"));
                vmao.put("pendingClaimAmount", 0);
                vmao.put("oppAccount", row.get("oppbankaccount"));
                vmao.put("oppAccountName", row.get("oppunitname"));
                vmao.put("oppBank", row.get("dfcode"));
                vmao.put("oppBankName", row.get("dfname"));
                vmao.put("description", "--");
                if (StringUtils.isNotEmpty(row.get("memo"))) {
                    vmao.put("description", row.get("memo"));
                }
                vmao.put("bankTransactionNumber", pjlsh);
                vmao.put("accountType", "默认类型");
                vmao.put("orgCode", row.get("orgcode"));
                vmao.put("billNumber", row.get("note_no"));

                if (row.get("pk_balatype") != null && !Objects.equals(row.get("pk_balatype"), "") && !Objects.equals(row.get("pk_balatype"), "~")) {
                    vmao.put("paymentMethod", row.get("pk_balatype"));
                } else {
                    vmao.put("paymentMethod", "10");
                }
                vmao.put("sourceId", row.get("pk_informer"));
                vmao.put("bankrelatedCode", row.get("bankrelated_code"));
                lists.add(vmao);
            }

            // lists转json
            String jsonString1 = JSON.toJSONString(lists);
            Map access_token = (Map) map.get("data");
            String urls2 = urlpath + "/iuap-api-gateway/" + tenant + "/current_yonbip_default_sys/KKAPI/paymentNotice/addBatch?access_token=" + access_token.get("access_token");
            Map mapjson = httpFW(urls2, jsonString1);
            Logger.error("myBtnClickAction-jsonString1 = " + jsonString1);
            Logger.error("myBtnClickAction-mapjson = " + mapjson);
            if (!"200".equals(mapjson.getOrDefault("code", "") + "")) {
                throw new Exception(mapjson.getOrDefault("message", "推送失败") + "");
            }
            Map datas = (Map) mapjson.get("data");
            JSONArray faijsonist = (JSONArray) datas.get("failData");

            String message1 = (String) mapjson.get("message");
            JSONArray jsonist = (JSONArray) datas.get("successData");
            // 将JSONArray转换为List<String>
            ArrayList<String> successData = null;
            ArrayList<String> failData = null;

            if (jsonist != null) {
                successData = (ArrayList<String>) jsonist.toJavaList(String.class);

            }
            if (faijsonist != null) {
                failData = (ArrayList<String>) faijsonist.toJavaList(String.class);
            }
            ArrayList sqlStr = new ArrayList<>();
            for (int i = 0; i < pks.size(); i++) {
                String pk_s = (String) pks.get(i);
                String sql1;
                if (successData != null && successData.contains(pk_s)) {
                    sql1 = "update cmp_informer set vdef1='已推送' where pk_informer='" + pk_s + "'";
                    sqlStr.add(sql1);
                } else {
                    sql1 = "update cmp_informer set vdef1='推送失败' where pk_informer='" + pk_s + "'";
                }
                sqlStr.add(sql1);

            }


            int succState = executeUpdate(sqlStr);
            String message = datas.get("successData") + "成功" + message1;
            if (failData != null && !failData.isEmpty()) {
                message = message + "，失败：" + failData;
            }
            resultMap.put("flag", "true");
            resultMap.put("message", message);
            ins.close();
        } catch (Exception ex) {
            // 捕获异常，并记录错误日志
            Logger.error("myBtnClickAction-exp:" + ex.getMessage(), ex);
            ExceptionUtils.wrapBusinessException(ex.getMessage());
        }

        // 返回结果映射
        return resultMap;
    }

    public IUAPQueryBS getQueryService() {

        return ServiceLocator.find(IUAPQueryBS.class);
    }

    public static String calculateHmacSHA256(String data, String key) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
        String algorithm = "HmacSHA256";
        Mac hmacSHA256 = Mac.getInstance(algorithm);
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), algorithm);
        hmacSHA256.init(secretKey);
        byte[] hashBytes = hmacSHA256.doFinal(data.getBytes());
        String base64Hash = Base64.encodeBase64String(hashBytes);
        return URLEncoder.encode(base64Hash, StandardCharsets.UTF_8);
    }


    public static Map httpFW(String urlString, String jsonInputString) {
        Logger.error("请求值 = " + jsonInputString);
        try {
            URL url = new URL(urlString);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            connection.setDoOutput(true);

            // 发送请求
            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
                os.write(input, 0, input.length);
            }

            // 获取响应码
            int responseCode = connection.getResponseCode();
            System.out.println("响应码: " + responseCode);
            // 根据响应码读取响应
            InputStream is = (responseCode >= 200 && responseCode < 300) ? connection.getInputStream() : connection.getErrorStream();
            StringBuilder response = new StringBuilder();

            try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
                String responseLine;
                while ((responseLine = br.readLine()) != null) {
                    response.append(responseLine.trim());
                }
            }

            // 输出响应
            System.out.println("返回值:");
            System.out.println(response.toString());
            // 返回map
            Map result = JSON.parseObject(response.toString(), HashMap.class);
            return result;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public class SSLUtilities {
        public void disableCertificateValidation() throws Exception {
            TrustManager[] trustAllCertificates = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }

                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                        }

                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                        }
                    }
            };

            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCertificates, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        }
    }

    public int executeUpdate(List<String> updateSqls) throws DbException {
        if (updateSqls == null) {
            return 0;
        }

        int ret = 0;
        PersistenceManager manager = null;
        JdbcSession session = null;
        Connection connection = null;

        try {
            manager = PersistenceManager.getInstance();
            session = manager.getJdbcSession();
            connection = session.getConnection();  // 获取实际的数据库连接
//			connection = ConnectionFactory.getConnection();
            // 开始事务
            connection.setAutoCommit(false);  // 禁用自动提交，手动管理事务

            // 执行批量操作
            for (String sql : updateSqls) {
                session.addBatch(sql);
            }


            // 执行批处理
            ret = session.executeBatch();

            // 提交事务
            connection.commit();  // 批处理成功后提交事务

        } catch (DbException e) {
            if (connection != null) {
                try {
                    // 如果发生异常，回滚事务
                    connection.rollback();
                } catch (SQLException rollbackEx) {
                    // 记录回滚异常的详细信息
                    throw new DbException("Error during transaction rollback", rollbackEx) {
                        @Override
                        public boolean isDataIntegrityViolation() {
                            return false;
                        }

                        @Override
                        public boolean isBadSQLGrammar() {
                            return false;
                        }
                    };
                }
            }
            throw e;  // 将原始异常抛出
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (connection != null) {
                try {
                    // 恢复自动提交模式，确保不会影响其他操作
                    connection.setAutoCommit(true);
                } catch (SQLException e) {
                    // 忽略恢复自动提交时的异常
                }
            }
            if (manager != null) {
                manager.release();
            }
        }

        return ret;
    }

}