package com.blackauth.sdk;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import java.lang.management.ManagementFactory;

/**
 * ==========================================================
 * BlackAuth Java SDK - Sentinel Licensing & Anti-Tamper Engine
 * Version: 1.2 (1:1 KeyAuth CC Protocol Compatible)
 * Compatible with Java 8+, OpenJDK, GraalVM, Minecraft mods, & Enterprise Java
 * Zero external dependencies (Pure Java Standard Library)
 * ==========================================================
 */
public class BlackAuth {

    public static class ResponseData {
        public boolean success = false;
        public String message = "";
        public String code = "";
    }

    public static class SubscriptionData {
        public String subscription = "default";
        public String expiry = "Lifetime";
    }

    public static class UserData {
        public String username = "";
        public String ip = "";
        public String hwid = "";
        public String createdate = "";
        public String lastlogin = "";
        public List<SubscriptionData> subscriptions = new ArrayList<>();
    }

    public static class Api {
        public String name;
        public String ownerid;
        public String secret;
        public String version;
        public String url;

        public String sessionid = "";
        public String enckey = "";
        public ResponseData response = new ResponseData();
        public UserData user_data = new UserData();

        public Api(String name, String ownerid, String secret, String version) {
            this(name, ownerid, secret, version, "https://blackauth.online/api/v1");
        }

        public Api(String name, String ownerid, String secret, String version, String url) {
            this.name = name;
            this.ownerid = ownerid;
            this.secret = secret;
            this.version = version;
            this.url = url != null && url.endsWith("/") ? url.substring(0, url.length() - 1) : url;
        }

        // ======================================================
        // Security & Anti-Reverse-Engineering Watchdog
        // ======================================================

        public boolean check_security(boolean autoTerminate) {
            String threat = "";

            // 1. JVM Debugger Inspection
            List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
            for (String arg : jvmArgs) {
                if (arg.contains("-Xdebug") || arg.contains("-agentlib:jdwp") || arg.contains("-Xrunjdwp")) {
                    threat = "JVM Debugger attached (" + arg + ")";
                    break;
                }
            }

            // 2. Blacklisted Reverse Engineering Tools & Disassemblers
            if (threat.isEmpty()) {
                String os = System.getProperty("os.name", "").toLowerCase();
                if (os.contains("win")) {
                    String[] blacklist = {
                        "x64dbg", "x32dbg", "ida", "ida64", "cheatengine",
                        "cheatengine-x86_64", "fiddler", "httpdebugger", "httpdebuggerui",
                        "wireshark", "processhacker", "ksdumper", "dnspy", "recaf", "bytecodeviewer"
                    };

                    try {
                        Process process = Runtime.getRuntime().exec("tasklist.exe /FO CSV /NH");
                        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                        String line;
                        while ((line = reader.readLine()) != null) {
                            String lower = line.toLowerCase();
                            for (String bad : blacklist) {
                                if (lower.contains(bad)) {
                                    threat = "Forbidden tool active: " + bad;
                                    break;
                                }
                            }
                            if (!threat.isEmpty()) break;
                        }
                        reader.close();
                    } catch (Exception ignored) {}
                }
            }

            if (!threat.isEmpty()) {
                if (autoTerminate) {
                    panic(threat);
                }
                return false;
            }
            return true;
        }

        public void panic(String threat) {
            try {
                if (sessionid != null && !sessionid.isEmpty()) {
                    String hwid = get_hwid();
                    String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"message\":\"[SECURITY ALERT] " + escape(threat) + "\",\"hwid\":\"" + escape(hwid) + "\"}";
                    post("/log", json);
                }
            } catch (Exception ignored) {}

            System.err.println("\n[FATAL SECURITY EXCEPTION] Tamper detected: " + threat);
            System.exit(1);
        }

        // ======================================================
        // Core Authentication Operations
        // ======================================================

        /**
         * Initialize secure handshake and obtain session token
         */
        public void init() {
            check_security(true);

            String hwid = get_hwid();
            String json = "{\"name\":\"" + escape(name) + "\",\"ownerid\":\"" + escape(ownerid) + "\",\"secret\":\"" + escape(secret) + "\",\"version\":\"" + escape(version) + "\",\"hwid\":\"" + escape(hwid) + "\"}";
            String res = post("/init", json);
            parse_response(res);

            if (response.success) {
                sessionid = extract_json_value(res, "sessionid");
                enckey = extract_json_value(res, "enckey");
            }
        }

        /**
         * Authenticate directly with a License Key
         */
        public void license(String key) {
            check_security(true);

            if (sessionid == null || sessionid.isEmpty()) {
                response.success = false;
                response.message = "Session not initialized. Call init() first.";
                return;
            }

            String hwid = get_hwid();
            String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"key\":\"" + escape(key) + "\",\"hwid\":\"" + escape(hwid) + "\"}";
            String res = post("/license", json);
            parse_response(res);

            if (response.success) {
                parse_user(res);
            }
        }

        /**
         * Login with Username and Password
         */
        public void login(String username, String password) {
            check_security(true);

            if (sessionid == null || sessionid.isEmpty()) {
                response.success = false;
                response.message = "Session not initialized. Call init() first.";
                return;
            }

            String hwid = get_hwid();
            String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"username\":\"" + escape(username) + "\",\"password\":\"" + escape(password) + "\",\"hwid\":\"" + escape(hwid) + "\"}";
            String res = post("/login", json);
            parse_response(res);

            if (response.success) {
                parse_user(res);
            }
        }

        /**
         * Register user account with license key
         */
        public void register(String username, String password, String key) {
            check_security(true);

            if (sessionid == null || sessionid.isEmpty()) {
                response.success = false;
                response.message = "Session not initialized. Call init() first.";
                return;
            }

            String hwid = get_hwid();
            String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"username\":\"" + escape(username) + "\",\"password\":\"" + escape(password) + "\",\"key\":\"" + escape(key) + "\",\"hwid\":\"" + escape(hwid) + "\"}";
            String res = post("/register", json);
            parse_response(res);

            if (response.success) {
                parse_user(res);
            }
        }

        /**
         * Upgrade an existing user subscription using a license key
         */
        public void upgrade(String username, String key) {
            check_security(true);

            if (sessionid == null || sessionid.isEmpty()) {
                response.success = false;
                response.message = "Session not initialized. Call init() first.";
                return;
            }

            String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"username\":\"" + escape(username) + "\",\"key\":\"" + escape(key) + "\"}";
            String res = post("/upgrade", json);
            parse_response(res);
        }

        /**
         * Heartbeat session verification
         */
        public boolean check() {
            check_security(true);

            if (sessionid == null || sessionid.isEmpty()) return false;
            String json = "{\"sessionid\":\"" + escape(sessionid) + "\"}";
            String res = post("/check", json);
            parse_response(res);
            return response.success;
        }

        /**
         * Fetch protected server-side cloud variable
         */
        public String var(String varid) {
            check_security(true);

            if (sessionid == null || sessionid.isEmpty()) return "";
            String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"varid\":\"" + escape(varid) + "\"}";
            String res = post("/var", json);
            parse_response(res);
            if (response.success) {
                return extract_json_value(res, "response");
            }
            return "";
        }

        /**
         * Download secure encrypted binary payload into memory bytes
         */
        public byte[] file(String fileid) {
            check_security(true);

            if (sessionid == null || sessionid.isEmpty()) return new byte[0];
            String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"fileid\":\"" + escape(fileid) + "\"}";
            String res = post("/file", json);
            parse_response(res);

            if (response.success) {
                String raw = extract_json_value(res, "contents");
                try {
                    return Base64.getDecoder().decode(raw);
                } catch (Exception e) {
                    return raw.getBytes(StandardCharsets.UTF_8);
                }
            }
            return new byte[0];
        }

        /**
         * Dispatch client telemetry log to enclave
         */
        public void log(String message) {
            if (sessionid == null || sessionid.isEmpty()) return;
            String hwid = get_hwid();
            String json = "{\"sessionid\":\"" + escape(sessionid) + "\",\"message\":\"" + escape(message) + "\",\"hwid\":\"" + escape(hwid) + "\"}";
            post("/log", json);
        }

        // ======================================================
        // Hardware Identification (HWID) Engine
        // ======================================================

        public static String get_hwid() {
            String os = System.getProperty("os.name", "").toLowerCase();
            try {
                if (os.contains("win")) {
                    Process process = Runtime.getRuntime().exec("reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography /v MachineGuid");
                    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (line.contains("MachineGuid")) {
                            String[] parts = line.trim().split("\\s+");
                            if (parts.length >= 3) {
                                reader.close();
                                return parts[parts.length - 1];
                            }
                        }
                    }
                    reader.close();
                } else if (os.contains("mac")) {
                    Process process = Runtime.getRuntime().exec("ioreg -rd1 -c IOPlatformExpertDevice");
                    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (line.contains("IOPlatformUUID")) {
                            String[] parts = line.split("=");
                            if (parts.length > 1) {
                                reader.close();
                                return parts[1].replace("\"", "").trim();
                            }
                        }
                    }
                    reader.close();
                } else if (os.contains("nix") || os.contains("nux")) {
                    File machineId = new File("/etc/machine-id");
                    if (machineId.exists()) {
                        BufferedReader br = new BufferedReader(new FileReader(machineId));
                        String id = br.readLine();
                        br.close();
                        if (id != null && !id.trim().isEmpty()) return id.trim();
                    }
                }
            } catch (Exception ignored) {}

            // Fallback composite deterministic fingerprint
            try {
                String raw = System.getProperty("user.name") + ":" + System.getProperty("os.arch") + ":" + System.getenv("COMPUTERNAME");
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                byte[] hash = md.digest(raw.getBytes(StandardCharsets.UTF_8));
                StringBuilder sb = new StringBuilder();
                for (byte b : hash) {
                    sb.append(String.format("%02x", b));
                }
                return sb.substring(0, 32);
            } catch (Exception ignored) {}

            return "HWID_FALLBACK_" + System.getProperty("user.name");
        }

        // ======================================================
        // HTTP Client & JSON Parser (Zero Dependencies)
        // ======================================================

        private String post(String endpoint, String jsonPayload) {
            HttpURLConnection conn = null;
            try {
                URL targetUrl = new URL(this.url + endpoint);
                conn = (HttpURLConnection) targetUrl.openConnection();
                conn.setRequestMethod("POST");
                conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
                conn.setRequestProperty("Accept", "application/json");
                conn.setRequestProperty("User-Agent", "BlackAuth-Java-SDK/1.2");
                conn.setConnectTimeout(6000);
                conn.setReadTimeout(8000);
                conn.setDoOutput(true);

                byte[] out = jsonPayload.getBytes(StandardCharsets.UTF_8);
                try (OutputStream os = conn.getOutputStream()) {
                    os.write(out);
                    os.flush();
                }

                int code = conn.getResponseCode();
                InputStream is = (code >= 200 && code < 400) ? conn.getInputStream() : conn.getErrorStream();
                if (is == null) return "{\"success\":false,\"message\":\"Empty server response\"}";

                BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
                StringBuilder responseBuilder = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    responseBuilder.append(line);
                }
                reader.close();
                return responseBuilder.toString();

            } catch (Exception e) {
                return "{\"success\":false,\"message\":\"Connection error: " + escape(e.getMessage()) + "\"}";
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }
        }

        private void parse_response(String json) {
            response.success = json.contains("\"success\":true");
            response.message = extract_json_value(json, "message");
            response.code = extract_json_value(json, "code");
        }

        private void parse_user(String json) {
            user_data.username = extract_json_value(json, "username");
            user_data.ip = extract_json_value(json, "ip");
            user_data.hwid = extract_json_value(json, "hwid");
            user_data.createdate = extract_json_value(json, "createdate");
            user_data.lastlogin = extract_json_value(json, "lastlogin");

            String sub = extract_json_value(json, "subscription");
            String exp = extract_json_value(json, "expiry");
            user_data.subscriptions.clear();
            if (!sub.isEmpty()) {
                SubscriptionData sd = new SubscriptionData();
                sd.subscription = sub;
                sd.expiry = exp.isEmpty() ? "Lifetime" : exp;
                user_data.subscriptions.add(sd);
            }
        }

        private String extract_json_value(String json, String key) {
            try {
                String pattern = "\"" + key + "\":\"";
                int start = json.indexOf(pattern);
                if (start != -1) {
                    start += pattern.length();
                    int end = json.indexOf("\"", start);
                    if (end != -1) {
                        return json.substring(start, end);
                    }
                }

                // Check boolean or number
                pattern = "\"" + key + "\":";
                start = json.indexOf(pattern);
                if (start != -1) {
                    start += pattern.length();
                    int end = json.indexOf(",", start);
                    if (end == -1) end = json.indexOf("}", start);
                    if (end != -1) {
                        return json.substring(start, end).trim();
                    }
                }
            } catch (Exception ignored) {}
            return "";
        }

        private String escape(String s) {
            if (s == null) return "";
            return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r");
        }
    }

    // ==========================================================
    // Interactive Console Example / Standalone Test Runner
    // ==========================================================
    public static void main(String[] args) {
        System.out.println("==================================================");
        System.out.println("   BlackAuth Java SDK - Sentinel Licensing Engine  ");
        System.out.println("==================================================");

        // Replace with your credentials from BlackAuth Console
        Api authApp = new Api(
            "ApexGuard",                      // Application Name
            "cbA9CmQzWf",                     // Owner ID
            "sec_live_3849fbc80129",           // App Secret
            "1.0",                            // Version
            "https://blackauth.online/api/v1" // Endpoint
        );

        System.out.println("[*] Initializing Enclave Handshake...");
        authApp.init();

        if (!authApp.response.success) {
            System.err.println("[-] Initialization Failed: " + authApp.response.message);
            return;
        }

        System.out.println("[+] Handshake OK! Session: " + authApp.sessionid);
        System.out.println("[*] Machine HWID: " + Api.get_hwid());

        Scanner scanner = new Scanner(System.in);
        System.out.println("\nSelect Authentication Mode:");
        System.out.println("[1] License Key Login");
        System.out.println("[2] User / Pass Login");
        System.out.println("[3] Register New Account");
        System.out.print("> Choice: ");

        String choice = scanner.nextLine().trim();

        if ("1".equals(choice)) {
            System.out.print("Enter License Key: ");
            String key = scanner.nextLine().trim();
            authApp.license(key);
        } else if ("2".equals(choice)) {
            System.out.print("Username: ");
            String u = scanner.nextLine().trim();
            System.out.print("Password: ");
            String p = scanner.nextLine().trim();
            authApp.login(u, p);
        } else if ("3".equals(choice)) {
            System.out.print("Username: ");
            String u = scanner.nextLine().trim();
            System.out.print("Password: ");
            String p = scanner.nextLine().trim();
            System.out.print("License Key: ");
            String k = scanner.nextLine().trim();
            authApp.register(u, p, k);
        }

        if (authApp.response.success) {
            System.out.println("\n[+] SUCCESS: " + authApp.response.message);
            System.out.println("[+] User: " + authApp.user_data.username);
            System.out.println("[+] HWID: " + authApp.user_data.hwid);
            if (!authApp.user_data.subscriptions.isEmpty()) {
                System.out.println("[+] Sub: " + authApp.user_data.subscriptions.get(0).subscription + " (Expires: " + authApp.user_data.subscriptions.get(0).expiry + ")");
            }

            // Test cloud variable
            String testVar = authApp.var("cheat_version");
            if (!testVar.isEmpty()) {
                System.out.println("[+] Cloud Variable: " + testVar);
            }
        } else {
            System.err.println("\n[-] Authentication Failed: " + authApp.response.message);
        }
        scanner.close();
    }
}
