"""
Secret File Guard - Protect against reading or storing sensitive files.

This module provides file-level protection to prevent agents from accessing
files that are likely to contain secrets (like .env, .pem, credentials.json).

Usage:
    from agent_orchestrator.secrets import SecretFileGuard

    # Check if a file should be accessed
    allowed, reason = SecretFileGuard.check_read("/path/to/.env")
    if not allowed:
        print(f"Access denied: {reason}")
"""

import re
from pathlib import Path
from typing import Optional

from ..adapters.base import RiskLevel


# File patterns that should NEVER be read or stored by agents
NEVER_STORE_PATTERNS: list[str] = [
    # Environment files
    r"\.env$",
    r"\.env\.local$",
    r"\.env\.production$",
    r"\.env\.development$",
    r"\.env\.staging$",
    r"\.env\.[a-zA-Z]+$",

    # Secret/credential files
    r"secrets?\.ya?ml$",
    r"secrets?\.json$",
    r"credentials?\.json$",
    r"credentials?\.ya?ml$",
    r"service[-_]?account\.json$",

    # Key files
    r".*\.pem$",
    r".*\.key$",
    r".*\.p12$",
    r".*\.pfx$",
    r".*_rsa$",
    r".*_dsa$",
    r".*_ecdsa$",
    r".*_ed25519$",
    r"id_rsa$",
    r"id_dsa$",
    r"id_ecdsa$",
    r"id_ed25519$",

    # Cloud provider credentials
    r"\.aws/credentials$",
    r"\.aws/config$",
    r"gcloud/.*credentials.*$",
    r"\.azure/.*$",
    r"\.kube/config$",

    # SSH
    r"\.ssh/.*$",
    r"known_hosts$",
    r"authorized_keys$",

    # GPG
    r"\.gnupg/.*$",
    r".*\.gpg$",
    r".*\.asc$",

    # Password stores
    r"\.password-store/.*$",
    r".*\.kdbx$",  # KeePass

    # Docker
    r"\.docker/config\.json$",

    # NPM
    r"\.npmrc$",

    # Git credentials
    r"\.git-credentials$",
    r"\.gitconfig$",  # Can contain credentials

    # Terraform
    r"terraform\.tfstate$",
    r"terraform\.tfstate\.backup$",
    r".*\.tfvars$",

    # Ansible
    r"vault\.ya?ml$",
    r".*vault.*\.ya?ml$",

    # Certificates
    r".*\.crt$",
    r".*\.cer$",
]


class SecretFileGuard:
    """
    Guard against accessing secret files.

    Provides methods to check whether file operations should be allowed
    based on the file path matching known secret file patterns.
    """

    # Cache compiled patterns for performance
    _compiled_patterns: Optional[list[re.Pattern]] = None

    @classmethod
    def _get_patterns(cls) -> list[re.Pattern]:
        """Get compiled regex patterns."""
        if cls._compiled_patterns is None:
            cls._compiled_patterns = [
                re.compile(pattern, re.IGNORECASE)
                for pattern in NEVER_STORE_PATTERNS
            ]
        return cls._compiled_patterns

    @classmethod
    def is_secret_file(cls, file_path: str) -> bool:
        """
        Check if a file path matches a secret file pattern.

        Args:
            file_path: Path to check (can be absolute or relative)

        Returns:
            True if the file is likely to contain secrets
        """
        # Normalize path for matching
        path = Path(file_path)
        path_str = str(path)

        # Check against all patterns
        for pattern in cls._get_patterns():
            if pattern.search(path_str):
                return True

        return False

    @classmethod
    def check_read(cls, file_path: str) -> tuple[bool, str]:
        """
        Check if a file can be read.

        Args:
            file_path: Path to the file

        Returns:
            Tuple of (allowed, reason)
        """
        if cls.is_secret_file(file_path):
            return False, f"BLOCKED: {file_path} matches secret file pattern"
        return True, "allowed"

    @classmethod
    def check_write(cls, file_path: str) -> tuple[bool, str]:
        """
        Check if a file can be written.

        Writing to secret files is generally MORE dangerous than reading.

        Args:
            file_path: Path to the file

        Returns:
            Tuple of (allowed, reason)
        """
        if cls.is_secret_file(file_path):
            return False, f"BLOCKED: Cannot write to secret file {file_path}"
        return True, "allowed"

    @classmethod
    def classify_file_risk(cls, file_path: str) -> RiskLevel:
        """
        Classify the risk level for accessing a file.

        Args:
            file_path: Path to the file

        Returns:
            RiskLevel enum value
        """
        if cls.is_secret_file(file_path):
            return RiskLevel.CRITICAL

        # Check for other risky file patterns
        path_lower = file_path.lower()

        # High risk files
        high_risk_patterns = [
            r"\.github/workflows/",
            r"docker-compose\.ya?ml$",
            r"dockerfile",
            r"terraform/",
            r"k8s/",
            r"kubernetes/",
            r"migrations?/",
            r"\.gitlab-ci\.ya?ml$",
            r"jenkinsfile",
        ]
        for pattern in high_risk_patterns:
            if re.search(pattern, path_lower):
                return RiskLevel.HIGH

        # Medium risk files
        medium_risk_patterns = [
            r"package\.json$",
            r"requirements\.txt$",
            r"pyproject\.toml$",
            r"cargo\.toml$",
            r"go\.mod$",
            r".*config.*\.(json|ya?ml|toml)$",
        ]
        for pattern in medium_risk_patterns:
            if re.search(pattern, path_lower):
                return RiskLevel.MEDIUM

        return RiskLevel.LOW

    @classmethod
    def get_matching_pattern(cls, file_path: str) -> Optional[str]:
        """
        Get the pattern that matched a file path.

        Useful for debugging and logging why a file was blocked.

        Args:
            file_path: Path to check

        Returns:
            The matching pattern string, or None if no match
        """
        path_str = str(Path(file_path))

        for i, pattern in enumerate(cls._get_patterns()):
            if pattern.search(path_str):
                return NEVER_STORE_PATTERNS[i]

        return None

    @classmethod
    def add_pattern(cls, pattern: str) -> None:
        """
        Add a custom pattern to the block list.

        Args:
            pattern: Regex pattern for files to block
        """
        NEVER_STORE_PATTERNS.append(pattern)
        # Invalidate cache
        cls._compiled_patterns = None

    @classmethod
    def filter_paths(cls, paths: list[str]) -> tuple[list[str], list[str]]:
        """
        Filter a list of paths into allowed and blocked.

        Args:
            paths: List of file paths

        Returns:
            Tuple of (allowed_paths, blocked_paths)
        """
        allowed = []
        blocked = []

        for path in paths:
            if cls.is_secret_file(path):
                blocked.append(path)
            else:
                allowed.append(path)

        return allowed, blocked


# Actions on secret files require explicit approval
SECRET_ACCESS_ACTIONS = {
    "read": RiskLevel.HIGH,
    "write": RiskLevel.CRITICAL,  # Never allow
    "delete": RiskLevel.CRITICAL,
    "copy": RiskLevel.CRITICAL,
    "move": RiskLevel.CRITICAL,
}


def get_action_risk_level(action: str, file_path: str) -> RiskLevel:
    """
    Get the risk level for an action on a file.

    Args:
        action: The action (read, write, delete, copy, move)
        file_path: Path to the file

    Returns:
        RiskLevel for the action
    """
    if SecretFileGuard.is_secret_file(file_path):
        return SECRET_ACCESS_ACTIONS.get(action, RiskLevel.HIGH)

    return SecretFileGuard.classify_file_risk(file_path)
