#!/usr/bin/env python3
"""
Tool Schema Generator - Generate structured tool schemas for AI agents

Given a description of desired tools (name, purpose, inputs, outputs), generates
structured tool schemas compatible with OpenAI function calling format and 
Anthropic tool use format. Includes: input validation rules, error response 
formats, example calls, rate limit suggestions.

Input: tool descriptions JSON
Output: tool schemas (OpenAI + Anthropic format) + validation rules + example usage
"""

import json
import argparse
import sys
import re
from typing import Dict, List, Any, Optional, Union, Tuple
from dataclasses import dataclass, asdict
from enum import Enum


class ParameterType(Enum):
    """Parameter types for tool schemas"""
    STRING = "string"
    INTEGER = "integer"
    NUMBER = "number"
    BOOLEAN = "boolean"
    ARRAY = "array"
    OBJECT = "object"
    NULL = "null"


class ValidationRule(Enum):
    """Validation rule types"""
    REQUIRED = "required"
    MIN_LENGTH = "min_length"
    MAX_LENGTH = "max_length"
    PATTERN = "pattern"
    ENUM = "enum"
    MINIMUM = "minimum"
    MAXIMUM = "maximum"
    MIN_ITEMS = "min_items"
    MAX_ITEMS = "max_items"
    UNIQUE_ITEMS = "unique_items"
    FORMAT = "format"


@dataclass
class ParameterSpec:
    """Parameter specification for tool inputs/outputs"""
    name: str
    type: ParameterType
    description: str
    required: bool = False
    default: Any = None
    validation_rules: Dict[str, Any] = None
    examples: List[Any] = None
    deprecated: bool = False


@dataclass
class ErrorSpec:
    """Error specification for tool responses"""
    error_code: str
    error_message: str
    http_status: int
    retry_after: Optional[int] = None
    details: Dict[str, Any] = None


@dataclass
class RateLimitSpec:
    """Rate limiting specification"""
    requests_per_minute: int
    requests_per_hour: int
    requests_per_day: int
    burst_limit: int
    cooldown_period: int
    rate_limit_key: str = "user_id"


@dataclass
class ToolDescription:
    """Input tool description"""
    name: str
    purpose: str
    category: str
    inputs: List[Dict[str, Any]]
    outputs: List[Dict[str, Any]]
    error_conditions: List[str]
    side_effects: List[str]
    idempotent: bool
    rate_limits: Dict[str, Any]
    dependencies: List[str]
    examples: List[Dict[str, Any]]
    security_requirements: List[str]


@dataclass
class ToolSchema:
    """Complete tool schema with validation and examples"""
    name: str
    description: str
    openai_schema: Dict[str, Any]
    anthropic_schema: Dict[str, Any]
    validation_rules: List[Dict[str, Any]]
    error_responses: List[ErrorSpec]
    rate_limits: RateLimitSpec
    examples: List[Dict[str, Any]]
    metadata: Dict[str, Any]


class ToolSchemaGenerator:
    """Generate structured tool schemas from descriptions"""
    
    def __init__(self):
        self.common_patterns = self._define_common_patterns()
        self.format_validators = self._define_format_validators()
        self.security_templates = self._define_security_templates()
    
    def _define_common_patterns(self) -> Dict[str, str]:
        """Define common regex patterns for validation"""
        return {
            "email": r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
            "url": r"^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$",
            "uuid": r"^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
            "phone": r"^\+?1?[0-9]{10,15}$",
            "ip_address": r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
            "date": r"^\d{4}-\d{2}-\d{2}$",
            "datetime": r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z?$",
            "slug": r"^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "semantic_version": r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
        }
    
    def _define_format_validators(self) -> Dict[str, Dict[str, Any]]:
        """Define format validators for common data types"""
        return {
            "email": {
                "type": "string",
                "format": "email",
                "pattern": self.common_patterns["email"],
                "min_length": 5,
                "max_length": 254
            },
            "url": {
                "type": "string",
                "format": "uri",
                "pattern": self.common_patterns["url"],
                "min_length": 7,
                "max_length": 2048
            },
            "uuid": {
                "type": "string",
                "format": "uuid",
                "pattern": self.common_patterns["uuid"],
                "min_length": 36,
                "max_length": 36
            },
            "date": {
                "type": "string",
                "format": "date",
                "pattern": self.common_patterns["date"],
                "min_length": 10,
                "max_length": 10
            },
            "datetime": {
                "type": "string",
                "format": "date-time",
                "pattern": self.common_patterns["datetime"],
                "min_length": 19,
                "max_length": 30
            },
            "password": {
                "type": "string",
                "min_length": 8,
                "max_length": 128,
                "pattern": r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]"
            }
        }
    
    def _define_security_templates(self) -> Dict[str, Dict[str, Any]]:
        """Define security requirement templates"""
        return {
            "authentication_required": {
                "requires_auth": True,
                "auth_methods": ["bearer_token", "api_key"],
                "scope_required": ["read", "write"]
            },
            "rate_limited": {
                "rate_limits": {
                    "requests_per_minute": 60,
                    "requests_per_hour": 1000,
                    "burst_limit": 10
                }
            },
            "input_sanitization": {
                "sanitize_html": True,
                "validate_sql_injection": True,
                "escape_special_chars": True
            },
            "output_validation": {
                "validate_response_schema": True,
                "filter_sensitive_data": True,
                "content_type_validation": True
            }
        }
    
    def parse_tool_description(self, description: ToolDescription) -> ParameterSpec:
        """Parse tool description into structured parameters"""
        input_params = []
        output_params = []
        
        # Parse input parameters
        for input_spec in description.inputs:
            param = self._parse_parameter_spec(input_spec)
            input_params.append(param)
        
        # Parse output parameters
        for output_spec in description.outputs:
            param = self._parse_parameter_spec(output_spec)
            output_params.append(param)
        
        return input_params, output_params
    
    def _parse_parameter_spec(self, param_spec: Dict[str, Any]) -> ParameterSpec:
        """Parse individual parameter specification"""
        name = param_spec.get("name", "")
        type_str = param_spec.get("type", "string")
        description = param_spec.get("description", "")
        required = param_spec.get("required", False)
        default = param_spec.get("default")
        examples = param_spec.get("examples", [])
        
        # Parse parameter type
        param_type = self._parse_parameter_type(type_str)
        
        # Generate validation rules
        validation_rules = self._generate_validation_rules(param_spec, param_type)
        
        return ParameterSpec(
            name=name,
            type=param_type,
            description=description,
            required=required,
            default=default,
            validation_rules=validation_rules,
            examples=examples
        )
    
    def _parse_parameter_type(self, type_str: str) -> ParameterType:
        """Parse parameter type from string"""
        type_mapping = {
            "str": ParameterType.STRING,
            "string": ParameterType.STRING,
            "text": ParameterType.STRING,
            "int": ParameterType.INTEGER,
            "integer": ParameterType.INTEGER,
            "float": ParameterType.NUMBER,
            "number": ParameterType.NUMBER,
            "bool": ParameterType.BOOLEAN,
            "boolean": ParameterType.BOOLEAN,
            "list": ParameterType.ARRAY,
            "array": ParameterType.ARRAY,
            "dict": ParameterType.OBJECT,
            "object": ParameterType.OBJECT,
            "null": ParameterType.NULL,
            "none": ParameterType.NULL
        }
        
        return type_mapping.get(type_str.lower(), ParameterType.STRING)
    
    def _generate_validation_rules(self, param_spec: Dict[str, Any], param_type: ParameterType) -> Dict[str, Any]:
        """Generate validation rules for a parameter"""
        rules = {}
        
        # Type-specific validation
        if param_type == ParameterType.STRING:
            rules.update(self._generate_string_validation(param_spec))
        elif param_type == ParameterType.INTEGER:
            rules.update(self._generate_integer_validation(param_spec))
        elif param_type == ParameterType.NUMBER:
            rules.update(self._generate_number_validation(param_spec))
        elif param_type == ParameterType.ARRAY:
            rules.update(self._generate_array_validation(param_spec))
        elif param_type == ParameterType.OBJECT:
            rules.update(self._generate_object_validation(param_spec))
        
        # Common validation rules
        if param_spec.get("required", False):
            rules["required"] = True
        
        if "enum" in param_spec:
            rules["enum"] = param_spec["enum"]
        
        if "pattern" in param_spec:
            rules["pattern"] = param_spec["pattern"]
        elif self._detect_format(param_spec.get("name", ""), param_spec.get("description", "")):
            format_name = self._detect_format(param_spec.get("name", ""), param_spec.get("description", ""))
            if format_name in self.format_validators:
                rules.update(self.format_validators[format_name])
        
        return rules
    
    def _generate_string_validation(self, param_spec: Dict[str, Any]) -> Dict[str, Any]:
        """Generate string-specific validation rules"""
        rules = {}
        
        if "min_length" in param_spec:
            rules["minLength"] = param_spec["min_length"]
        elif "min_len" in param_spec:
            rules["minLength"] = param_spec["min_len"]
        else:
            # Infer from description
            desc = param_spec.get("description", "").lower()
            if "password" in desc:
                rules["minLength"] = 8
            elif "email" in desc:
                rules["minLength"] = 5
            elif "name" in desc:
                rules["minLength"] = 1
        
        if "max_length" in param_spec:
            rules["maxLength"] = param_spec["max_length"]
        elif "max_len" in param_spec:
            rules["maxLength"] = param_spec["max_len"]
        else:
            # Reasonable defaults
            desc = param_spec.get("description", "").lower()
            if "password" in desc:
                rules["maxLength"] = 128
            elif "email" in desc:
                rules["maxLength"] = 254
            elif "description" in desc or "content" in desc:
                rules["maxLength"] = 10000
            elif "name" in desc or "title" in desc:
                rules["maxLength"] = 255
            else:
                rules["maxLength"] = 1000
        
        return rules
    
    def _generate_integer_validation(self, param_spec: Dict[str, Any]) -> Dict[str, Any]:
        """Generate integer-specific validation rules"""
        rules = {}
        
        if "minimum" in param_spec:
            rules["minimum"] = param_spec["minimum"]
        elif "min" in param_spec:
            rules["minimum"] = param_spec["min"]
        else:
            # Infer from context
            name = param_spec.get("name", "").lower()
            desc = param_spec.get("description", "").lower()
            if any(word in name + desc for word in ["count", "quantity", "amount", "size", "limit"]):
                rules["minimum"] = 0
            elif "page" in name + desc:
                rules["minimum"] = 1
            elif "port" in name + desc:
                rules["minimum"] = 1
                rules["maximum"] = 65535
        
        if "maximum" in param_spec:
            rules["maximum"] = param_spec["maximum"]
        elif "max" in param_spec:
            rules["maximum"] = param_spec["max"]
        
        return rules
    
    def _generate_number_validation(self, param_spec: Dict[str, Any]) -> Dict[str, Any]:
        """Generate number-specific validation rules"""
        rules = {}
        
        if "minimum" in param_spec:
            rules["minimum"] = param_spec["minimum"]
        if "maximum" in param_spec:
            rules["maximum"] = param_spec["maximum"]
        if "exclusive_minimum" in param_spec:
            rules["exclusiveMinimum"] = param_spec["exclusive_minimum"]
        if "exclusive_maximum" in param_spec:
            rules["exclusiveMaximum"] = param_spec["exclusive_maximum"]
        if "multiple_of" in param_spec:
            rules["multipleOf"] = param_spec["multiple_of"]
        
        return rules
    
    def _generate_array_validation(self, param_spec: Dict[str, Any]) -> Dict[str, Any]:
        """Generate array-specific validation rules"""
        rules = {}
        
        if "min_items" in param_spec:
            rules["minItems"] = param_spec["min_items"]
        elif "min_length" in param_spec:
            rules["minItems"] = param_spec["min_length"]
        else:
            rules["minItems"] = 0
        
        if "max_items" in param_spec:
            rules["maxItems"] = param_spec["max_items"]
        elif "max_length" in param_spec:
            rules["maxItems"] = param_spec["max_length"]
        else:
            rules["maxItems"] = 1000  # Reasonable default
        
        if param_spec.get("unique_items", False):
            rules["uniqueItems"] = True
        
        if "item_type" in param_spec:
            rules["items"] = {"type": param_spec["item_type"]}
        
        return rules
    
    def _generate_object_validation(self, param_spec: Dict[str, Any]) -> Dict[str, Any]:
        """Generate object-specific validation rules"""
        rules = {}
        
        if "properties" in param_spec:
            rules["properties"] = param_spec["properties"]
        
        if "required_properties" in param_spec:
            rules["required"] = param_spec["required_properties"]
        
        if "additional_properties" in param_spec:
            rules["additionalProperties"] = param_spec["additional_properties"]
        else:
            rules["additionalProperties"] = False
        
        if "min_properties" in param_spec:
            rules["minProperties"] = param_spec["min_properties"]
        
        if "max_properties" in param_spec:
            rules["maxProperties"] = param_spec["max_properties"]
        
        return rules
    
    def _detect_format(self, name: str, description: str) -> Optional[str]:
        """Detect parameter format from name and description"""
        combined = (name + " " + description).lower()
        
        format_indicators = {
            "email": ["email", "e-mail", "email_address"],
            "url": ["url", "uri", "link", "website", "endpoint"],
            "uuid": ["uuid", "guid", "identifier", "id"],
            "date": ["date", "birthday", "created_date", "modified_date"],
            "datetime": ["datetime", "timestamp", "created_at", "updated_at"],
            "password": ["password", "secret", "token", "api_key"]
        }
        
        for format_name, indicators in format_indicators.items():
            if any(indicator in combined for indicator in indicators):
                return format_name
        
        return None
    
    def generate_openai_schema(self, description: ToolDescription, input_params: List[ParameterSpec]) -> Dict[str, Any]:
        """Generate OpenAI function calling schema"""
        properties = {}
        required = []
        
        for param in input_params:
            prop_def = {
                "type": param.type.value,
                "description": param.description
            }
            
            # Add validation rules
            if param.validation_rules:
                prop_def.update(param.validation_rules)
            
            # Add examples
            if param.examples:
                prop_def["examples"] = param.examples
            
            # Add default value
            if param.default is not None:
                prop_def["default"] = param.default
            
            properties[param.name] = prop_def
            
            if param.required:
                required.append(param.name)
        
        schema = {
            "name": description.name,
            "description": description.purpose,
            "parameters": {
                "type": "object",
                "properties": properties,
                "required": required,
                "additionalProperties": False
            }
        }
        
        return schema
    
    def generate_anthropic_schema(self, description: ToolDescription, input_params: List[ParameterSpec]) -> Dict[str, Any]:
        """Generate Anthropic tool use schema"""
        input_schema = {
            "type": "object",
            "properties": {},
            "required": []
        }
        
        for param in input_params:
            prop_def = {
                "type": param.type.value,
                "description": param.description
            }
            
            # Add validation rules (Anthropic uses subset of JSON Schema)
            if param.validation_rules:
                # Filter to supported validation rules
                supported_rules = ["minLength", "maxLength", "minimum", "maximum", "pattern", "enum", "items"]
                for rule, value in param.validation_rules.items():
                    if rule in supported_rules:
                        prop_def[rule] = value
            
            input_schema["properties"][param.name] = prop_def
            
            if param.required:
                input_schema["required"].append(param.name)
        
        schema = {
            "name": description.name,
            "description": description.purpose,
            "input_schema": input_schema
        }
        
        return schema
    
    def generate_error_responses(self, description: ToolDescription) -> List[ErrorSpec]:
        """Generate error response specifications"""
        error_specs = []
        
        # Common errors
        common_errors = [
            {
                "error_code": "invalid_input",
                "error_message": "Invalid input parameters provided",
                "http_status": 400,
                "details": {"validation_errors": []}
            },
            {
                "error_code": "authentication_required",
                "error_message": "Authentication required to access this tool",
                "http_status": 401
            },
            {
                "error_code": "insufficient_permissions",
                "error_message": "Insufficient permissions to perform this operation",
                "http_status": 403
            },
            {
                "error_code": "rate_limit_exceeded",
                "error_message": "Rate limit exceeded. Please try again later",
                "http_status": 429,
                "retry_after": 60
            },
            {
                "error_code": "internal_error",
                "error_message": "Internal server error occurred",
                "http_status": 500
            },
            {
                "error_code": "service_unavailable",
                "error_message": "Service temporarily unavailable",
                "http_status": 503,
                "retry_after": 300
            }
        ]
        
        # Add common errors
        for error in common_errors:
            error_specs.append(ErrorSpec(**error))
        
        # Add tool-specific errors based on error conditions
        for condition in description.error_conditions:
            if "not found" in condition.lower():
                error_specs.append(ErrorSpec(
                    error_code="resource_not_found",
                    error_message=f"Requested resource not found: {condition}",
                    http_status=404
                ))
            elif "timeout" in condition.lower():
                error_specs.append(ErrorSpec(
                    error_code="operation_timeout",
                    error_message=f"Operation timed out: {condition}",
                    http_status=408,
                    retry_after=30
                ))
            elif "quota" in condition.lower() or "limit" in condition.lower():
                error_specs.append(ErrorSpec(
                    error_code="quota_exceeded",
                    error_message=f"Quota or limit exceeded: {condition}",
                    http_status=429,
                    retry_after=3600
                ))
            elif "dependency" in condition.lower():
                error_specs.append(ErrorSpec(
                    error_code="dependency_failure",
                    error_message=f"Dependency service failure: {condition}",
                    http_status=502
                ))
        
        return error_specs
    
    def generate_rate_limits(self, description: ToolDescription) -> RateLimitSpec:
        """Generate rate limiting specification"""
        rate_limits = description.rate_limits
        
        # Default rate limits based on tool category
        defaults = {
            "search": {"rpm": 60, "rph": 1000, "rpd": 10000, "burst": 10},
            "data": {"rpm": 30, "rph": 500, "rpd": 5000, "burst": 5},
            "api": {"rpm": 100, "rph": 2000, "rpd": 20000, "burst": 20},
            "file": {"rpm": 120, "rph": 3000, "rpd": 30000, "burst": 30},
            "compute": {"rpm": 10, "rph": 100, "rpd": 1000, "burst": 3},
            "communication": {"rpm": 30, "rph": 300, "rpd": 3000, "burst": 5}
        }
        
        category_defaults = defaults.get(description.category.lower(), defaults["api"])
        
        return RateLimitSpec(
            requests_per_minute=rate_limits.get("requests_per_minute", category_defaults["rpm"]),
            requests_per_hour=rate_limits.get("requests_per_hour", category_defaults["rph"]),
            requests_per_day=rate_limits.get("requests_per_day", category_defaults["rpd"]),
            burst_limit=rate_limits.get("burst_limit", category_defaults["burst"]),
            cooldown_period=rate_limits.get("cooldown_period", 60),
            rate_limit_key=rate_limits.get("rate_limit_key", "user_id")
        )
    
    def generate_examples(self, description: ToolDescription, input_params: List[ParameterSpec]) -> List[Dict[str, Any]]:
        """Generate usage examples"""
        examples = []
        
        # Use provided examples if available
        if description.examples:
            for example in description.examples:
                examples.append(example)
        
        # Generate synthetic examples
        if len(examples) == 0:
            synthetic_example = self._generate_synthetic_example(description, input_params)
            if synthetic_example:
                examples.append(synthetic_example)
        
        # Ensure we have multiple examples showing different scenarios
        if len(examples) == 1 and len(input_params) > 1:
            # Generate minimal example
            minimal_example = self._generate_minimal_example(description, input_params)
            if minimal_example and minimal_example != examples[0]:
                examples.append(minimal_example)
        
        return examples
    
    def _generate_synthetic_example(self, description: ToolDescription, input_params: List[ParameterSpec]) -> Dict[str, Any]:
        """Generate a synthetic example based on parameter specifications"""
        example_input = {}
        
        for param in input_params:
            if param.examples:
                example_input[param.name] = param.examples[0]
            elif param.default is not None:
                example_input[param.name] = param.default
            else:
                example_input[param.name] = self._generate_example_value(param)
        
        # Generate expected output based on tool purpose
        expected_output = self._generate_example_output(description)
        
        return {
            "description": f"Example usage of {description.name}",
            "input": example_input,
            "expected_output": expected_output
        }
    
    def _generate_minimal_example(self, description: ToolDescription, input_params: List[ParameterSpec]) -> Dict[str, Any]:
        """Generate minimal example with only required parameters"""
        example_input = {}
        
        for param in input_params:
            if param.required:
                if param.examples:
                    example_input[param.name] = param.examples[0]
                else:
                    example_input[param.name] = self._generate_example_value(param)
        
        if not example_input:
            return None
        
        expected_output = self._generate_example_output(description)
        
        return {
            "description": f"Minimal example of {description.name} with required parameters only",
            "input": example_input,
            "expected_output": expected_output
        }
    
    def _generate_example_value(self, param: ParameterSpec) -> Any:
        """Generate example value for a parameter"""
        if param.type == ParameterType.STRING:
            format_examples = {
                "email": "user@example.com",
                "url": "https://example.com",
                "uuid": "123e4567-e89b-12d3-a456-426614174000",
                "date": "2024-01-15",
                "datetime": "2024-01-15T10:30:00Z"
            }
            
            # Check for format in validation rules
            if param.validation_rules and "format" in param.validation_rules:
                format_type = param.validation_rules["format"]
                if format_type in format_examples:
                    return format_examples[format_type]
            
            # Check for patterns or enum
            if param.validation_rules:
                if "enum" in param.validation_rules:
                    return param.validation_rules["enum"][0]
            
            # Generate based on name/description
            name_lower = param.name.lower()
            if "name" in name_lower:
                return "example_name"
            elif "query" in name_lower or "search" in name_lower:
                return "search query"
            elif "path" in name_lower:
                return "/path/to/resource"
            elif "message" in name_lower:
                return "Example message"
            else:
                return "example_value"
        
        elif param.type == ParameterType.INTEGER:
            if param.validation_rules:
                min_val = param.validation_rules.get("minimum", 0)
                max_val = param.validation_rules.get("maximum", 100)
                return min(max(42, min_val), max_val)
            return 42
        
        elif param.type == ParameterType.NUMBER:
            if param.validation_rules:
                min_val = param.validation_rules.get("minimum", 0.0)
                max_val = param.validation_rules.get("maximum", 100.0)
                return min(max(42.5, min_val), max_val)
            return 42.5
        
        elif param.type == ParameterType.BOOLEAN:
            return True
        
        elif param.type == ParameterType.ARRAY:
            return ["item1", "item2"]
        
        elif param.type == ParameterType.OBJECT:
            return {"key": "value"}
        
        else:
            return None
    
    def _generate_example_output(self, description: ToolDescription) -> Dict[str, Any]:
        """Generate example output based on tool description"""
        category = description.category.lower()
        
        if category == "search":
            return {
                "results": [
                    {"title": "Example Result 1", "url": "https://example.com/1", "snippet": "Example snippet..."},
                    {"title": "Example Result 2", "url": "https://example.com/2", "snippet": "Another snippet..."}
                ],
                "total_count": 2
            }
        elif category == "data":
            return {
                "data": [{"id": 1, "value": "example"}, {"id": 2, "value": "another"}],
                "metadata": {"count": 2, "processed_at": "2024-01-15T10:30:00Z"}
            }
        elif category == "file":
            return {
                "success": True,
                "file_path": "/path/to/file.txt",
                "size": 1024,
                "modified_at": "2024-01-15T10:30:00Z"
            }
        elif category == "api":
            return {
                "status": "success",
                "data": {"result": "operation completed successfully"},
                "timestamp": "2024-01-15T10:30:00Z"
            }
        else:
            return {
                "success": True,
                "message": f"{description.name} executed successfully",
                "result": "example result"
            }
    
    def generate_tool_schema(self, description: ToolDescription) -> ToolSchema:
        """Generate complete tool schema"""
        # Parse parameters
        input_params, output_params = self.parse_tool_description(description)
        
        # Generate schemas
        openai_schema = self.generate_openai_schema(description, input_params)
        anthropic_schema = self.generate_anthropic_schema(description, input_params)
        
        # Generate validation rules
        validation_rules = []
        for param in input_params:
            if param.validation_rules:
                validation_rules.append({
                    "parameter": param.name,
                    "rules": param.validation_rules
                })
        
        # Generate error responses
        error_responses = self.generate_error_responses(description)
        
        # Generate rate limits
        rate_limits = self.generate_rate_limits(description)
        
        # Generate examples
        examples = self.generate_examples(description, input_params)
        
        # Generate metadata
        metadata = {
            "category": description.category,
            "idempotent": description.idempotent,
            "side_effects": description.side_effects,
            "dependencies": description.dependencies,
            "security_requirements": description.security_requirements,
            "generated_at": "2024-01-15T10:30:00Z",
            "schema_version": "1.0",
            "input_parameters": len(input_params),
            "output_parameters": len(output_params),
            "required_parameters": sum(1 for p in input_params if p.required),
            "optional_parameters": sum(1 for p in input_params if not p.required)
        }
        
        return ToolSchema(
            name=description.name,
            description=description.purpose,
            openai_schema=openai_schema,
            anthropic_schema=anthropic_schema,
            validation_rules=validation_rules,
            error_responses=error_responses,
            rate_limits=rate_limits,
            examples=examples,
            metadata=metadata
        )


def main():
    parser = argparse.ArgumentParser(description="Tool Schema Generator for AI Agents")
    parser.add_argument("input_file", help="JSON file with tool descriptions")
    parser.add_argument("-o", "--output", help="Output file prefix (default: tool_schemas)")
    parser.add_argument("--format", choices=["json", "both"], default="both", 
                       help="Output format")
    parser.add_argument("--validate", action="store_true", 
                       help="Validate generated schemas")
    
    args = parser.parse_args()
    
    try:
        # Load tool descriptions
        with open(args.input_file, 'r') as f:
            tools_data = json.load(f)
        
        # Parse tool descriptions
        tool_descriptions = []
        for tool_data in tools_data.get("tools", []):
            tool_desc = ToolDescription(**tool_data)
            tool_descriptions.append(tool_desc)
        
        # Generate schemas
        generator = ToolSchemaGenerator()
        schemas = []
        
        for description in tool_descriptions:
            schema = generator.generate_tool_schema(description)
            schemas.append(schema)
            print(f"Generated schema for: {schema.name}")
        
        # Prepare output
        output_data = {
            "tool_schemas": [asdict(schema) for schema in schemas],
            "metadata": {
                "generated_by": "tool_schema_generator.py",
                "input_file": args.input_file,
                "tool_count": len(schemas),
                "generation_timestamp": "2024-01-15T10:30:00Z",
                "schema_version": "1.0"
            },
            "validation_summary": {
                "total_tools": len(schemas),
                "total_parameters": sum(schema.metadata["input_parameters"] for schema in schemas),
                "total_validation_rules": sum(len(schema.validation_rules) for schema in schemas),
                "total_examples": sum(len(schema.examples) for schema in schemas)
            }
        }
        
        # Output files
        output_prefix = args.output or "tool_schemas"
        
        if args.format in ["json", "both"]:
            with open(f"{output_prefix}.json", 'w') as f:
                json.dump(output_data, f, indent=2, default=str)
            print(f"JSON output written to {output_prefix}.json")
        
        if args.format == "both":
            # Generate separate files for different formats
            
            # OpenAI format
            openai_schemas = {
                "functions": [schema.openai_schema for schema in schemas]
            }
            with open(f"{output_prefix}_openai.json", 'w') as f:
                json.dump(openai_schemas, f, indent=2)
            print(f"OpenAI schemas written to {output_prefix}_openai.json")
            
            # Anthropic format
            anthropic_schemas = {
                "tools": [schema.anthropic_schema for schema in schemas]
            }
            with open(f"{output_prefix}_anthropic.json", 'w') as f:
                json.dump(anthropic_schemas, f, indent=2)
            print(f"Anthropic schemas written to {output_prefix}_anthropic.json")
            
            # Validation rules
            validation_data = {
                "validation_rules": {schema.name: schema.validation_rules for schema in schemas}
            }
            with open(f"{output_prefix}_validation.json", 'w') as f:
                json.dump(validation_data, f, indent=2)
            print(f"Validation rules written to {output_prefix}_validation.json")
            
            # Usage examples
            examples_data = {
                "examples": {schema.name: schema.examples for schema in schemas}
            }
            with open(f"{output_prefix}_examples.json", 'w') as f:
                json.dump(examples_data, f, indent=2)
            print(f"Usage examples written to {output_prefix}_examples.json")
        
        # Print summary
        print(f"\nSchema Generation Summary:")
        print(f"Tools processed: {len(schemas)}")
        print(f"Total input parameters: {sum(schema.metadata['input_parameters'] for schema in schemas)}")
        print(f"Total validation rules: {sum(len(schema.validation_rules) for schema in schemas)}")
        print(f"Total examples generated: {sum(len(schema.examples) for schema in schemas)}")
        
        # Validation if requested
        if args.validate:
            print("\nValidation Results:")
            for schema in schemas:
                validation_errors = []
                
                # Basic validation checks
                if not schema.openai_schema.get("parameters", {}).get("properties"):
                    validation_errors.append("Missing input parameters")
                
                if not schema.examples:
                    validation_errors.append("No usage examples")
                
                if not schema.validation_rules:
                    validation_errors.append("No validation rules defined")
                
                if validation_errors:
                    print(f"  {schema.name}: {', '.join(validation_errors)}")
                else:
                    print(f"  {schema.name}: ✓ Valid")
        
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()