"""
ape_openai - OpenAI integration for Ape

Public API for using Ape tasks with OpenAI function calling.
"""

from ape_openai.schema import ape_task_to_openai_schema
from ape_openai.executor import execute_openai_call, ApeOpenAIFunction
from ape_openai.generator import generate_ape_from_nl

# Re-export ApeTask for convenience
try:
    from ape.runtime.core import FunctionSignature
    from ape import ApeModule

    class ApeTask:
        """
        Representation of an Ape task for OpenAI integration.
        Wraps Ape's FunctionSignature with additional helpers.
        """

        def __init__(self, name: str, inputs: dict, output: str | None = None, description: str | None = None):
            self.name = name
            self.inputs = inputs
            self.output = output
            self.description = description

        @classmethod
        def from_module(cls, module: ApeModule, function_name: str) -> "ApeTask":
            """Extract task from compiled Ape module."""
            sig = module.get_function_signature(function_name)
            return cls(
                name=sig.name,
                inputs=sig.inputs,
                output=sig.output,
                description=sig.description
            )

        def validate_inputs(self, **kwargs) -> None:
            """Validate that provided arguments match expected inputs."""
            provided = set(kwargs.keys())
            required = set(self.inputs.keys())

            missing = required - provided
            if missing:
                raise TypeError(f"Missing required parameters: {', '.join(sorted(missing))}")

            unexpected = provided - required
            if unexpected:
                raise TypeError(f"Unexpected parameters: {', '.join(sorted(unexpected))}")
except ImportError:
    # Fallback if ape-lang not installed
    class ApeTask:  # type: ignore
        def __init__(self, *args, **kwargs):
            raise ImportError("ape-openai requires ape-lang to be installed")


# Aliases for compatibility with spec
def ape_task_to_openai_function(task: "ApeTask", description: str | None = None) -> dict:
    """
    Convert an ApeTask into an OpenAI function calling schema.
    
    Alias for ape_task_to_openai_schema() for compatibility.
    
    Args:
        task: ApeTask instance
        description: Optional override for function description
        
    Returns:
        OpenAI function schema dict
    """
    if description:
        # Temporarily override description
        original_desc = task.description
        task.description = description
        schema = ape_task_to_openai_schema(task)
        task.description = original_desc
        return schema
    return ape_task_to_openai_schema(task)


def execute_openai_function_call(module, task: "ApeTask", arguments_json: str):
    """
    Execute an OpenAI function call with full ApeTask validation.
    
    Alias for execute_openai_call() that accepts an ApeTask parameter.
    
    Args:
        module: Compiled ApeModule
        task: ApeTask instance for validation
        arguments_json: JSON string of arguments from OpenAI
        
    Returns:
        Function execution result
        
    Raises:
        ValueError: If required argument is missing
        json.JSONDecodeError: If JSON is invalid
    """
    import json
    
    # Parse arguments
    try:
        arguments = json.loads(arguments_json or "{}")
    except json.JSONDecodeError as e:
        raise json.JSONDecodeError(
            f"Invalid JSON in function arguments: {e}",
            e.doc,
            e.pos
        ) from e
    
    # Validate using ApeTask
    task.validate_inputs(**arguments)
    
    # Execute
    return execute_openai_call(module, task.name, arguments_json)


# Alias for generator with compatible name
def generate_ape_from_natural_language(
    prompt: str,
    model: str = "gpt-4",
    api_key: str | None = None
) -> str:
    """
    Use an OpenAI model to generate Ape code from natural language.
    
    Alias for generate_ape_from_nl() with full spec-compatible naming.
    
    Args:
        prompt: Natural language description of the task
        model: OpenAI model to use (default: "gpt-4")
        api_key: OpenAI API key (optional)
        
    Returns:
        Generated Ape code as string
        
    Raises:
        ImportError: If openai package not installed
        Exception: If generation fails
    """
    return generate_ape_from_nl(prompt, model, api_key)


__version__ = "0.1.2"

__all__ = [
    # Primary API
    "ape_task_to_openai_schema",
    "execute_openai_call",
    "ApeOpenAIFunction",
    "generate_ape_from_nl",
    "ApeTask",
    # Spec-compatible aliases
    "ape_task_to_openai_function",
    "execute_openai_function_call",
    "generate_ape_from_natural_language",
]

