"""Human-readable detection messages for Obol UX.

Single source of truth for translating detection flags into user language.
Both hooks and CLI commands import from here.

Zero external dependencies.
"""

# ─── Flag message catalog ─────────────────────────────────────────────────
#
# Each entry maps a detection flag to:
#   title        — short human label (shown in all modes)
#   explanation  — one-sentence plain-English explanation
#   user_severity — UX tier: CRITICAL / WARNING / INFO / FYI
#
# Every flag in detection.py FLAG_SEVERITY must have an entry here.

FLAG_MESSAGES = {
    # ── CRITICAL flags ─────────────────────────────────────────────
    "reverse_shell": {
        "title": "Reverse Shell",
        "explanation": "A command was detected that opens a network connection back to an attacker, giving them interactive shell access.",
        "user_severity": "CRITICAL",
    },
    "exfiltration_pattern": {
        "title": "Data Exfiltration Sequence",
        "explanation": "Sensitive data was accessed and then sent over the network in a short time window.",
        "user_severity": "CRITICAL",
    },
    "container_escape": {
        "title": "Container Escape",
        "explanation": "An attempt to break out of a container sandbox into the host system was detected.",
        "user_severity": "CRITICAL",
    },
    "process_injection": {
        "title": "Process Injection",
        "explanation": "Code is being injected into another running process (e.g. via ptrace or /proc/mem).",
        "user_severity": "CRITICAL",
    },
    "kernel_module_loading": {
        "title": "Kernel Module Loading",
        "explanation": "A kernel module is being loaded, which could modify core system behavior.",
        "user_severity": "CRITICAL",
    },
    "crypto_miner": {
        "title": "Cryptocurrency Miner",
        "explanation": "A cryptocurrency mining tool or configuration was detected.",
        "user_severity": "CRITICAL",
    },
    "dns_exfiltration": {
        "title": "DNS Exfiltration",
        "explanation": "Data is being encoded into DNS queries to exfiltrate it past firewalls.",
        "user_severity": "CRITICAL",
    },
    "piped_exfiltration": {
        "title": "Data Exfiltration via Pipe",
        "explanation": "Sensitive data was piped to a network tool that could send it externally.",
        "user_severity": "CRITICAL",
    },
    "variable_exfiltration": {
        "title": "Variable-Based Exfiltration",
        "explanation": "Sensitive data was captured into a variable and then sent over the network.",
        "user_severity": "CRITICAL",
    },
    "webfetch_exfiltration": {
        "title": "WebFetch Exfiltration",
        "explanation": "Data is being exfiltrated via URL parameters or encoded in a web request.",
        "user_severity": "CRITICAL",
    },
    "escape_attempt": {
        "title": "Sandbox Escape Attempt",
        "explanation": "An attempt to escape the agent's sandbox or security boundary was detected.",
        "user_severity": "CRITICAL",
    },
    "null_byte_injection": {
        "title": "Null Byte Injection",
        "explanation": "A null byte was injected into a path or command to bypass security checks.",
        "user_severity": "CRITICAL",
    },
    "data_destruction": {
        "title": "Data Destruction",
        "explanation": "A command that could destroy significant amounts of data was detected (e.g. rm -rf, disk wipe).",
        "user_severity": "CRITICAL",
    },
    "agent_self_modification": {
        "title": "Agent Self-Modification",
        "explanation": "The agent is attempting to modify its own configuration, hooks, or security settings.",
        "user_severity": "CRITICAL",
    },
    # Chain detection flags
    "chain_download_stage_exec": {
        "title": "Download-Stage-Execute Chain",
        "explanation": "A file was downloaded, staged, and then executed — a classic malware delivery pattern.",
        "user_severity": "CRITICAL",
    },
    "chain_write_execute_temp": {
        "title": "Write-Execute in Temp",
        "explanation": "A script was written to a temporary directory and then executed.",
        "user_severity": "CRITICAL",
    },
    "chain_persistence": {
        "title": "Persistence Installation Chain",
        "explanation": "A multi-step sequence was detected that installs persistent access (cron, systemd, shell rc).",
        "user_severity": "CRITICAL",
    },
    "chain_encode_exec": {
        "title": "Encode-Execute Chain",
        "explanation": "Data was encoded/obfuscated and then executed, suggesting hidden payload delivery.",
        "user_severity": "CRITICAL",
    },
    "chain_supply_chain_exec": {
        "title": "Supply Chain Execution",
        "explanation": "An untrusted package was installed and then code from it was executed.",
        "user_severity": "CRITICAL",
    },
    "chain_staged_exfiltration": {
        "title": "Staged Data Exfiltration",
        "explanation": "Data was collected, staged (archived/compressed), then sent over the network.",
        "user_severity": "CRITICAL",
    },
    "chain_privilege_persist": {
        "title": "Privilege Escalation + Persistence",
        "explanation": "Privileges were escalated and then used to install persistent access.",
        "user_severity": "CRITICAL",
    },

    # ── HIGH flags ─────────────────────────────────────────────────
    "credential_hunting": {
        "title": "Credential Hunting",
        "explanation": "Commands are searching for or accessing credential files (SSH keys, tokens, passwords).",
        "user_severity": "WARNING",
    },
    "persistence_install": {
        "title": "Persistence Installation",
        "explanation": "A mechanism for persistent access is being installed (cron job, systemd service, shell hook).",
        "user_severity": "WARNING",
    },
    "privilege_escalation": {
        "title": "Privilege Escalation",
        "explanation": "An attempt to gain higher system privileges was detected (sudo, setuid, capabilities).",
        "user_severity": "WARNING",
    },
    "supply_chain_risk": {
        "title": "Supply Chain Risk",
        "explanation": "A package install from an untrusted or unusual source was detected.",
        "user_severity": "WARNING",
    },
    "injection_attempt": {
        "title": "Injection Attempt",
        "explanation": "A SQL injection, command injection, or similar code injection pattern was detected.",
        "user_severity": "WARNING",
    },
    "path_obfuscation": {
        "title": "Path Obfuscation",
        "explanation": "File paths are being constructed in unusual ways to hide the true target.",
        "user_severity": "WARNING",
    },
    "symlink_indirection": {
        "title": "Symlink Indirection",
        "explanation": "A symlink is being created or followed that could redirect access to sensitive files.",
        "user_severity": "WARNING",
    },
    "alias_obfuscation": {
        "title": "Alias Obfuscation",
        "explanation": "Shell aliases or functions are being used to disguise the actual command being run.",
        "user_severity": "WARNING",
    },
    "delayed_exfiltration": {
        "title": "Delayed Exfiltration",
        "explanation": "A scheduled task (at, cron) is being set up to send data later.",
        "user_severity": "WARNING",
    },
    "git_credential_search": {
        "title": "Git Credential Search",
        "explanation": "Git credential stores, tokens, or authentication configs are being accessed.",
        "user_severity": "WARNING",
    },
    "data_staging": {
        "title": "Data Staging",
        "explanation": "Data is being collected and staged (archived, compressed) in preparation for exfiltration.",
        "user_severity": "WARNING",
    },
    "prompt_injection": {
        "title": "Prompt Injection",
        "explanation": "Content that attempts to manipulate the AI agent's instructions was detected.",
        "user_severity": "WARNING",
    },

    # ── MEDIUM flags ───────────────────────────────────────────────
    "ml_anomaly": {
        "title": "ML Behavioral Anomaly",
        "explanation": "The machine learning model flagged this command as statistically unusual.",
        "user_severity": "INFO",
    },
    "infra_config_access": {
        "title": "Infrastructure Config Access",
        "explanation": "Infrastructure configuration files are being read or modified (Docker, K8s, nginx).",
        "user_severity": "INFO",
    },
    "env_harvesting": {
        "title": "Environment Variable Harvesting",
        "explanation": "Environment variables are being read in bulk, which could expose secrets.",
        "user_severity": "INFO",
    },
    "ssrf_attempt": {
        "title": "SSRF Attempt",
        "explanation": "A request to an internal or metadata endpoint was detected (server-side request forgery).",
        "user_severity": "INFO",
    },
    "cloud_infra_mutation": {
        "title": "Cloud Infrastructure Mutation",
        "explanation": "Cloud infrastructure is being modified (AWS, GCP, Azure resource changes).",
        "user_severity": "INFO",
    },
    "sensitive_target": {
        "title": "Sensitive File Access",
        "explanation": "A sensitive file was accessed (e.g. .env, credentials, private keys).",
        "user_severity": "INFO",
    },
    "blocked_domain": {
        "title": "Blocked Domain Access",
        "explanation": "A request was made to a domain on the blocklist.",
        "user_severity": "INFO",
    },
    "potential_injection": {
        "title": "Potential Injection Pattern",
        "explanation": "A pattern that could indicate prompt injection was detected (medium confidence).",
        "user_severity": "INFO",
    },

    # ── LOW flags ──────────────────────────────────────────────────
    "behavioral_shift": {
        "title": "Behavioral Shift",
        "explanation": "The agent's behavior pattern has changed from its established baseline.",
        "user_severity": "FYI",
    },
    "obfuscation_detected": {
        "title": "Obfuscation Detected",
        "explanation": "Obfuscation patterns were found in the command (base64, eval, encoded strings).",
        "user_severity": "FYI",
    },
    "error_on_suspicious": {
        "title": "Error on Suspicious Command",
        "explanation": "A command that previously raised suspicion resulted in an error.",
        "user_severity": "FYI",
    },
}

# Severity label formatting
_SEVERITY_LABELS = {
    "CRITICAL": "\u26a0 CRITICAL",
    "WARNING": "WARNING",
    "INFO": "INFO",
    "FYI": "FYI",
}

# Severity ordering for sorting (higher = more severe)
_SEVERITY_ORDER = {"CRITICAL": 4, "WARNING": 3, "INFO": 2, "FYI": 1}


def get_flag_title(flag):
    """Get human-readable title for a flag. Falls back to flag name."""
    entry = FLAG_MESSAGES.get(flag)
    if entry:
        return entry["title"]
    # Unknown flag — format the name nicely
    return flag.replace("_", " ").title()


def get_flag_explanation(flag):
    """Get explanation for a flag. Falls back to generic message."""
    entry = FLAG_MESSAGES.get(flag)
    if entry:
        return entry["explanation"]
    return f"Detection flag '{flag}' was triggered."


def get_user_severity(flag):
    """Get UX severity tier for a flag. Falls back to INFO."""
    entry = FLAG_MESSAGES.get(flag)
    if entry:
        return entry["user_severity"]
    return "INFO"


def _highest_severity(flags):
    """Return the highest UX severity among a set of flags."""
    best = "FYI"
    for f in flags:
        sev = get_user_severity(f)
        if _SEVERITY_ORDER.get(sev, 0) > _SEVERITY_ORDER.get(best, 0):
            best = sev
    return best


def format_detection(flags, tool_name, target_preview, severity=None, mode="immediate"):
    """Format detection output for stderr.

    Args:
        flags: list of detection flag strings
        tool_name: the tool that was flagged (e.g. "Bash")
        target_preview: short preview of the command/path
        severity: override severity string, or None to compute from flags
        mode: "immediate" (CRITICAL/HIGH multi-line),
              "brief" (MEDIUM/LOW single-line),
              "gate_block" (enforce mode block with override hint)

    Returns:
        Formatted string ready for sys.stderr.write()
    """
    if not flags:
        return ""

    # Use the most severe flag for the primary message
    primary_flag = max(flags, key=lambda f: _SEVERITY_ORDER.get(get_user_severity(f), 0))
    sev = severity or _highest_severity(flags)
    sev_label = _SEVERITY_LABELS.get(sev, sev)
    title = get_flag_title(primary_flag)
    explanation = get_flag_explanation(primary_flag)
    preview = (target_preview or "")[:80]

    if mode == "brief":
        # Single line for deferred review
        return f"[obol] {title} ({sev}) \u2014 {preview}\n"

    if mode == "gate_block":
        # Enforce mode block — multi-line with override hint
        lines = [
            f"\n\u26a0 Obol: {title} [{sev_label}]",
            f"  {explanation}",
            f"  Tool: {tool_name} | {preview}",
        ]
        if len(flags) > 1:
            other = [get_flag_title(f) for f in flags if f != primary_flag]
            lines.append(f"  Also: {', '.join(other)}")
        lines.append(f"  \u2192 obol review       See this session's detections")
        lines.append(f"  \u2192 obol explain {primary_flag}")
        lines.append("")
        return "\n".join(lines) + "\n"

    # mode == "immediate" — multi-line for CRITICAL/HIGH
    lines = [
        f"\n\u26a0 Obol: {title} [{sev_label}]",
        f"  {explanation}",
    ]
    if len(flags) > 1:
        other = [get_flag_title(f) for f in flags if f != primary_flag]
        lines.append(f"  Also: {', '.join(other)}")
    lines.append(f"  \u2192 obol review       See this session's detections")
    lines.append(f"  \u2192 obol explain {primary_flag}")
    lines.append("")
    return "\n".join(lines) + "\n"


def format_session_summary(stats):
    """Format end-of-session summary box.

    Args:
        stats: dict with keys:
            total (int), clean (int), flagged (int),
            deferred (list of (flag, tool, target_preview, timestamp) tuples),
            session_start (float, epoch timestamp)

    Returns:
        Formatted string for terminal output.
    """
    import time as _time

    total = stats.get("total", 0)
    clean = stats.get("clean", 0)
    flagged = stats.get("flagged", 0)
    deferred = stats.get("deferred", [])
    start = stats.get("session_start", 0)

    # Duration
    if start:
        elapsed = _time.time() - start
        mins = int(elapsed / 60)
        if mins < 1:
            duration = "<1 min"
        elif mins < 60:
            duration = f"{mins} min"
        else:
            duration = f"{mins // 60}h {mins % 60}m"
    else:
        duration = "unknown"

    width = 50
    bar = "\u2500"  # ─

    lines = [
        f"\n{bar * 2} Obol Session Summary {bar * (width - 23)}",
        f"  Duration: {duration} | Events: {total}",
    ]
    if clean:
        lines.append(f"  \u2713 {clean} clean")

    if flagged:
        lines.append(f"  \u26a0 {flagged} flagged:")

        # Group deferred by flag
        flag_counts = {}
        flag_targets = {}
        for flag, tool, target, ts in deferred:
            flag_counts[flag] = flag_counts.get(flag, 0) + 1
            if flag not in flag_targets:
                flag_targets[flag] = []
            short = (target or "")[:30]
            if short and short not in flag_targets[flag]:
                flag_targets[flag].append(short)

        # Sort by severity then count
        sorted_flags = sorted(
            flag_counts.keys(),
            key=lambda f: (-_SEVERITY_ORDER.get(get_user_severity(f), 0), -flag_counts[f]),
        )
        for flag in sorted_flags:
            sev = get_user_severity(flag)
            title = get_flag_title(flag)
            count = flag_counts[flag]
            targets_str = ", ".join(flag_targets.get(flag, [])[:3])
            count_str = f" (\u00d7{count})" if count > 1 else ""
            lines.append(f"    {sev:<8} {title}{count_str} \u2014 {targets_str}")
    elif total > 0:
        lines.append("  All clean.")

    lines.append(f"  \u2192 obol review                   Full details")
    if flagged:
        lines.append(f"  \u2192 obol allow <flag>             Suppress in future")
    lines.append(bar * width)
    lines.append("")
    return "\n".join(lines) + "\n"
