"""Helper operations for exploit mitigation analyzer."""

from __future__ import annotations

from typing import Any

from ..domain.services.exploit_mitigation import (
    build_authenticode_entry,
    build_entry_point_vulnerability,
    build_pe_info,
    build_relocations_vulnerability,
    build_stack_cookie_entry,
)


def check_stack_cookies(analyzer: Any, result: dict[str, Any], *, logger: Any) -> None:
    try:
        if result.get("load_config", {}).get("security_cookie"):
            result["mitigations"]["Stack_Cookies"] = analyzer._stack_cookie_entry(
                enabled=True,
                cookie=result["load_config"]["security_cookie"],
            )
            return
        if analyzer._has_security_cookie_imports():
            result["mitigations"]["Stack_Cookies"] = analyzer._stack_cookie_entry(
                enabled=True,
                note="Security cookie imports found",
            )
            return
        indicator = analyzer._find_gs_indicator()
        if indicator:
            result["mitigations"]["Stack_Cookies"] = analyzer._stack_cookie_entry(
                enabled=True,
                note=f"GS indicator found: {indicator}",
            )
            return
        result["mitigations"]["Stack_Cookies"] = analyzer._stack_cookie_entry(
            enabled=False,
            note="No stack cookie protection detected",
        )
    except Exception as exc:
        logger.error("Error checking stack cookies: %s", exc)


def has_security_cookie_imports(imports: list[dict[str, Any]] | None) -> bool:
    if not imports:
        return False
    for imp in imports:
        name = imp.get("name", "").lower()
        if "__security_cookie" in name or "__security_init_cookie" in name:
            return True
    return False


def find_gs_indicator(strings: list[dict[str, Any]] | None) -> str | None:
    if not strings:
        return None
    gs_indicators = ["__GSHandlerCheck", "__security_check_cookie", "/GS"]
    for s in strings[:100]:
        string_val = s.get("string", "")
        for indicator in gs_indicators:
            if indicator in string_val:
                return indicator
    return None


def check_authenticode(analyzer: Any, result: dict[str, Any], *, logger: Any) -> None:
    try:
        data_dirs = analyzer._cmdj("iDj", [])
        if not data_dirs or not isinstance(data_dirs, list):
            result["mitigations"]["Authenticode"] = build_authenticode_entry(
                enabled=False,
                note="No data directories",
            )
            return
        for dd in data_dirs:
            if isinstance(dd, dict) and dd.get("name") == "SECURITY" and dd.get("vaddr", 0) != 0:
                result["mitigations"]["Authenticode"] = build_authenticode_entry(
                    enabled=True,
                    note="Certificate table present",
                    size=dd.get("size", 0),
                )
                return
        result["mitigations"]["Authenticode"] = build_authenticode_entry(
            enabled=False,
            note="No certificate table found",
        )
    except Exception as exc:
        logger.error("Error checking Authenticode: %s", exc)


def check_pe_security_features(analyzer: Any, result: dict[str, Any], *, logger: Any) -> None:
    try:
        pe_header = analyzer._get_pe_header()
        if not pe_header:
            return
        characteristics = pe_header.get("characteristics", 0)
        is_dll = bool(characteristics & 0x2000)
        vulnerability = build_relocations_vulnerability(
            bool(result["mitigations"].get("ASLR", {}).get("enabled")),
            characteristics,
        )
        if vulnerability:
            result["vulnerabilities"].append(vulnerability)
        optional_header = analyzer._cmdj("iHj", {})
        if optional_header and isinstance(optional_header, dict):
            pe_info = build_pe_info(optional_header, is_dll)
            if pe_info:
                result["pe_info"] = pe_info
            entry_point = optional_header.get("entry_point", 0)
            image_base = optional_header.get("image_base", 0)
            sections = analyzer._get_sections()
            if sections and isinstance(sections, list) and entry_point > 0:
                entry_rva = entry_point - image_base if entry_point > image_base else entry_point
                entry_in_exec_section = analyzer._entry_point_in_exec_section(sections, entry_rva)
                vulnerability = build_entry_point_vulnerability(entry_in_exec_section)
                if vulnerability:
                    result["vulnerabilities"].append(vulnerability)
    except Exception as exc:
        logger.error("Error checking PE security features: %s", exc)


def stack_cookie_entry(
    enabled: bool, cookie: str | None = None, note: str | None = None
) -> dict[str, Any]:
    return build_stack_cookie_entry(enabled=enabled, cookie=cookie, note=note)
