"""
SafeCodeExecutor API Handler

POST /v1/tools/safe-exec - Execute code synchronously
POST /v1/tools/safe-exec/async - Execute code asynchronously (returns job_id)
GET /v1/jobs/{job_id} - Get async job result

Security:
- RBAC check (agent must have safe_exec scope)
- Rate limiting
- Request validation
"""

from typing import Dict, Any, Optional
from dataclasses import dataclass
import hashlib
import time


@dataclass
class ExecRequest:
    """Execution request"""
    language: str
    code: str
    stdin: Optional[str] = None
    limits: Optional[Dict[str, Any]] = None
    context: Optional[Dict[str, Any]] = None


@dataclass  
class ExecResponse:
    """Execution response"""
    status: str
    execution_id: str
    language: str
    stdout: Optional[str] = None
    stderr: Optional[str] = None
    result_json: Optional[Dict] = None
    error: Optional[str] = None
    metrics: Optional[Dict] = None
    job_id: Optional[str] = None


class SafeExecAPI:
    """API handler for SafeCodeExecutor"""
    
    def __init__(self, executor, auth_check=None, rate_limiter=None):
        self.executor = executor
        self.auth_check = auth_check  # RBAC function
        self.rate_limiter = rate_limiter
    
    def _check_auth(self, agent_id: str, scopes: list) -> bool:
        """Check if agent has required scopes"""
        if self.auth_check:
            return self.auth_check(agent_id, scopes)
        return True  # No auth in dev mode
    
    def _check_rate_limit(self, agent_id: str) -> bool:
        """Check rate limit"""
        if self.rate_limiter:
            return self.rate_limiter.is_allowed(agent_id)
        return True
    
    def execute(
        self,
        agent_id: str,
        request: ExecRequest
    ) -> ExecResponse:
        """
        Execute code synchronously.
        
        POST /v1/tools/safe-exec
        """
        # Auth check
        if not self._check_auth(agent_id, ["safe_exec"]):
            return ExecResponse(
                status="unauthorized",
                execution_id="",
                language=request.language,
                error="Agent lacks safe_exec scope"
            )
        
        # Rate limit check
        if not self._check_rate_limit(agent_id):
            return ExecResponse(
                status="rate_limited",
                execution_id="",
                language=request.language,
                error="Rate limit exceeded"
            )
        
        # Validate request
        validation_error = self.executor.validate(request.language, request.code)
        if validation_error:
            return ExecResponse(
                status="validation_failed",
                execution_id="",
                language=request.language,
                error=validation_error
            )
        
        # Execute
        result = self.executor.execute(
            language=request.language,
            code=request.code,
            stdin=request.stdin,
            limits=request.limits,
            context={"agent_id": agent_id, **(request.context or {})}
        )
        
        # Convert to response
        return ExecResponse(
            status=result.get("status", "failed"),
            execution_id=result.get("execution_id", ""),
            language=result.get("language", request.language),
            stdout=result.get("stdout"),
            stderr=result.get("stderr"),
            result_json=result.get("result_json"),
            error=result.get("error"),
            metrics=result.get("metrics")
        )
    
    def execute_async(
        self,
        agent_id: str,
        request: ExecRequest
    ) -> Dict[str, Any]:
        """
        Execute code asynchronously.
        
        POST /v1/tools/safe-exec/async
        Returns job_id for polling
        """
        # Auth check
        if not self._check_auth(agent_id, ["safe_exec"]):
            return {
                "status": "unauthorized",
                "error": "Agent lacks safe_exec scope"
            }
        
        # Rate limit
        if not self._check_rate_limit(agent_id):
            return {
                "status": "rate_limited",
                "error": "Rate limit exceeded"
            }
        
        # Get job_id
        job_id = self.executor.execute_async(
            language=request.language,
            code=request.code,
            stdin=request.stdin,
            limits=request.limits,
            context={"agent_id": agent_id, **(request.context or {})}
        )
        
        return {
            "status": "queued",
            "job_id": job_id,
            "check_url": f"/v1/jobs/{job_id}"
        }
    
    def get_job(
        self,
        agent_id: str,
        job_id: str
    ) -> Dict[str, Any]:
        """
        Get async job result.
        
        GET /v1/jobs/{job_id}
        """
        result = self.executor.get_job_result(job_id)
        
        if not result:
            return {
                "status": "not_found",
                "error": "Job not found"
            }
        
        return result


# =============================================================================
# FASTAPI EXAMPLE (optional integration)
# =============================================================================

def create_api_routes(executor) -> list:
    """Create FastAPI routes for safe-exec"""
    from fastapi import APIRouter, HTTPException, Header
    from typing import Optional
    
    router = APIRouter()
    api = SafeExecAPI(executor)
    
    @router.post("/v1/tools/safe-exec")
    async def exec_code(
        request: ExecRequest,
        x_agent_id: str = Header(default="anonymous")
    ):
        """Execute code synchronously"""
        result = api.execute(x_agent_id, request)
        return result.__dict__
    
    @router.post("/v1/tools/safe-exec/async")
    async def exec_code_async(
        request: ExecRequest,
        x_agent_id: str = Header(default="anonymous")
    ):
        """Execute code asynchronously"""
        return api.execute_async(x_agent_id, request)
    
    @router.get("/v1/jobs/{job_id}")
    async def get_job(
        job_id: str,
        x_agent_id: str = Header(default="anonymous")
    ):
        """Get job result"""
        return api.get_job(x_agent_id, job_id)
    
    return router
