"""Tests for default CLI behavior (freeform generation)."""

from unittest.mock import MagicMock, patch
import pytest
from click.testing import CliRunner

from scry_run.cli import main


@pytest.fixture
def runner():
    """Create a Click test runner."""
    return CliRunner()


class TestDefaultCommand:
    """Tests for default command handling (freeform generation)."""

    def test_default_command_invocation(self, runner):
        """Test that unknown args invoke the default 'ask' command."""
        with patch("scry_run.cli.CodeGenerator") as MockGenerator:
            # Setup mock
            mock_instance = MockGenerator.return_value
            mock_instance.generate_freeform.return_value = "This is a poetic response."
            
            # Invoke with freeform args
            result = runner.invoke(main, ["write", "a", "poem"])
            
            assert result.exit_code == 0
            assert "This is a poetic response." in result.output
            
            # Verify generator was called correctly
            mock_instance.generate_freeform.assert_called_once_with("write a poem")

    def test_default_command_with_flags(self, runner):
        """Test that flags are passed to the default command if unknown."""
        with patch("scry_run.cli.CodeGenerator") as MockGenerator:
            mock_instance = MockGenerator.return_value
            mock_instance.generate_freeform.return_value = "Response"
    
            # Pass a flag-like argument
            result = runner.invoke(main, ["--something", "unknown"])
    
            assert result.exit_code == 0
            assert "Response" in result.output
            # Verify it was called with *some* arguments. 
            # Exact string depends on Click's parsing of unknown options + arguments order.
            assert mock_instance.generate_freeform.called
            args = mock_instance.generate_freeform.call_args[0][0]
            assert "unknown" in args

    def test_no_args_shows_help(self, runner):
        """Test that running with no args shows help."""
        result = runner.invoke(main, [])
        # If UsageError occurs (exit 2), check if help is in output
        if result.exit_code == 2:
             # Click might treat missing command as usage error 2, but we want to show help.
             # If our handler printed help, it's good.
             assert "scry-run: LLM-powered dynamic code generation" in result.output
        else:
             assert result.exit_code == 0
             assert "scry-run: LLM-powered dynamic code generation" in result.output
        
        # Should not invoke generator
        with patch("scry_run.cli.CodeGenerator") as MockGenerator:
            runner.invoke(main, [])
            MockGenerator.assert_not_called()

    def test_error_handling(self, runner):
        """Test that errors are handled gracefully."""
        from scry_run.generator import ScryRunError
        
        with patch("scry_run.cli.CodeGenerator") as MockGenerator:
            mock_instance = MockGenerator.return_value
            mock_instance.generate_freeform.side_effect = ScryRunError("API Error", "Hint text")
            
            result = runner.invoke(main, ["crash"])
            
            assert result.exit_code == 1
            assert "Error: API Error" in result.output
            assert "Hint: Hint text" in result.output
