"""
Nucleus Runtime - Unified Hardening Module
===========================================
Enterprise-grade security and reliability hardening for Nucleus-MCP.

This module integrates ALL hardening components identified in the 
Feb 24, 2026 Exhaustive Design Thinking Analysis:

CRITICAL FIXES (Enterprise Hardening):
- C20: Path Traversal Prevention
- C25: Concurrent Write Safety  
- C33: Error Information Leakage Prevention
- C18: Timeout Bounds Enforcement
- C30: UTF-8 Encoding Standardization

SYNERGY WITH ANTIGRAVITY THREAD:
- AgentPool integration ready
- Federation state protection
- Multi-agent concurrent access safe

Usage:
    from mcp_server_nucleus.runtime.hardening import (
        safe_path,
        safe_write_json,
        safe_append_jsonl,
        safe_read_jsonl,
        safe_error,
        with_timeout,
    )
"""

import os
import json
import logging
from pathlib import Path
from typing import Any, Dict, List, Optional, Union
from functools import wraps

logger = logging.getLogger("nucleus.hardening")

# Re-export all hardening components
from .path_sanitizer import (
    sanitize_path,
    sanitize_filename,
    safe_join,
    is_safe_path,
    PathTraversalError,
    InvalidPathError,
)

from .file_lock import (
    file_lock,
    atomic_write_json,
    atomic_append_jsonl,
    safe_read_jsonl,
    safe_read_json,
    repair_jsonl,
    LockError,
    AtomicWriteError,
)

from .error_sanitizer import (
    sanitize_error,
    SanitizedError,
    safe_error_handler,
    format_safe_response,
    log_operation,
    ErrorContext,
)

from .timeout_handler import (
    with_timeout,
    run_with_timeout,
    TimeoutError as NucleusTimeoutError,
    tool_timeout,
    file_timeout,
    network_timeout,
    OperationTimeout,
)


# ============================================================================
# CONVENIENCE WRAPPERS (Enterprise-Grade Defaults)
# ============================================================================

def safe_path(user_input: str, base_dir: Union[str, Path]) -> Path:
    """
    Safely resolve a user-provided path within a base directory.
    
    This is the primary path validation function for all user input.
    Prevents path traversal attacks (C20).
    
    Args:
        user_input: User-provided path string (task_id, engram_key, etc.)
        base_dir: Base directory that path must stay within
        
    Returns:
        Resolved, validated Path object
        
    Raises:
        PathTraversalError: If path would escape base_dir
        InvalidPathError: If path contains invalid characters
    """
    return sanitize_path(user_input, base_dir, allow_subdirs=False)


def safe_write_json(
    path: Union[str, Path],
    data: Any,
    indent: int = 2
) -> None:
    """
    Safely write JSON data with atomic operations and fsync.
    
    Prevents data corruption from concurrent writes (C25).
    Uses write-to-temp-then-rename pattern.
    
    Args:
        path: Destination file path
        data: Data to serialize as JSON
        indent: JSON indentation
    """
    atomic_write_json(path, data, indent)


def safe_append_jsonl(
    path: Union[str, Path],
    record: Dict[str, Any],
    timeout: float = 10.0
) -> None:
    """
    Safely append to JSONL with file locking.
    
    Prevents data corruption from concurrent appends (C25).
    Uses file locking for mutual exclusion.
    
    Args:
        path: Path to JSONL file
        record: Record to append
        timeout: Lock timeout in seconds
    """
    atomic_append_jsonl(path, record, timeout)


def safe_error(error: Exception, context: str = "") -> str:
    """
    Convert exception to sanitized error message.
    
    Prevents information leakage (C33).
    Logs full details internally, returns safe message.
    
    Args:
        error: The exception
        context: Additional context for logging
        
    Returns:
        User-safe error message
    """
    return sanitize_error(error, "internal_error", context)


def safe_open(
    path: Union[str, Path],
    mode: str = "r",
    **kwargs
) -> Any:
    """
    Open file with UTF-8 encoding by default.
    
    Fixes cross-platform encoding issues (C30).
    
    Args:
        path: File path
        mode: Open mode
        **kwargs: Additional open() arguments
        
    Returns:
        File handle
    """
    if "encoding" not in kwargs and "b" not in mode:
        kwargs["encoding"] = "utf-8"
    return open(path, mode, **kwargs)


# ============================================================================
# AGENT POOL INTEGRATION (Synergy with Antigravity Thread)
# ============================================================================

def safe_agent_id(agent_id: str, base_dir: Union[str, Path]) -> Path:
    """
    Validate and sanitize agent ID for file operations.
    
    Used by AgentPool for safe agent state persistence.
    
    Args:
        agent_id: Agent identifier from pool
        base_dir: Agent state directory
        
    Returns:
        Safe path for agent state file
    """
    # Validate agent ID format
    sanitized = sanitize_filename(agent_id)
    return safe_join(base_dir, f"{sanitized}.json")


def safe_agent_state_write(
    agent_id: str,
    state: Dict[str, Any],
    base_dir: Union[str, Path]
) -> None:
    """
    Safely persist agent state with locking.
    
    Used by AgentPool for concurrent agent state updates.
    
    Args:
        agent_id: Agent identifier
        state: Agent state dict
        base_dir: Agent state directory
    """
    path = safe_agent_id(agent_id, base_dir)
    safe_write_json(path, state)


def safe_agent_state_read(
    agent_id: str,
    base_dir: Union[str, Path],
    default: Optional[Dict] = None
) -> Optional[Dict]:
    """
    Safely read agent state.
    
    Args:
        agent_id: Agent identifier
        base_dir: Agent state directory
        default: Default value if not found
        
    Returns:
        Agent state dict or default
    """
    path = safe_agent_id(agent_id, base_dir)
    return safe_read_json(path, default)


# ============================================================================
# FEDERATION INTEGRATION (Synergy with Antigravity Thread)
# ============================================================================

def safe_federation_state_write(
    node_id: str,
    state: Dict[str, Any],
    federation_dir: Union[str, Path]
) -> None:
    """
    Safely persist federation node state.
    
    Used by Federation Engine for RAFT state persistence.
    
    Args:
        node_id: Federation node identifier
        state: Node state dict
        federation_dir: Federation state directory
    """
    sanitized_id = sanitize_filename(node_id)
    path = Path(federation_dir) / f"node_{sanitized_id}.json"
    path.parent.mkdir(parents=True, exist_ok=True)
    safe_write_json(path, state)


def safe_federation_log_append(
    federation_dir: Union[str, Path],
    entry: Dict[str, Any]
) -> None:
    """
    Safely append to federation log.
    
    Used by Federation Engine for RAFT log entries.
    
    Args:
        federation_dir: Federation state directory
        entry: Log entry dict
    """
    path = Path(federation_dir) / "raft_log.jsonl"
    safe_append_jsonl(path, entry)


# ============================================================================
# HARDENING STATUS CHECK
# ============================================================================

def get_hardening_status() -> Dict[str, Any]:
    """
    Get current hardening module status.
    
    Returns dict with status of all hardening components.
    """
    try:
        from .file_lock import FILELOCK_AVAILABLE
        filelock_status = "robust" if FILELOCK_AVAILABLE else "basic"
    except ImportError:
        filelock_status = "unavailable"
    
    return {
        "hardening_version": "1.0.0",
        "components": {
            "path_sanitizer": "active",
            "file_lock": filelock_status,
            "error_sanitizer": "active",
            "timeout_handler": "active",
        },
        "critical_fixes": {
            "C20_path_traversal": "FIXED",
            "C25_concurrent_write": "FIXED",
            "C33_info_leakage": "FIXED",
            "C18_timeout_bounds": "FIXED",
            "C30_utf8_encoding": "PARTIAL",
        },
        "enterprise_ready": True,
        "hardened": True,
        "antigravity_synergy": {
            "agent_pool_integration": "ready",
            "federation_integration": "ready",
        },
    }


# ============================================================================
# DECORATOR FOR MCP TOOLS (Full Protection)
# ============================================================================

def hardened_tool(timeout: float = 30.0, category: str = "internal_error"):
    """
    Decorator that applies all hardening to an MCP tool.
    
    Combines:
    - Timeout bounds (C18)
    - Error sanitization (C33)
    - Audit logging
    
    Usage:
        @hardened_tool(timeout=10.0)
        def my_mcp_tool(arg1, arg2):
            ...
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            op_id = log_operation(
                operation=func.__name__,
                resource=str(args[0]) if args else None,
                result="started"
            )
            
            try:
                result = run_with_timeout(func, args, kwargs, timeout=timeout)
                log_operation(
                    operation=func.__name__,
                    result="success"
                )
                return result
            except NucleusTimeoutError as e:
                log_operation(
                    operation=func.__name__,
                    result="timeout"
                )
                raise SanitizedError("timeout", str(e))
            except Exception as e:
                log_operation(
                    operation=func.__name__,
                    result="error"
                )
                raise SanitizedError(category, str(e))
        
        return wrapper
    return decorator


# ============================================================================
# INITIALIZATION
# ============================================================================

logger.info("Nucleus hardening module loaded - enterprise hardening active")
