"""Tests for the core module."""

import pytest

from aap.core import autoarg


def test_single_function_basic():
    """Test wrapping a single function with basic types."""
    def greet(name: str, age: int):
        """Greet a person.
        
        Args:
            name: Person's name
            age: Person's age
        """
        return f"Hello {name}, you are {age} years old"
    
    wrapped = autoarg(greet)
    result = wrapped(['--name', 'Alice', '--age', '30'])
    
    assert result == "Hello Alice, you are 30 years old"


def test_single_function_with_defaults():
    """Test wrapping a function with default values."""
    def greet(name: str, greeting: str = "Hello"):
        """Greet a person with a custom greeting.
        
        Args:
            name: Person's name
            greeting: The greeting to use
        """
        return f"{greeting} {name}"
    
    wrapped = autoarg(greet)
    
    # Test with default
    result1 = wrapped(['--name', 'Bob'])
    assert result1 == "Hello Bob"
    
    # Test with custom greeting
    result2 = wrapped(['--name', 'Bob', '--greeting', 'Hi'])
    assert result2 == "Hi Bob"


def test_single_function_with_bool_flag():
    """Test wrapping a function with boolean parameters."""
    def process(name: str, verbose: bool = False):
        """Process something.
        
        Args:
            name: Item name
            verbose: Enable verbose output
        """
        if verbose:
            return f"Processing {name} verbosely"
        return f"Processing {name}"
    
    wrapped = autoarg(process)
    
    # Test without flag
    result1 = wrapped(['--name', 'test'])
    assert result1 == "Processing test"
    
    # Test with flag
    result2 = wrapped(['--name', 'test', '--verbose'])
    assert result2 == "Processing test verbosely"


def test_single_function_with_bool_default_true():
    """Test wrapping a function with boolean default True."""
    def process(name: str, enabled: bool = True):
        """Process something.
        
        Args:
            name: Item name
            enabled: Whether processing is enabled
        """
        if enabled:
            return f"Processing {name}"
        return f"Skipping {name}"
    
    wrapped = autoarg(process)
    
    # Test with default (True)
    result1 = wrapped(['--name', 'test'])
    assert result1 == "Processing test"
    
    # Test with flag to disable
    result2 = wrapped(['--name', 'test', '--no-enabled'])
    assert result2 == "Skipping test"


def test_single_function_with_float():
    """Test wrapping a function with float parameters."""
    def calculate(value: float, multiplier: float = 2.0):
        """Calculate a value.
        
        Args:
            value: Input value
            multiplier: Multiplication factor
        """
        return value * multiplier
    
    wrapped = autoarg(calculate)
    result = wrapped(['--value', '3.5', '--multiplier', '2.5'])
    
    assert result == 3.5 * 2.5


def test_multiple_functions():
    """Test wrapping multiple functions as subcommands (now requires set)."""
    def add(a: int, b: int):
        """Add two numbers.
        
        Args:
            a: First number
            b: Second number
        """
        return a + b
    
    def multiply(a: int, b: int):
        """Multiply two numbers.
        
        Args:
            a: First number
            b: Second number
        """
        return a * b
    
    # Use set for commands
    wrapped = autoarg({add, multiply})
    
    # Test add command
    result1 = wrapped(['add', '--a', '5', '--b', '3'])
    assert result1 == 8
    
    # Test multiply command
    result2 = wrapped(['multiply', '--a', '5', '--b', '3'])
    assert result2 == 15


def test_multiple_functions_different_params():
    """Test multiple functions with different parameter sets (now requires set)."""
    def greet(name: str):
        """Greet someone.
        
        Args:
            name: Person's name
        """
        return f"Hello {name}"
    
    def calculate(x: int, y: int, operation: str = "add"):
        """Perform a calculation.
        
        Args:
            x: First number
            y: Second number
            operation: Operation to perform
        """
        if operation == "add":
            return x + y
        elif operation == "multiply":
            return x * y
        return 0
    
    # Use set for commands
    wrapped = autoarg({greet, calculate})
    
    # Test greet
    result1 = wrapped(['greet', '--name', 'Alice'])
    assert result1 == "Hello Alice"
    
    # Test calculate with default
    result2 = wrapped(['calculate', '--x', '10', '--y', '5'])
    assert result2 == 15
    
    # Test calculate with custom operation
    result3 = wrapped(['calculate', '--x', '10', '--y', '5', '--operation', 'multiply'])
    assert result3 == 50


def test_function_with_list_parameter():
    """Test wrapping a function with List type parameter."""
    from typing import List
    
    def sum_numbers(numbers: List[int]):
        """Sum a list of numbers.
        
        Args:
            numbers: List of integers to sum
        """
        return sum(numbers)
    
    wrapped = autoarg(sum_numbers)
    result = wrapped(['--numbers', '1', '2', '3', '4', '5'])
    
    assert result == 15


def test_function_with_optional_parameter():
    """Test wrapping a function with Optional type parameter."""
    from typing import Optional
    
    def greet(name: str, title: Optional[str] = None):
        """Greet someone with optional title.
        
        Args:
            name: Person's name
            title: Optional title
        """
        if title:
            return f"Hello {title} {name}"
        return f"Hello {name}"
    
    wrapped = autoarg(greet)
    
    # Test without optional
    result1 = wrapped(['--name', 'Smith'])
    assert result1 == "Hello Smith"
    
    # Test with optional
    result2 = wrapped(['--name', 'Smith', '--title', 'Dr.'])
    assert result2 == "Hello Dr. Smith"


def test_function_without_docstring():
    """Test wrapping a function without docstring."""
    def simple_func(x: int):
        return x * 2
    
    wrapped = autoarg(simple_func)
    result = wrapped(['--x', '5'])
    
    assert result == 10


def test_function_with_underscore_params():
    """Test that underscored parameter names are converted to dashes."""
    def process_data(file_name: str, output_dir: str = "/tmp"):
        """Process data from a file.
        
        Args:
            file_name: Input file name
            output_dir: Output directory
        """
        return f"Processing {file_name} to {output_dir}"
    
    wrapped = autoarg(process_data)
    result = wrapped(['--file-name', 'data.txt', '--output-dir', '/home'])
    
    assert result == "Processing data.txt to /home"


def test_help_includes_defaults():
    """Test that help text includes default values."""
    def func_with_defaults(name: str, count: int = 5, rate: float = 1.5):
        """A function with defaults.
        
        Args:
            name: The name
            count: Number of items
            rate: Processing rate
        """
        return f"{name}: {count} at {rate}"
    
    wrapped = autoarg(func_with_defaults)
    
    # This test verifies the function works; actual help text testing
    # would require capturing argparse output
    result = wrapped(['--name', 'test'])
    assert result == "test: 5 at 1.5"
