package com.yc.ship.module.trade.utils;
import cn.hutool.json.JSONObject;
import cn.hutool.json.XML;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;


@Slf4j
public class CMLT40Demo {

    public static void main(String[] args) {
        String host = "10.3.10.50";
        int port = 15999;

        try {
            // 1. 获取当前时间，用于组装公共包头流水与日期
            Date now = new Date();
            String reqDate = new SimpleDateFormat("yyyyMMdd").format(now);
            String reqTime = new SimpleDateFormat("HHmmss").format(now);
            // 构造请求方流水号 (保证唯一性)
            String reqSeqNo = new SimpleDateFormat("yyyyMMddHHmmss").format(now) + "0001";
            Long s1 = System.currentTimeMillis();
            Long s0 = s1-172800000;

            // 2. 构造 CMLT40 增加多级账簿 XML 请求报文
            String xmlData = "<ap>\n" +
                    "  <CCTransCode>CQRD02</CCTransCode>\n" +
                    "  <ProductID>ICC</ProductID>\n" +
                    "  <ChannelType>ERP</ChannelType>\n" +
                    "  <CorpNo></CorpNo>\n" +
                    "  <OpNo></OpNo>\n" +
                    "  <AuthNo></AuthNo>\n" +
                    "  <ReqSeqNo>" + reqSeqNo + "</ReqSeqNo>\n" +
                    "  <ReqDate>" + reqDate + "</ReqDate>\n" +
                    "  <ReqTime>" + reqTime + "</ReqTime>\n" +
                    "  <Sign></Sign>\n" +
                    "  <Corp>\n" +
                    "    <StartDate>20260420</StartDate>\n" +
                    "    <EndDate>20260424</EndDate>\n" +
                    "  </Corp>\n" +
                    "  <Cmp>\n" +
                    "    <DbProv>17</DbProv>\n" +
                    "    <StartTime>"+s0+"</StartTime>\n" +
                    "    <DbAccNo>342101046484369</DbAccNo>\n" +
//                    "    <DbLogAccNo>0000000000</DbLogAccNo>\n" +
                    "    <DbLogAccNo>1203444786</DbLogAccNo>\n" +
                    "    <DbCur>01</DbCur>\n" +
                    "    <LogAccBkOInd>0</LogAccBkOInd>\n" +
                    "  </Cmp>\n" +
                    "</ap>";

            // 3. 按照约定编码报文 (ERP上送报文必须为GBK字符集)
            byte[] xmlBytes = xmlData.getBytes("GBK");

            // 4. 构造7字节包头
            // 第1字节为加密标志（0-不加密），后6字节为数据包长度（包含加密标志位），不足6位在右边用空格补足
//            int packetLen = xmlBytes.length + 1;
            int packetLen = xmlBytes.length;
            String lengthStr = String.format("%-6s", packetLen);
            String headerStr = "0" + lengthStr;
            byte[] headerBytes = headerStr.getBytes("GBK");

            // 拼接完整的待发送字节数组
            byte[] fullPacket = new byte[headerBytes.length + xmlBytes.length];
            System.arraycopy(headerBytes, 0, fullPacket, 0, headerBytes.length);
            System.arraycopy(xmlBytes, 0, fullPacket, headerBytes.length, xmlBytes.length);

            // 5. 发送 TCP/IP Socket 同步短连接请求
            System.out.println("正在连接到前置机 " + host + ":" + port + "...");
            Socket socket = new Socket(host, port);
            // 设置读取超时时间为 30 秒
//            socket.setSoTimeout(30000);

            OutputStream out = socket.getOutputStream();
            out.write(fullPacket);
            out.flush();
            System.out.println("请求报文发送成功，等待响应...\n");
            System.out.println("请求报文发送成功，等待响应...\n"+new String(fullPacket, "GBK"));
//            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK"));
//            PrintWriter out2 = new PrintWriter(socket.getOutputStream(), true);
//
//            String inputLine;
//            while ((inputLine = in.readLine()) != null) {
//                System.out.println("Received: " + inputLine);
//                out2.println("Echo: " + inputLine); // 回显客户端发送的数据
//            }

            // 6. 接收并解析前置机返回的报文
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            // 使用 StringBuilder 拼接读取到的报文内容，必须以 GBK 解码
            StringBuilder responseBuilder = new StringBuilder();

            while ((bytesRead = in.read(buffer)) != -1) {
                responseBuilder.append(new String(buffer, 0, bytesRead, "GBK"));
            }

            socket.close();
            in.close();
            out.close();

            String recvData = responseBuilder.toString();
            if (recvData.length() >= 7) {
                String respHeader = recvData.substring(0, 7);
                String respXml = recvData.substring(7);
                System.out.println("收到前置机响应头: '" + respHeader + "'");
                System.out.println("收到前置机响应报文:\n" + respXml);
                JSONObject jsonObject = XML.toJSONObject(respXml);
                System.out.println(jsonObject);
                JSONObject ap = jsonObject.getJSONObject("ap");
                String respCode = ap.getStr("RespCode");
                if(!"0000".equals(respCode)){
                    System.err.println("交易发送异常，异常信息："+ap.getStr("RespInfo"));
                    //{
                    //    "ap": {
                    //        "CCTransCode": "CQRD02",
                    //        "RespDate": 20260428,
                    //        "RespTime": 105107,
                    //        "Channel": {
                    //            "AccDate": 20260428,
                    //            "JrnNo": "FC24902142",
                    //            "VchNo": 0,
                    //            "RespInfo": "",
                    //            "RxtInfo": "",
                    //            "AbisRespCode": "0000"
                    //        },
                    //        "Cmp": {
                    //            "ContFlag": 0,
                    //            "QueryCnt": 0,
                    //            "BatchFileName": "CQRD02.17999953800000028.GS202604281051000577-D-Q",
                    //            "RespPrvData": ""
                    //        },
                    //        "Corp": {
                    //            "DbAccName": "",
                    //            "DbLogAccName": ""
                    //        },
                    //        "Cme": {
                    //            "RespHead": "Prov|AccNo|LogAccNo|Cur|TrDate|TrJrn|TrTime|AccName|LogAccName|TrType|TrBankNo|CreNo|AmtIndex|CshIndex|Amt|Bal|OvdAmt|VchType|TrCode|VchNo|OppProv|OppAccNo|OppCur|OppName|OppBank|ErrDate|ErrVch|Teller|Abs|Cmt|SpFlag|FmtCode|SpecInfo|",
                    //            "RecordNum": 2,
                    //            "FieldNum": 33
                    //        },
                    //        "RespSeqNo": "",
                    //        "RespSource": 0,
                    //        "RespCode": "0000",
                    //        "RespInfo": "交易成功",
                    //        "RxtInfo": "交易成功",
                    //        "FileFlag": 1
                    //    }
                    //}
                    JSONObject cmp = ap.getJSONObject("Cmp");
                    JSONObject cme = ap.getJSONObject("Cme");
                    String batchFileName = cmp.getStr("BatchFileName");
                    String recordNum = cme.getStr("RecordNum");
                    if(!"0".equals(recordNum)){
                        log.info("批次文件名：" + batchFileName);
                    }
                    String respHead = cme.getStr("RespHead");
                }else {
                    String cardNo = ap.getJSONObject("Cmp").getStr("DbLogAccNo");
                    System.err.println("卡号：" + cardNo);
                }
            } else {
                System.out.println("响应报文异常或为空");
            }

        } catch (SocketTimeoutException e) {
            System.err.println("交易发送超时，请检查ICT前置机通讯状态。");
        } catch (Exception e) {
            System.err.println("交易发送异常: " + e.getMessage());
            e.printStackTrace();
        }
    }
}