"""MCP tools — vallm code validation integration.

Exposes vallm validators as MCP tools that can be invoked from the
proxym task pipeline, allowing automated code validation as part of
project workflows.

Available tools:
    validate_syntax   — Check code for syntax errors (multi-language)
    validate_imports  — Verify imports are resolvable
    validate_security — Detect security issues (eval, exec, secrets)
    validate_code     — Full pipeline validation (syntax + imports + complexity + security)
    validate_regression — Run tests against proposed code changes
"""
from __future__ import annotations

import traceback
from typing import Any

import structlog
from fastapi import APIRouter
from pydantic import BaseModel, Field

router = APIRouter()
logger = structlog.get_logger()


# --- Request models ---

class ValidateCodeReq(BaseModel):
    """Request to validate code."""
    code: str = ""
    language: str = "python"
    filename: str | None = None
    validators: list[str] = Field(
        default_factory=lambda: ["syntax", "imports", "security"],
        description="Which validators to run: syntax, imports, security, complexity, regression",
    )
    reference_code: str | None = None
    test_dir: str | None = None
    metadata: dict[str, Any] = Field(default_factory=dict)


class ValidateSyntaxReq(BaseModel):
    code: str = ""
    language: str = "python"
    filename: str | None = None


class ValidateSecurityReq(BaseModel):
    code: str = ""
    language: str = "python"


# --- Helpers ---

def _try_import_vallm():
    """Try to import vallm; return None if not available."""
    try:
        import vallm
        return vallm
    except ImportError:
        return None


def _make_proposal(code: str, language: str, filename: str | None = None, metadata: dict | None = None):
    """Create a vallm Proposal object."""
    from vallm.core.proposal import Proposal
    return Proposal(
        code=code,
        language=language,
        filename=filename,
        metadata=metadata or {},
    )


def _result_to_dict(result) -> dict[str, Any]:
    """Convert a vallm ValidationResult to a dict."""
    return {
        "score": result.score,
        "verdict": result.verdict.value if hasattr(result.verdict, "value") else str(result.verdict),
        "issues": [
            {
                "message": issue.message,
                "severity": issue.severity.value if hasattr(issue.severity, "value") else str(issue.severity),
                "line": getattr(issue, "line", None),
                "validator": getattr(issue, "validator", ""),
            }
            for issue in (result.issues or [])
        ],
    }


# --- Shared validation helper ---

def _validate_single(
    validator_name: str,
    validator_import_path: str,
    validator_class_name: str,
    req: ValidateSyntaxReq,
) -> dict[str, Any]:
    """Run a single vallm validator and return the result dict."""
    if not _try_import_vallm():
        return {"error": "vallm not installed", "available": False}

    try:
        import importlib
        mod = importlib.import_module(validator_import_path)
        validator_cls = getattr(mod, validator_class_name)
        validator = validator_cls()
        proposal = _make_proposal(req.code, req.language, getattr(req, "filename", None))
        result = validator.validate(proposal, {})

        _emit_validation_event(validator_name, req.language, result)

        return {
            "validator": validator_name,
            "language": req.language,
            **_result_to_dict(result),
        }
    except Exception as exc:
        logger.warning(f"vallm_{validator_name}_error", error=str(exc))
        return {"validator": validator_name, "error": str(exc), "score": 0.0}


# --- Endpoints ---

@router.post("/tools/validate_syntax")
async def tool_validate_syntax(req: ValidateSyntaxReq) -> dict[str, Any]:
    """Validate code syntax using vallm SyntaxValidator."""
    return _validate_single("syntax", "vallm.validators.syntax", "SyntaxValidator", req)


@router.post("/tools/validate_imports")
async def tool_validate_imports(req: ValidateSyntaxReq) -> dict[str, Any]:
    """Validate code imports using vallm ImportValidator."""
    return _validate_single("imports", "vallm.validators.imports", "ImportValidator", req)


@router.post("/tools/validate_security")
async def tool_validate_security(req: ValidateSecurityReq) -> dict[str, Any]:
    """Validate code security using vallm SecurityValidator."""
    return _validate_single("security", "vallm.validators.security", "SecurityValidator", req)


@router.post("/tools/validate_code")
async def tool_validate_code(req: ValidateCodeReq) -> dict[str, Any]:
    """Full code validation pipeline using multiple vallm validators.

    Runs the requested validators in sequence and returns aggregated results.
    """
    if not _try_import_vallm():
        return {"error": "vallm not installed", "available": False}

    try:
        proposal = _make_proposal(req.code, req.language, req.filename, req.metadata)
        results = {}
        all_issues = []
        total_score = 0.0
        count = 0

        validator_map = _get_validator_map(req)

        for name in req.validators:
            if name not in validator_map:
                results[name] = {"error": f"Unknown validator: {name}"}
                continue

            try:
                validator = validator_map[name]
                result = validator.validate(proposal, {})
                results[name] = _result_to_dict(result)
                total_score += result.score
                count += 1
                all_issues.extend(results[name]["issues"])
            except Exception as exc:
                results[name] = {"error": str(exc), "score": 0.0}

        avg_score = total_score / count if count > 0 else 0.0

        # Emit aggregate event
        _emit_validation_event("pipeline", req.language, None, score=avg_score)

        return {
            "language": req.language,
            "validators_run": list(results.keys()),
            "results": results,
            "aggregate_score": round(avg_score, 3),
            "total_issues": len(all_issues),
            "issues": all_issues,
        }
    except Exception as exc:
        logger.warning("vallm_pipeline_error", error=str(exc))
        return {"error": str(exc), "aggregate_score": 0.0}


def _get_validator_map(req: ValidateCodeReq) -> dict:
    """Build a map of validator name → instance."""
    validators = {}
    try:
        from vallm.validators.syntax import SyntaxValidator
        validators["syntax"] = SyntaxValidator()
    except ImportError:
        pass
    try:
        from vallm.validators.imports import ImportValidator
        validators["imports"] = ImportValidator()
    except ImportError:
        pass
    try:
        from vallm.validators.security import SecurityValidator
        validators["security"] = SecurityValidator()
    except ImportError:
        pass
    try:
        from vallm.validators.complexity import ComplexityValidator
        validators["complexity"] = ComplexityValidator()
    except ImportError:
        pass
    try:
        from vallm.validators.regression import RegressionValidator
        kwargs = {}
        if req.test_dir:
            kwargs["test_dir"] = req.test_dir
        validators["regression"] = RegressionValidator(**kwargs)
    except ImportError:
        pass
    return validators


def _emit_validation_event(validator_name: str, language: str, result: Any = None, score: float | None = None) -> None:
    """Emit a ValidationCompleted domain event."""
    try:
        from proxym.domain.setup import get_event_store
        from proxym.domain.events import ValidationCompleted
        store = get_event_store()
        store.append(ValidationCompleted(
            aggregate_id=f"validation-{validator_name}",
            data={
                "validator": validator_name,
                "language": language,
                "score": score if score is not None else (result.score if result else 0.0),
            },
            actor="mcp",
        ))
    except Exception:
        pass  # Don't fail validation because of event store issues


# ── Schema fragments ─────────────────────────────────────

TOOL_SCHEMA_VALLM: list[dict[str, Any]] = [
    {
        "type": "function",
        "function": {
            "name": "validate_syntax",
            "description": "Check code for syntax errors (supports Python, JavaScript, C, Rust, Go, Java)",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {"type": "string", "description": "Source code to validate"},
                    "language": {"type": "string", "description": "Programming language", "default": "python"},
                },
                "required": ["code"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "validate_imports",
            "description": "Verify that code imports are resolvable",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {"type": "string", "description": "Source code to validate"},
                    "language": {"type": "string", "description": "Programming language", "default": "python"},
                },
                "required": ["code"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "validate_security",
            "description": "Detect security issues: eval/exec, hardcoded secrets, dangerous patterns",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {"type": "string", "description": "Source code to check"},
                    "language": {"type": "string", "description": "Programming language", "default": "python"},
                },
                "required": ["code"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "validate_code",
            "description": "Full code validation pipeline: syntax + imports + security + complexity",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {"type": "string", "description": "Source code to validate"},
                    "language": {"type": "string", "description": "Programming language", "default": "python"},
                    "validators": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "Which validators to run",
                        "default": ["syntax", "imports", "security"],
                    },
                },
                "required": ["code"],
            },
        },
    },
]
