"""Tests for sequence functionality (list of callables)."""

import pytest

from aap.core import autoarg


def test_sequence_no_conflicts_unix():
    """Test sequence with no parameter conflicts, unix return type (default)."""
    def step1(name: str):
        """First step.
        
        Args:
            name: The name
        """
        return f"Step1: {name}"
    
    def step2(count: int):
        """Second step.
        
        Args:
            count: The count
        """
        return f"Step2: {count}"
    
    wrapped = autoarg([step1, step2])
    result = wrapped(['--name', 'Alice', '--count', '5'])
    
    # Unix mode returns last result
    assert result == "Step2: 5"


def test_sequence_no_conflicts_list():
    """Test sequence with no parameter conflicts, list return type."""
    def step1(name: str):
        """First step.
        
        Args:
            name: The name
        """
        return f"Step1: {name}"
    
    def step2(count: int):
        """Second step.
        
        Args:
            count: The count
        """
        return f"Step2: {count}"
    
    wrapped = autoarg([step1, step2], return_type="list")
    result = wrapped(['--name', 'Alice', '--count', '5'])
    
    # List mode returns all results
    assert result == ["Step1: Alice", "Step2: 5"]


def test_sequence_no_conflicts_dict():
    """Test sequence with no parameter conflicts, dict return type."""
    def step1(name: str):
        """First step.
        
        Args:
            name: The name
        """
        return f"Step1: {name}"
    
    def step2(count: int):
        """Second step.
        
        Args:
            count: The count
        """
        return f"Step2: {count}"
    
    wrapped = autoarg([step1, step2], return_type="dict")
    result = wrapped(['--name', 'Alice', '--count', '5'])
    
    # Dict mode returns name->result mapping
    assert result == {
        "step1": "Step1: Alice",
        "step2": "Step2: 5"
    }


def test_sequence_with_conflicts():
    """Test sequence with conflicting parameter names."""
    def step1(name: str, count: int):
        """First step.
        
        Args:
            name: First name
            count: First count
        """
        return f"Step1: {name} x {count}"
    
    def step2(name: str, value: float):
        """Second step.
        
        Args:
            name: Second name
            value: A value
        """
        return f"Step2: {name} = {value}"
    
    wrapped = autoarg([step1, step2], return_type="list")
    result = wrapped([
        '--step1-name', 'Alice',
        '--count', '5',
        '--step2-name', 'Bob',
        '--value', '3.14'
    ])
    
    assert result == ["Step1: Alice x 5", "Step2: Bob = 3.14"]


def test_sequence_three_functions():
    """Test sequence with three functions."""
    def add(a: int, b: int):
        """Add two numbers.
        
        Args:
            a: First number
            b: Second number
        """
        return a + b
    
    def multiply(x: int, y: int):
        """Multiply two numbers.
        
        Args:
            x: First number
            y: Second number
        """
        return x * y
    
    def format_result(result: int):
        """Format the result.
        
        Args:
            result: The result to format
        """
        return f"Result: {result}"
    
    wrapped = autoarg([add, multiply, format_result], return_type="list")
    result = wrapped([
        '--a', '5',
        '--b', '3',
        '--x', '2',
        '--y', '4',
        '--result', '100'
    ])
    
    assert result == [8, 8, "Result: 100"]


def test_sequence_with_defaults():
    """Test sequence where functions have default values."""
    def step1(name: str, prefix: str = "Hello"):
        """First step.
        
        Args:
            name: The name
            prefix: Greeting prefix
        """
        return f"{prefix} {name}"
    
    def step2(suffix: str = "!"):
        """Second step.
        
        Args:
            suffix: Suffix to add
        """
        return f"Done{suffix}"
    
    wrapped = autoarg([step1, step2], return_type="list")
    
    # Test with defaults
    result1 = wrapped(['--name', 'Alice'])
    assert result1 == ["Hello Alice", "Done!"]
    
    # Test with custom values
    result2 = wrapped(['--name', 'Bob', '--prefix', 'Hi', '--suffix', '!!!'])
    assert result2 == ["Hi Bob", "Done!!!"]


def test_sequence_conflict_with_different_types():
    """Test sequence where conflicting params have different types."""
    def step1(value: int):
        """First step.
        
        Args:
            value: An integer value
        """
        return value * 2
    
    def step2(value: str):
        """Second step.
        
        Args:
            value: A string value
        """
        return f"Value: {value}"
    
    wrapped = autoarg([step1, step2], return_type="list")
    result = wrapped(['--step1-value', '10', '--step2-value', 'hello'])
    
    assert result == [20, "Value: hello"]


def test_sequence_conflict_with_defaults():
    """Test sequence where conflicting params have different defaults."""
    def step1(name: str, enabled: bool = True):
        """First step.
        
        Args:
            name: The name
            enabled: Whether enabled
        """
        return f"Step1: {name} ({'on' if enabled else 'off'})"
    
    def step2(name: str, enabled: bool = False):
        """Second step.
        
        Args:
            name: The name
            enabled: Whether enabled
        """
        return f"Step2: {name} ({'on' if enabled else 'off'})"
    
    wrapped = autoarg([step1, step2], return_type="list")
    
    # Test with defaults
    result1 = wrapped(['--step1-name', 'Alice', '--step2-name', 'Bob'])
    assert result1 == ["Step1: Alice (on)", "Step2: Bob (off)"]
    
    # Test with flags
    result2 = wrapped([
        '--step1-name', 'Alice',
        '--no-step1-enabled',
        '--step2-name', 'Bob',
        '--step2-enabled'
    ])
    assert result2 == ["Step1: Alice (off)", "Step2: Bob (on)"]


def test_invalid_return_type():
    """Test that invalid return_type raises ValueError."""
    def func(x: int):
        return x
    
    with pytest.raises(ValueError, match="return_type must be"):
        autoarg([func], return_type="invalid")


def test_sequence_empty_list():
    """Test sequence with empty list."""
    wrapped = autoarg([], return_type="list")
    result = wrapped([])
    
    assert result == []


def test_sequence_single_function():
    """Test sequence with single function in list."""
    def greet(name: str):
        """Greet someone.
        
        Args:
            name: The name
        """
        return f"Hello {name}"
    
    wrapped = autoarg([greet], return_type="list")
    result = wrapped(['--name', 'Alice'])
    
    assert result == ["Hello Alice"]
