"""VAL-001: Missing Input Validation detection rule."""

from __future__ import annotations

import ast

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


class MissingInputValidationRule(Rule):
    """Detects MCP handler functions that process arguments without validation."""

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

    @property
    def name(self) -> str:
        return "Missing Input Validation"

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

    @property
    def description(self) -> str:
        return "Handler functions processing arguments without type/range validation."

    def suggest_fix(self, source: str, finding: Finding) -> str | None:
        """Suggest adding isinstance validation before argument use."""
        lines = source.splitlines()
        idx = finding.line - 1
        if idx < 0 or idx >= len(lines):
            return None
        line = lines[idx]
        indent = line[: len(line) - len(line.lstrip())]
        return f'{indent}# TODO: Add input validation — e.g. isinstance(arguments["key"], str)'

    def check(self, tree: ast.Module, source: str) -> list[Finding]:
        """Check for handler functions lacking input validation."""
        findings: list[Finding] = []

        for node in ast.walk(tree):
            if not isinstance(node, (ast.AsyncFunctionDef, ast.FunctionDef)):
                continue
            if "call_tool" not in node.name and "handle" not in node.name:
                continue

            body_src = ast.get_source_segment(source, node) or ""
            if "arguments" not in body_src:
                continue
            if "validate" in body_src.lower():
                continue
            if "isinstance" in body_src or "schema" in body_src.lower():
                continue

            findings.append(Finding(
                rule_id=self.rule_id,
                severity=self.severity,
                title="Missing input validation",
                description=f"Function {node.name}() processes arguments without validation.",
                file="",
                line=node.lineno,
                recommendation="Validate argument types and ranges.",
                cwe="CWE-20",
            ))
        return findings
