"""Tests for run command."""

import os
import sys
from pathlib import Path
from unittest.mock import patch, MagicMock

import pytest
from click.testing import CliRunner

from scry_run.cli import main


class TestRunCommand:
    """Tests for scry-run run command."""

    def test_run_nonexistent_app(self, scry_run_home):
        """Test run fails for nonexistent app."""
        runner = CliRunner()
        result = runner.invoke(main, ["run", "nonexistent"])

        assert result.exit_code != 0
        assert "not found" in result.output.lower()

    def test_run_existing_app(self, scry_run_home):
        """Test run executes existing app."""
        # Create app
        runner = CliRunner()
        runner.invoke(
            main,
            ["init", "--name", "test-app", "--description", "Test"],
        )

        # Mock subprocess and ensure_scry_run_installed to avoid actually running
        with patch("scry_run.cli.run.ensure_scry_run_installed"):
            with patch("scry_run.cli.run.subprocess.run") as mock_run:
                mock_run.return_value = MagicMock(returncode=0)

                result = runner.invoke(main, ["run", "test-app"])

                assert result.exit_code == 0
                mock_run.assert_called_once()

            # Check command uses uv run --directory
            call_args = mock_run.call_args
            cmd = call_args[0][0]
            assert cmd[0] == "uv"
            assert cmd[1] == "run"
            assert cmd[2] == "--directory"
            assert "test-app" in cmd[3]  # app_dir
            assert cmd[4] == "python"
            assert "app.py" in cmd[5]
            assert "test-app" in cmd[5]

    def test_run_passes_args_to_app(self, scry_run_home):
        """Test run passes arguments to app."""
        runner = CliRunner()
        runner.invoke(
            main,
            ["init", "--name", "test-app", "--description", "Test"],
        )

        with patch("scry_run.cli.run.ensure_scry_run_installed"):
            with patch("scry_run.cli.run.subprocess.run") as mock_run:
                mock_run.return_value = MagicMock(returncode=0)

                runner.invoke(main, ["run", "test-app", "arg1", "arg2", "--flag"])

                call_args = mock_run.call_args
                cmd = call_args[0][0]
                assert "arg1" in cmd
                assert "arg2" in cmd
                assert "--flag" in cmd

    def test_run_loads_config_as_env_vars(self, scry_run_home):
        """Test run loads config and sets env vars."""
        # Create config
        config_path = scry_run_home / "config.toml"
        config_path.write_text("""
[defaults]
backend = "claude"

[backend.claude]
model = "opus"
""")

        # Create app
        runner = CliRunner()
        runner.invoke(
            main,
            ["init", "--name", "test-app", "--description", "Test"],
        )

        # Clear SCRY_BACKEND to test config file loading
        saved_backend = os.environ.pop("SCRY_BACKEND", None)
        try:
            with patch("scry_run.cli.run.ensure_scry_run_installed"):
                with patch("scry_run.cli.run.subprocess.run") as mock_run:
                    mock_run.return_value = MagicMock(returncode=0)

                    runner.invoke(main, ["run", "test-app"])

                    call_args = mock_run.call_args
                    env = call_args[1].get("env", {})
                    assert env.get("SCRY_BACKEND") == "claude"
                    assert env.get("SCRY_MODEL") == "opus"
        finally:
            if saved_backend is not None:
                os.environ["SCRY_BACKEND"] = saved_backend
