#
#  Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#

"""
E2B provider implementation.

This provider integrates with E2B Cloud for cloud-based code execution
using Firecracker microVMs.
"""

import uuid
from typing import Dict, Any, List

from .base import SandboxProvider, SandboxInstance, ExecutionResult


class E2BProvider(SandboxProvider):
    """
    E2B provider implementation.

    This provider uses E2B Cloud service for secure code execution
    in Firecracker microVMs.
    """

    def __init__(self):
        self.api_key: str = ""
        self.region: str = "us"
        self.timeout: int = 30
        self._initialized: bool = False

    def initialize(self, config: Dict[str, Any]) -> bool:
        """
        Initialize the provider with E2B credentials.

        Args:
            config: Configuration dictionary with keys:
                - api_key: E2B API key
                - region: Region (us, eu) (default: "us")
                - timeout: Request timeout in seconds (default: 30)

        Returns:
            True if initialization successful, False otherwise
        """
        self.api_key = config.get("api_key", "")
        self.region = config.get("region", "us")
        self.timeout = config.get("timeout", 30)

        # Validate required fields
        if not self.api_key:
            return False

        # TODO: Implement actual E2B API client initialization
        # For now, we'll mark as initialized but actual API calls will fail
        self._initialized = True
        return True

    def create_instance(self, template: str = "python") -> SandboxInstance:
        """
        Create a new sandbox instance in E2B.

        Args:
            template: Programming language template (python, nodejs, go, bash)

        Returns:
            SandboxInstance object

        Raises:
            RuntimeError: If instance creation fails
        """
        if not self._initialized:
            raise RuntimeError("Provider not initialized. Call initialize() first.")

        # Normalize language
        language = self._normalize_language(template)

        # TODO: Implement actual E2B API call
        # POST /sandbox with template
        instance_id = str(uuid.uuid4())

        return SandboxInstance(
            instance_id=instance_id,
            provider="e2b",
            status="running",
            metadata={
                "language": language,
                "region": self.region,
            },
        )

    def execute_code(self, instance_id: str, code: str, language: str, timeout: int = 10) -> ExecutionResult:
        """
        Execute code in the E2B instance.

        Args:
            instance_id: ID of the sandbox instance
            code: Source code to execute
            language: Programming language (python, nodejs, go, bash)
            timeout: Maximum execution time in seconds

        Returns:
            ExecutionResult containing stdout, stderr, exit_code, and metadata

        Raises:
            RuntimeError: If execution fails
            TimeoutError: If execution exceeds timeout
        """
        if not self._initialized:
            raise RuntimeError("Provider not initialized. Call initialize() first.")

        # TODO: Implement actual E2B API call
        # POST /sandbox/{sandboxID}/execute

        raise RuntimeError(
            "E2B provider is not yet fully implemented. Please use the self-managed provider or implement the E2B API integration. See https://github.com/e2b-dev/e2b for API documentation."
        )

    def destroy_instance(self, instance_id: str) -> bool:
        """
        Destroy an E2B instance.

        Args:
            instance_id: ID of the instance to destroy

        Returns:
            True if destruction successful, False otherwise
        """
        if not self._initialized:
            raise RuntimeError("Provider not initialized. Call initialize() first.")

        # TODO: Implement actual E2B API call
        # DELETE /sandbox/{sandboxID}
        return True

    def health_check(self) -> bool:
        """
        Check if the E2B service is accessible.

        Returns:
            True if provider is healthy, False otherwise
        """
        if not self._initialized:
            return False

        # TODO: Implement actual E2B health check API call
        # GET /healthz or similar
        # For now, return True if initialized with API key
        return bool(self.api_key)

    def get_supported_languages(self) -> List[str]:
        """
        Get list of supported programming languages.

        Returns:
            List of language identifiers
        """
        return ["python", "nodejs", "javascript", "go", "bash"]

    @staticmethod
    def get_config_schema() -> Dict[str, Dict]:
        """
        Return configuration schema for E2B provider.

        Returns:
            Dictionary mapping field names to their schema definitions
        """
        return {
            "api_key": {
                "type": "string",
                "required": True,
                "label": "API Key",
                "placeholder": "e2b_sk_...",
                "description": "E2B API key for authentication",
                "secret": True,
            },
            "region": {
                "type": "string",
                "required": False,
                "label": "Region",
                "default": "us",
                "description": "E2B service region (us or eu)",
            },
            "timeout": {
                "type": "integer",
                "required": False,
                "label": "Request Timeout (seconds)",
                "default": 30,
                "min": 5,
                "max": 300,
                "description": "API request timeout for code execution",
            },
        }

    def _normalize_language(self, language: str) -> str:
        """
        Normalize language identifier to E2B template format.

        Args:
            language: Language identifier

        Returns:
            Normalized language identifier
        """
        if not language:
            return "python"

        lang_lower = language.lower()
        if lang_lower in ("python", "python3"):
            return "python"
        elif lang_lower in ("javascript", "nodejs"):
            return "nodejs"
        else:
            return language
