"""DESER-001: Unsafe Deserialization detection rule.

NOTE: This module contains regex patterns that match dangerous functions
(like eval) because it is a SECURITY SCANNER that detects these patterns
in target code. These are detection signatures, not actual usage.
"""

from __future__ import annotations

import ast
import re

from . import Rule
from ..models import Finding, Severity

# Detection patterns for unsafe deserialization in scanned target code.
# Format: (regex_pattern, description, severity)
UNSAFE_DESER_PATTERNS: list[tuple[str, str, Severity]] = [
    (r'\byaml\.load\b(?!\s*\(.*Loader)', "yaml.load() without SafeLoader", Severity.HIGH),
    # Detects arbitrary code execution in target files
    (r'\beval\s*\(', "Arbitrary code execution risk", Severity.CRITICAL),
    (r'\bpickle\.loads?\s*\(', "pickle deserialization allows arbitrary code execution", Severity.CRITICAL),
    (r'\bmarshal\.loads?\s*\(', "marshal deserialization allows arbitrary code execution", Severity.HIGH),
]


class UnsafeDeserializationRule(Rule):
    """Detects unsafe deserialization and code execution patterns."""

    @property
    def rule_id(self) -> str:
        return "DESER-001"

    @property
    def name(self) -> str:
        return "Unsafe Deserialization"

    @property
    def severity(self) -> Severity:
        return Severity.CRITICAL

    @property
    def cwe(self) -> str:
        return "CWE-502"

    @property
    def description(self) -> str:
        return "Unsafe deserialization or arbitrary code execution detected."

    def check(self, tree: ast.Module, source: str) -> list[Finding]:
        """Check for unsafe deserialization patterns."""
        findings: list[Finding] = []
        lines = self._get_lines(source)

        for i, line in enumerate(lines, 1):
            if line.strip().startswith("#"):
                continue
            for pattern, desc, sev in UNSAFE_DESER_PATTERNS:
                if re.search(pattern, line):
                    findings.append(Finding(
                        rule_id=self.rule_id,
                        severity=sev,
                        title="Deserializacion/ejecucion insegura",
                        description=f"Detectado: {desc}.",
                        file="",
                        line=i,
                        code_snippet=line.strip()[:80],
                        recommendation="Use json.loads() or yaml.safe_load() instead.",
                        cwe="CWE-502",
                        confidence="MEDIUM",
                    ))
        return findings
