package com.morefun.tester;

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

/**
 * Simple TCP/IP Client for sending ISO8583 messages
 */
public class SimpleTCPClient {
    
    /**
     * Send message via TCP and return response
     */
    public static String sendMessage(String message, String host, int port, boolean useSSL, int timeout) throws Exception {
        Socket socket = null;
        PrintWriter out = null;
        BufferedReader in = null;
        
        try {
            System.out.println("\n=== TCP Connection Details ===");
            System.out.println("Host: " + host + ":" + port);
            System.out.println("SSL: " + (useSSL ? "ENABLED" : "DISABLED"));
            System.out.println("Timeout: " + timeout + "ms");
            System.out.println("Message Length: " + message.length() + " chars");
            
            // Create socket
            if (useSSL) {
                SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
                socket = factory.createSocket(host, port);
                System.out.println("✓ SSL Socket created");
            } else {
                socket = new Socket();
                socket.connect(new InetSocketAddress(host, port), timeout);
                System.out.println("✓ TCP Socket connected");
            }
            
            socket.setSoTimeout(timeout);
            
            // Setup streams
            out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
            
            // Send message with length prefix (ISO8583 standard)
            String lengthPrefix = String.format("%04d", message.length());
            String fullMessage = lengthPrefix + message;
            
            System.out.println("\n=== Sending Message ===");
            System.out.println("Length Prefix: " + lengthPrefix);
            System.out.println("Message Sample: " + message.substring(0, Math.min(50, message.length())) + "...");
            
            out.print(fullMessage);
            out.flush();
            System.out.println("✓ Message sent successfully");
            
            // Read response
            System.out.println("\n=== Reading Response ===");
            System.out.println("Waiting for response...");
            
            // Read length prefix first
            char[] lengthBuffer = new char[4];
            int bytesRead = in.read(lengthBuffer, 0, 4);
            
            if (bytesRead < 4) {
                throw new IOException("Could not read response length prefix");
            }
            
            int responseLength = Integer.parseInt(new String(lengthBuffer));
            System.out.println("Response Length: " + responseLength);
            
            // Read response message
            char[] messageBuffer = new char[responseLength];
            bytesRead = in.read(messageBuffer, 0, responseLength);
            
            if (bytesRead < responseLength) {
                throw new IOException("Could not read complete response message");
            }
            
            String response = new String(messageBuffer);
            System.out.println("✓ Response received");
            System.out.println("Response Sample: " + response.substring(0, Math.min(50, response.length())) + "...");
            
            return response;
            
        } finally {
            // Clean up resources
            if (out != null) out.close();
            if (in != null) in.close();
            if (socket != null && !socket.isClosed()) {
                socket.close();
                System.out.println("✓ Connection closed");
            }
        }
    }
    
    /**
     * Send raw byte array message
     */
    public static byte[] sendRawMessage(byte[] message, String host, int port, boolean useSSL, int timeout) throws Exception {
        Socket socket = null;
        OutputStream out = null;
        InputStream in = null;
        
        try {
            System.out.println("\n=== Raw TCP Connection ===");
            System.out.println("Host: " + host + ":" + port);
            System.out.println("Message Size: " + message.length + " bytes");
            
            // Create socket
            if (useSSL) {
                SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
                socket = factory.createSocket(host, port);
            } else {
                socket = new Socket();
                socket.connect(new InetSocketAddress(host, port), timeout);
            }
            
            socket.setSoTimeout(timeout);
            
            // Setup streams
            out = socket.getOutputStream();
            in = socket.getInputStream();
            
            // Send message with length prefix
            byte[] lengthPrefix = String.format("%04d", message.length).getBytes();
            out.write(lengthPrefix);
            out.write(message);
            out.flush();
            
            System.out.println("✓ Raw message sent");
            
            // Read response length
            byte[] lengthBuffer = new byte[4];
            int bytesRead = in.read(lengthBuffer);
            
            if (bytesRead < 4) {
                throw new IOException("Could not read response length");
            }
            
            int responseLength = Integer.parseInt(new String(lengthBuffer));
            
            // Read response
            byte[] responseBuffer = new byte[responseLength];
            bytesRead = in.read(responseBuffer);
            
            if (bytesRead < responseLength) {
                throw new IOException("Could not read complete response");
            }
            
            System.out.println("✓ Raw response received (" + responseLength + " bytes)");
            return responseBuffer;
            
        } finally {
            if (out != null) out.close();
            if (in != null) in.close();
            if (socket != null && !socket.isClosed()) {
                socket.close();
            }
        }
    }
    
    /**
     * Test connection to server
     */
    public static boolean testConnection(String host, int port, int timeout) {
        try {
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(host, port), timeout);
            socket.close();
            System.out.println("✓ Connection test successful to " + host + ":" + port);
            return true;
        } catch (Exception e) {
            System.out.println("✗ Connection test failed to " + host + ":" + port + " - " + e.getMessage());
            return false;
        }
    }
    
    /**
     * Convert string to hex for debugging
     */
    public static String toHex(String str) {
        StringBuilder hex = new StringBuilder();
        for (char c : str.toCharArray()) {
            hex.append(String.format("%02X ", (int) c));
        }
        return hex.toString().trim();
    }
    
    /**
     * Convert byte array to hex for debugging
     */
    public static String toHex(byte[] bytes) {
        StringBuilder hex = new StringBuilder();
        for (byte b : bytes) {
            hex.append(String.format("%02X ", b & 0xFF));
        }
        return hex.toString().trim();
    }
}