package com.xebyte.core;

import ghidra.program.model.address.Address;
import ghidra.program.model.data.StringDataType;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.model.symbol.ReferenceManager;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolIterator;
import ghidra.program.model.symbol.SymbolTable;

import java.util.*;
import java.util.regex.Pattern;

/**
 * Service for malware analysis and security operations: anti-analysis detection,
 * API call chain analysis, IOC extraction, and malware behavior detection.
 * Extracted from GhidraMCPPlugin as part of v4.0.0 refactor.
 */
@McpToolGroup(value = "malware", description = "Anti-analysis detection, suspicious instructions, IOC extraction")
public class MalwareSecurityService {

    private final ProgramProvider programProvider;
    private final ThreadingStrategy threadingStrategy;

    public MalwareSecurityService(ProgramProvider programProvider, ThreadingStrategy threadingStrategy) {
        this.programProvider = programProvider;
        this.threadingStrategy = threadingStrategy;
    }

    // ========================================================================
    // Inner classes
    // ========================================================================

    /**
     * Helper class for threat pattern definitions
     */
    private static class ThreatPattern {
        String id;
        String name;
        String severity;
        String[] apis;
        String description;

        ThreatPattern(String id, String name, String severity, String[] apis, String description) {
            this.id = id;
            this.name = name;
            this.severity = severity;
            this.apis = apis;
            this.description = description;
        }
    }

    // ========================================================================
    // Public endpoint methods
    // ========================================================================

    /**
     * Detect anti-analysis and anti-debugging techniques
     * Scans for known anti-debug APIs, timing checks, VM detection, and SEH tricks
     */
    public Response findAntiAnalysisTechniques() {
        return findAntiAnalysisTechniques(null);
    }

    @McpTool(path = "/find_anti_analysis_techniques", description = "Detect anti-analysis and anti-debug techniques", category = "malware")
    public Response findAntiAnalysisTechniques(
            @Param(value = "program", description = "Target program name (omit to use the active program — always specify when multiple programs are open)", defaultValue = "") String programName) {
        ServiceUtils.ProgramOrError pe = ServiceUtils.getProgramOrError(programProvider, programName);
        if (pe.hasError()) return pe.error();
        Program program = pe.program();

        try {
            // Define patterns to search for
            Map<String, String[]> antiDebugAPIs = new LinkedHashMap<>();
            antiDebugAPIs.put("debugger_detection", new String[]{
                "IsDebuggerPresent", "CheckRemoteDebuggerPresent", "NtQueryInformationProcess",
                "OutputDebugString", "DebugActiveProcess", "CloseHandle", "NtClose"
            });
            antiDebugAPIs.put("timing_checks", new String[]{
                "GetTickCount", "GetTickCount64", "QueryPerformanceCounter",
                "GetSystemTimeAsFileTime", "timeGetTime", "NtQuerySystemTime"
            });
            antiDebugAPIs.put("process_enumeration", new String[]{
                "CreateToolhelp32Snapshot", "Process32First", "Process32Next",
                "EnumProcesses", "NtQuerySystemInformation", "OpenProcess"
            });
            antiDebugAPIs.put("vm_detection", new String[]{
                "GetSystemFirmwareTable", "EnumSystemFirmwareTable",
                "WMI", "SMBIOS", "ACPI"
            });
            antiDebugAPIs.put("exception_based", new String[]{
                "SetUnhandledExceptionFilter", "AddVectoredExceptionHandler",
                "RtlAddVectoredExceptionHandler", "NtSetInformationThread"
            });
            antiDebugAPIs.put("memory_checks", new String[]{
                "VirtualQuery", "NtQueryVirtualMemory", "ReadProcessMemory",
                "WriteProcessMemory"
            });

            // Instruction patterns to detect
            String[] suspiciousInstructions = {"RDTSC", "CPUID", "INT 3", "INT 0x2d", "SIDT", "SGDT", "SLDT", "STR"};

            List<Map<String, Object>> findings = new ArrayList<>();
            FunctionManager functionManager = program.getFunctionManager();
            SymbolTable symbolTable = program.getSymbolTable();
            Listing listing = program.getListing();

            // Scan for API calls
            for (Map.Entry<String, String[]> category : antiDebugAPIs.entrySet()) {
                String categoryName = category.getKey();
                for (String apiName : category.getValue()) {
                    // Search for symbols matching the API name
                    SymbolIterator symbols = symbolTable.getSymbolIterator("*" + apiName + "*", true);
                    while (symbols.hasNext()) {
                        Symbol sym = symbols.next();
                        // Find references to this symbol
                        ReferenceManager refManager = program.getReferenceManager();
                        ReferenceIterator refs = refManager.getReferencesTo(sym.getAddress());
                        while (refs.hasNext()) {
                            Reference ref = refs.next();
                            if (ref.getReferenceType().isCall()) {
                                Function callingFunc = functionManager.getFunctionContaining(ref.getFromAddress());
                                Map<String, Object> finding = new LinkedHashMap<>();
                                finding.put("category", categoryName);
                                finding.put("technique", apiName);
                                finding.putAll(ServiceUtils.addressToJson(ref.getFromAddress(), program));
                                finding.put("function", callingFunc != null ? callingFunc.getName() : "unknown");
                                finding.put("severity", getSeverity(categoryName));
                                findings.add(finding);
                            }
                        }
                    }
                }
            }

            // Scan for suspicious instructions
            for (Function func : functionManager.getFunctions(true)) {
                InstructionIterator instrIter = listing.getInstructions(func.getBody(), true);
                while (instrIter.hasNext()) {
                    Instruction instr = instrIter.next();
                    String mnemonic = instr.getMnemonicString().toUpperCase();

                    for (String suspicious : suspiciousInstructions) {
                        if (mnemonic.contains(suspicious.split(" ")[0])) {
                            Map<String, Object> instrFinding = new LinkedHashMap<>();
                            instrFinding.put("category", "suspicious_instruction");
                            instrFinding.put("technique", suspicious);
                            instrFinding.putAll(ServiceUtils.addressToJson(instr.getAddress(), program));
                            instrFinding.put("function", func.getName());
                            instrFinding.put("instruction", instr.toString());
                            instrFinding.put("severity", "medium");
                            findings.add(instrFinding);
                        }
                    }
                }
            }

            // Check for PEB access patterns (common anti-debug)
            for (Function func : functionManager.getFunctions(true)) {
                InstructionIterator instrIter = listing.getInstructions(func.getBody(), true);
                boolean foundFsAccess = false;
                while (instrIter.hasNext()) {
                    Instruction instr = instrIter.next();
                    String instrStr = instr.toString().toUpperCase();
                    // FS:[0x30] is PEB access, FS:[0x18] is TEB
                    if (instrStr.contains("FS:") && (instrStr.contains("0X30") || instrStr.contains("0X18"))) {
                        if (!foundFsAccess) {
                            Map<String, Object> pebFinding = new LinkedHashMap<>();
                            pebFinding.put("category", "peb_teb_access");
                            pebFinding.put("technique", "Direct PEB/TEB access");
                            pebFinding.putAll(ServiceUtils.addressToJson(instr.getAddress(), program));
                            pebFinding.put("function", func.getName());
                            pebFinding.put("instruction", instr.toString());
                            pebFinding.put("severity", "high");
                            pebFinding.put("description", "Direct access to PEB/TEB can be used to detect debuggers");
                            findings.add(pebFinding);
                            foundFsAccess = true;
                        }
                    }
                }
            }

            // Count by category
            Map<String, Integer> categoryCounts = new LinkedHashMap<>();
            Map<String, Integer> severityCounts = new LinkedHashMap<>();
            for (Map<String, Object> finding : findings) {
                String cat = (String) finding.get("category");
                String sev = (String) finding.get("severity");
                categoryCounts.put(cat, categoryCounts.getOrDefault(cat, 0) + 1);
                severityCounts.put(sev, severityCounts.getOrDefault(sev, 0) + 1);
            }

            // Truncate findings to 100
            List<Map<String, Object>> truncatedFindings = findings.size() > 100
                ? new ArrayList<>(findings.subList(0, 100))
                : findings;

            if (findings.size() > 100) {
                truncatedFindings.add(JsonHelper.mapOf("note", (findings.size() - 100) + " additional findings truncated"));
            }

            return Response.ok(JsonHelper.mapOf(
                "total_findings", findings.size(),
                "summary", JsonHelper.mapOf(
                    "by_category", categoryCounts,
                    "by_severity", severityCounts
                ),
                "findings", truncatedFindings
            ));
        } catch (Exception e) {
            return Response.err(e.getMessage());
        }
    }

    /**
     * Automatically identify and decrypt obfuscated strings
     */
    public Response autoDecryptStrings() {
        return autoDecryptStrings(null);
    }

    public Response autoDecryptStrings(String programName) {
        ServiceUtils.ProgramOrError pe = ServiceUtils.getProgramOrError(programProvider, programName);
        if (pe.hasError()) return pe.error();

        try {
            // Placeholder implementation
            // Full implementation would detect and decrypt:
            // - XOR-encoded strings
            // - Base64-encoded strings
            // - ROT13 encoding
            // - Stack strings
            // - RC4/AES encrypted strings

            List<Map<String, Object>> results = new ArrayList<>();
            results.add(JsonHelper.mapOf(
                "method", "String Decryption",
                "status", "Not yet implemented",
                "note", "This endpoint requires pattern detection and decryption of various encoding schemes"
            ));
            return Response.ok(results);
        } catch (Exception e) {
            return Response.err(e.getMessage());
        }
    }

    /**
     * Identify and analyze suspicious API call chains
     * Detects threat patterns like process injection, persistence, credential theft
     */
    public Response analyzeAPICallChains() {
        return analyzeAPICallChains(null);
    }

    @McpTool(path = "/analyze_api_call_chains", description = "Detect suspicious API call patterns", category = "malware")
    public Response analyzeAPICallChains(
            @Param(value = "program", defaultValue = "") String programName) {
        ServiceUtils.ProgramOrError pe = ServiceUtils.getProgramOrError(programProvider, programName);
        if (pe.hasError()) return pe.error();
        Program program = pe.program();

        try {
            // Define threat patterns as API call sequences
            List<ThreatPattern> threatPatterns = new ArrayList<>();

            // Process Injection patterns
            threatPatterns.add(new ThreatPattern("process_injection_classic",
                "Classic Process Injection", "critical",
                new String[]{"VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread"},
                "Allocates memory in remote process, writes code, and creates thread to execute"));

            threatPatterns.add(new ThreatPattern("process_injection_ntapi",
                "NT API Process Injection", "critical",
                new String[]{"NtOpenProcess", "NtAllocateVirtualMemory", "NtWriteVirtualMemory", "NtCreateThreadEx"},
                "Process injection using NT native APIs"));

            threatPatterns.add(new ThreatPattern("process_hollowing",
                "Process Hollowing", "critical",
                new String[]{"CreateProcess", "NtUnmapViewOfSection", "VirtualAllocEx", "WriteProcessMemory", "SetThreadContext", "ResumeThread"},
                "Creates suspended process, hollows it out, and replaces with malicious code"));

            threatPatterns.add(new ThreatPattern("dll_injection",
                "DLL Injection", "high",
                new String[]{"OpenProcess", "VirtualAllocEx", "WriteProcessMemory", "LoadLibrary"},
                "Injects DLL into remote process"));

            // Persistence patterns
            threatPatterns.add(new ThreatPattern("registry_persistence",
                "Registry Persistence", "high",
                new String[]{"RegOpenKey", "RegSetValue"},
                "Modifies registry for persistence"));

            threatPatterns.add(new ThreatPattern("service_persistence",
                "Service Persistence", "high",
                new String[]{"OpenSCManager", "CreateService"},
                "Creates Windows service for persistence"));

            threatPatterns.add(new ThreatPattern("scheduled_task",
                "Scheduled Task Persistence", "high",
                new String[]{"CoCreateInstance", "ITaskScheduler"},
                "Creates scheduled task for persistence"));

            // Credential theft patterns
            threatPatterns.add(new ThreatPattern("lsass_access",
                "LSASS Memory Access", "critical",
                new String[]{"OpenProcess", "ReadProcessMemory"},
                "May be accessing LSASS for credential extraction"));

            threatPatterns.add(new ThreatPattern("sam_access",
                "SAM Database Access", "critical",
                new String[]{"RegOpenKey", "SAM"},
                "May be accessing SAM database for password hashes"));

            // Network patterns
            threatPatterns.add(new ThreatPattern("socket_communication",
                "Network Communication", "medium",
                new String[]{"WSAStartup", "socket", "connect", "send", "recv"},
                "Establishes network connection"));

            threatPatterns.add(new ThreatPattern("http_communication",
                "HTTP Communication", "medium",
                new String[]{"InternetOpen", "InternetConnect", "HttpOpenRequest"},
                "Performs HTTP communication"));

            // File operations
            threatPatterns.add(new ThreatPattern("file_encryption",
                "Potential Ransomware", "critical",
                new String[]{"FindFirstFile", "FindNextFile", "CryptEncrypt"},
                "File enumeration combined with encryption"));

            // Analyze functions for these patterns
            FunctionManager functionManager = program.getFunctionManager();
            SymbolTable symbolTable = program.getSymbolTable();
            ReferenceManager refManager = program.getReferenceManager();

            List<Map<String, Object>> detectedPatterns = new ArrayList<>();

            // Build API call map per function
            Map<Function, Set<String>> functionAPIs = new LinkedHashMap<>();

            for (Function func : functionManager.getFunctions(true)) {
                if (func.isThunk()) continue;

                Set<String> apis = new HashSet<>();
                Listing listing = program.getListing();
                InstructionIterator instrIter = listing.getInstructions(func.getBody(), true);

                while (instrIter.hasNext()) {
                    Instruction instr = instrIter.next();
                    if (instr.getFlowType().isCall()) {
                        for (Reference ref : refManager.getReferencesFrom(instr.getAddress())) {
                            if (ref.getReferenceType().isCall()) {
                                Symbol sym = symbolTable.getPrimarySymbol(ref.getToAddress());
                                if (sym != null) {
                                    apis.add(sym.getName());
                                }
                            }
                        }
                    }
                }

                if (!apis.isEmpty()) {
                    functionAPIs.put(func, apis);
                }
            }

            // Check each function against threat patterns
            for (Map.Entry<Function, Set<String>> entry : functionAPIs.entrySet()) {
                Function func = entry.getKey();
                Set<String> apis = entry.getValue();

                for (ThreatPattern pattern : threatPatterns) {
                    int matchCount = 0;
                    List<String> matchedAPIs = new ArrayList<>();

                    for (String requiredAPI : pattern.apis) {
                        for (String funcAPI : apis) {
                            if (funcAPI.toLowerCase().contains(requiredAPI.toLowerCase())) {
                                matchCount++;
                                matchedAPIs.add(funcAPI);
                                break;
                            }
                        }
                    }

                    // Require at least half of the pattern APIs to match
                    if (matchCount >= Math.ceil(pattern.apis.length / 2.0) && matchCount >= 2) {
                        double confidence = (double) matchCount / pattern.apis.length;

                        Map<String, Object> patternItem = new LinkedHashMap<>();
                        patternItem.put("pattern_id", pattern.id);
                        patternItem.put("pattern_name", pattern.name);
                        patternItem.put("severity", pattern.severity);
                        patternItem.put("function", func.getName());
                        patternItem.putAll(ServiceUtils.addressToJson(func.getEntryPoint(), program));
                        patternItem.put("confidence", Math.round(confidence * 100.0) / 100.0);
                        patternItem.put("matched_apis", matchedAPIs);
                        patternItem.put("description", pattern.description);
                        detectedPatterns.add(patternItem);
                    }
                }
            }

            // Sort by severity and confidence
            detectedPatterns.sort((a, b) -> {
                int sevCompare = getSeverityRank((String)a.get("severity")) - getSeverityRank((String)b.get("severity"));
                if (sevCompare != 0) return sevCompare;
                return Double.compare((Double)b.get("confidence"), (Double)a.get("confidence"));
            });

            // Count by severity
            Map<String, Integer> sevCounts = new LinkedHashMap<>();
            for (Map<String, Object> det : detectedPatterns) {
                String sev = (String) det.get("severity");
                sevCounts.put(sev, sevCounts.getOrDefault(sev, 0) + 1);
            }

            // Truncate to 50
            List<Map<String, Object>> truncatedPatterns = detectedPatterns.size() > 50
                ? detectedPatterns.subList(0, 50)
                : detectedPatterns;

            return Response.ok(JsonHelper.mapOf(
                "total_patterns_detected", detectedPatterns.size(),
                "severity_summary", sevCounts,
                "detected_patterns", truncatedPatterns
            ));
        } catch (Exception e) {
            return Response.err(e.getMessage());
        }
    }

    /**
     * Enhanced IOC extraction with context and confidence scoring
     */
    public Response extractIOCsWithContext() {
        return extractIOCsWithContext(null);
    }

    @McpTool(path = "/extract_iocs_with_context", description = "Enhanced IOC extraction with context", category = "malware")
    public Response extractIOCsWithContext(
            @Param(value = "program", defaultValue = "") String programName) {
        ServiceUtils.ProgramOrError pe = ServiceUtils.getProgramOrError(programProvider, programName);
        if (pe.hasError()) return pe.error();
        Program program = pe.program();

        try {
            List<Map<String, Object>> iocs = new ArrayList<>();
            Listing listing = program.getListing();
            FunctionManager functionManager = program.getFunctionManager();

            // Regex patterns for IOC extraction
            Pattern ipv4Pattern = Pattern.compile("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b");
            Pattern urlPattern = Pattern.compile("https?://[\\w\\-._~:/?#\\[\\]@!$&'()*+,;=%]+", Pattern.CASE_INSENSITIVE);
            Pattern domainPattern = Pattern.compile("\\b[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]\\.[a-zA-Z]{2,}\\b");
            Pattern emailPattern = Pattern.compile("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
            Pattern registryPattern = Pattern.compile("(HKEY_[A-Z_]+|HKLM|HKCU|HKCR|HKU|HKCC)\\\\[\\w\\\\]+", Pattern.CASE_INSENSITIVE);
            Pattern filePathPattern = Pattern.compile("([a-zA-Z]:\\\\[^\"<>|*?\\n]+|\\\\\\\\[\\w.]+\\\\[^\"<>|*?\\n]+)");
            Pattern bitcoinPattern = Pattern.compile("\\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\\b");
            Pattern md5Pattern = Pattern.compile("\\b[a-fA-F0-9]{32}\\b");
            Pattern sha256Pattern = Pattern.compile("\\b[a-fA-F0-9]{64}\\b");

            // Scan defined strings
            DataIterator dataIter = listing.getDefinedData(true);
            while (dataIter.hasNext()) {
                Data data = dataIter.next();
                if (data.getDataType() instanceof StringDataType ||
                    data.getDataType().getName().toLowerCase().contains("string")) {

                    Object value = data.getValue();
                    if (value != null) {
                        String strValue = value.toString();
                        Address addr = data.getAddress();

                        // Find containing function for context
                        Function containingFunc = functionManager.getFunctionContaining(addr);
                        String funcContext = containingFunc != null ? containingFunc.getName() : "global";

                        // Check each pattern
                        checkAndAddIOC(iocs, strValue, ipv4Pattern, "ipv4", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, urlPattern, "url", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, domainPattern, "domain", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, emailPattern, "email", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, registryPattern, "registry_key", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, filePathPattern, "file_path", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, bitcoinPattern, "bitcoin_address", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, md5Pattern, "md5_hash", addr, funcContext, program);
                        checkAndAddIOC(iocs, strValue, sha256Pattern, "sha256_hash", addr, funcContext, program);
                    }
                }
            }

            // Calculate confidence scores
            for (Map<String, Object> ioc : iocs) {
                double confidence = calculateIOCConfidence(ioc, program);
                ioc.put("confidence", Math.round(confidence * 100.0) / 100.0);
            }

            // Sort by confidence descending
            iocs.sort((a, b) -> Double.compare((Double)b.get("confidence"), (Double)a.get("confidence")));

            // Summary by type
            Map<String, Integer> typeCounts = new LinkedHashMap<>();
            for (Map<String, Object> ioc : iocs) {
                String type = (String) ioc.get("type");
                typeCounts.put(type, typeCounts.getOrDefault(type, 0) + 1);
            }

            // Truncate to 100
            List<Map<String, Object>> truncatedIOCs = iocs.size() > 100
                ? new ArrayList<>(iocs.subList(0, 100))
                : iocs;

            if (iocs.size() > 100) {
                truncatedIOCs.add(JsonHelper.mapOf("note", (iocs.size() - 100) + " additional IOCs truncated"));
            }

            return Response.ok(JsonHelper.mapOf(
                "total_iocs", iocs.size(),
                "by_type", typeCounts,
                "iocs", truncatedIOCs
            ));
        } catch (Exception e) {
            return Response.err(e.getMessage());
        }
    }

    /**
     * Detect common malware behaviors and techniques
     */
    public Response detectMalwareBehaviors() {
        return detectMalwareBehaviors(null);
    }

    @McpTool(path = "/detect_malware_behaviors", description = "Detect common malware behaviors", category = "malware")
    public Response detectMalwareBehaviors(
            @Param(value = "program", defaultValue = "") String programName) {
        ServiceUtils.ProgramOrError pe = ServiceUtils.getProgramOrError(programProvider, programName);
        if (pe.hasError()) return pe.error();
        Program program = pe.program();

        try {
            List<Map<String, Object>> behaviors = new ArrayList<>();
            FunctionManager functionManager = program.getFunctionManager();
            SymbolTable symbolTable = program.getSymbolTable();
            ReferenceManager refManager = program.getReferenceManager();
            Listing listing = program.getListing();

            // Define behavior categories and their indicators
            Map<String, String[]> behaviorIndicators = new LinkedHashMap<>();

            // Code injection
            behaviorIndicators.put("code_injection", new String[]{
                "VirtualAlloc", "VirtualAllocEx", "WriteProcessMemory", "CreateRemoteThread",
                "NtWriteVirtualMemory", "RtlCreateUserThread", "QueueUserAPC"
            });

            // Keylogging
            behaviorIndicators.put("keylogging", new String[]{
                "SetWindowsHookEx", "GetAsyncKeyState", "GetKeyState", "RegisterRawInputDevices"
            });

            // Screen capture
            behaviorIndicators.put("screen_capture", new String[]{
                "GetDC", "GetWindowDC", "BitBlt", "CreateCompatibleBitmap", "GetDIBits"
            });

            // Privilege escalation
            behaviorIndicators.put("privilege_escalation", new String[]{
                "AdjustTokenPrivileges", "LookupPrivilegeValue", "OpenProcessToken",
                "ImpersonateLoggedOnUser", "DuplicateToken"
            });

            // Defense evasion
            behaviorIndicators.put("defense_evasion", new String[]{
                "NtSetInformationThread", "NtQueryInformationProcess", "GetProcAddress",
                "LoadLibrary", "VirtualProtect"
            });

            // Lateral movement
            behaviorIndicators.put("lateral_movement", new String[]{
                "WNetAddConnection", "NetShareEnum", "WNetEnumResource"
            });

            // Data exfiltration
            behaviorIndicators.put("data_exfiltration", new String[]{
                "InternetOpen", "HttpSendRequest", "FtpPutFile", "send", "WSASend"
            });

            // Cryptographic operations
            behaviorIndicators.put("crypto_operations", new String[]{
                "CryptAcquireContext", "CryptGenKey", "CryptEncrypt", "CryptDecrypt",
                "CryptImportKey", "CryptDeriveKey"
            });

            // Process manipulation
            behaviorIndicators.put("process_manipulation", new String[]{
                "TerminateProcess", "SuspendThread", "ResumeThread", "NtSuspendProcess"
            });

            // Check each function for behavior indicators
            for (Function func : functionManager.getFunctions(true)) {
                if (func.isThunk()) continue;

                Set<String> funcAPIs = new HashSet<>();
                InstructionIterator instrIter = listing.getInstructions(func.getBody(), true);

                while (instrIter.hasNext()) {
                    Instruction instr = instrIter.next();
                    if (instr.getFlowType().isCall()) {
                        for (Reference ref : refManager.getReferencesFrom(instr.getAddress())) {
                            if (ref.getReferenceType().isCall()) {
                                Symbol sym = symbolTable.getPrimarySymbol(ref.getToAddress());
                                if (sym != null) {
                                    funcAPIs.add(sym.getName());
                                }
                            }
                        }
                    }
                }

                // Check against behavior indicators
                for (Map.Entry<String, String[]> entry : behaviorIndicators.entrySet()) {
                    String behaviorType = entry.getKey();
                    String[] indicators = entry.getValue();

                    List<String> matchedIndicators = new ArrayList<>();
                    for (String indicator : indicators) {
                        for (String api : funcAPIs) {
                            if (api.toLowerCase().contains(indicator.toLowerCase())) {
                                matchedIndicators.add(api);
                            }
                        }
                    }

                    if (matchedIndicators.size() >= 2) {
                        Map<String, Object> behaviorItem = new LinkedHashMap<>();
                        behaviorItem.put("behavior_type", behaviorType);
                        behaviorItem.put("function", func.getName());
                        behaviorItem.putAll(ServiceUtils.addressToJson(func.getEntryPoint(), program));
                        behaviorItem.put("indicators", matchedIndicators);
                        behaviorItem.put("indicator_count", matchedIndicators.size());
                        behaviorItem.put("severity", getBehaviorSeverity(behaviorType));
                        behaviors.add(behaviorItem);
                    }
                }
            }

            // Sort by severity and indicator count
            behaviors.sort((a, b) -> {
                int sevCompare = getSeverityRank((String)a.get("severity")) - getSeverityRank((String)b.get("severity"));
                if (sevCompare != 0) return sevCompare;
                return (Integer)b.get("indicator_count") - (Integer)a.get("indicator_count");
            });

            // Summary by behavior type
            Map<String, Integer> behaviorCounts = new LinkedHashMap<>();
            for (Map<String, Object> behavior : behaviors) {
                String type = (String) behavior.get("behavior_type");
                behaviorCounts.put(type, behaviorCounts.getOrDefault(type, 0) + 1);
            }

            // Truncate to 100
            List<Map<String, Object>> truncatedBehaviors = behaviors.size() > 100
                ? new ArrayList<>(behaviors.subList(0, 100))
                : behaviors;

            if (behaviors.size() > 100) {
                truncatedBehaviors.add(JsonHelper.mapOf("note", (behaviors.size() - 100) + " additional behaviors truncated"));
            }

            return Response.ok(JsonHelper.mapOf(
                "total_behaviors_detected", behaviors.size(),
                "by_behavior_type", behaviorCounts,
                "behaviors", truncatedBehaviors
            ));
        } catch (Exception e) {
            return Response.err(e.getMessage());
        }
    }

    // ========================================================================
    // Private helper methods
    // ========================================================================

    /**
     * Helper to determine severity based on anti-analysis category
     */
    private String getSeverity(String category) {
        switch (category) {
            case "debugger_detection": return "high";
            case "timing_checks": return "medium";
            case "process_enumeration": return "medium";
            case "vm_detection": return "high";
            case "exception_based": return "high";
            case "memory_checks": return "low";
            default: return "medium";
        }
    }

    /**
     * Helper to rank severity for sorting
     */
    private int getSeverityRank(String severity) {
        switch (severity) {
            case "critical": return 0;
            case "high": return 1;
            case "medium": return 2;
            case "low": return 3;
            default: return 4;
        }
    }

    /**
     * Helper to check pattern and add IOC
     */
    private void checkAndAddIOC(List<Map<String, Object>> iocs, String value, Pattern pattern,
                                 String type, Address address, String funcContext, Program program) {
        java.util.regex.Matcher matcher = pattern.matcher(value);
        while (matcher.find()) {
            String match = matcher.group();
            // Skip common false positives
            if (type.equals("ipv4") && (match.startsWith("0.") || match.startsWith("255."))) continue;
            if (type.equals("domain") && match.length() < 4) continue;

            Map<String, Object> iocItem = new LinkedHashMap<>();
            iocItem.put("type", type);
            iocItem.put("value", match);
            iocItem.putAll(ServiceUtils.addressToJson(address, program));
            iocItem.put("function_context", funcContext);
            iocs.add(iocItem);
        }
    }

    /**
     * Calculate confidence score for an IOC based on context
     */
    private double calculateIOCConfidence(Map<String, Object> ioc, Program program) {
        String type = (String) ioc.get("type");
        String value = (String) ioc.get("value");
        String funcContext = (String) ioc.get("function_context");

        double confidence = 0.5; // Base confidence

        // Type-based adjustments
        switch (type) {
            case "url":
            case "ipv4":
                confidence += 0.2;
                break;
            case "registry_key":
                if (value.toLowerCase().contains("run") || value.toLowerCase().contains("services")) {
                    confidence += 0.3; // Persistence indicators
                }
                break;
            case "bitcoin_address":
                confidence += 0.4; // Strong indicator
                break;
            case "file_path":
                if (value.toLowerCase().contains("temp") || value.toLowerCase().contains("appdata")) {
                    confidence += 0.2;
                }
                break;
        }

        // Function context adjustments
        if (!funcContext.equals("global")) {
            confidence += 0.1; // IOC used in actual function
        }

        // Check for xrefs to increase confidence
        try {
            String iocAddress = (String) ioc.get("address");
            Address addr = ServiceUtils.parseAddress(program, iocAddress);
            if (addr == null) {
                return Math.min(confidence, 1.0);
            }
            ReferenceManager refManager = program.getReferenceManager();
            ReferenceIterator refs = refManager.getReferencesTo(addr);
            int refCount = 0;
            while (refs.hasNext() && refCount < 10) {
                refs.next();
                refCount++;
            }
            if (refCount > 0) {
                confidence += 0.1 * Math.min(refCount, 3);
            }
        } catch (Exception e) {
            // Ignore xref errors
        }

        return Math.min(confidence, 1.0);
    }

    /**
     * Helper to get severity for behavior type
     */
    private String getBehaviorSeverity(String behaviorType) {
        switch (behaviorType) {
            case "code_injection":
            case "privilege_escalation":
                return "critical";
            case "keylogging":
            case "lateral_movement":
            case "data_exfiltration":
                return "high";
            case "screen_capture":
            case "defense_evasion":
            case "crypto_operations":
                return "medium";
            case "process_manipulation":
                return "medium";
            default:
                return "low";
        }
    }
}
