"""
End-to-end tests for issue management CLI commands.

Demonstrates:
- CLI command testing with real processes
- Environment isolation
- Workflow validation
- Output verification
"""

import pytest
import subprocess
import json
import sys
from pathlib import Path
import time
import os

from tests.utils.assertions import assert_file_exists, assert_directory_exists, assert_file_contains


@pytest.mark.e2e
class TestIssueCommandsE2E:
    """End-to-end tests for issue management CLI commands."""

    def test_show_issue_command_basic(self, isolated_environment):
        """Test basic issue show command."""
        # Act
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "show-issue", "23"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        # Assert
        assert result.returncode == 0, f"Command failed with stderr: {result.stderr}"
        assert "Issue #23" in result.stdout or "issue 23" in result.stdout.lower()

    def test_show_issue_command_with_invalid_number(self, isolated_environment):
        """Test show issue command with invalid issue number."""
        # Act
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "show-issue", "99999"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        # Assert - Should handle gracefully
        # Note: Depending on implementation, this might return 0 or 1
        assert "not found" in result.stdout.lower() or "error" in result.stdout.lower() or "error" in result.stderr.lower()

    def test_workspace_status_command(self, isolated_environment):
        """Test workspace status command."""
        # Act
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "workspace-status"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        # Assert
        assert result.returncode == 0
        # Should show workspace information
        assert "workspace" in result.stdout.lower() or "status" in result.stdout.lower()

    @pytest.mark.slow
    def test_complete_issue_workflow(self, isolated_environment, test_workspace):
        """Test complete issue workflow from start to finish."""
        workspace_dir = Path(isolated_environment["MARKITECT_WORKSPACE_DIR"])
        workspace_dir.mkdir(exist_ok=True)

        # Step 1: Check initial workspace status
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "workspace-status"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )
        assert result.returncode == 0

        # Step 2: Start working on an issue
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "start-issue", "42"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd(),
            timeout=30  # Prevent hanging
        )

        # Verify the start command works (might create workspace)
        if result.returncode == 0:
            # If successful, check if workspace was created
            issue_workspace = workspace_dir / "issue_42"
            if issue_workspace.exists():
                assert_directory_exists(issue_workspace)

        # Step 3: Check workspace status again
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "workspace-status"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )
        assert result.returncode == 0

        # Step 4: Try to finish (cleanup)
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "finish-issue"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd(),
            timeout=30
        )

        # The finish command should work or provide meaningful feedback
        assert result.returncode in [0, 1]  # Allow for various implementation states

    def test_list_open_issues_command(self, isolated_environment):
        """Test listing open issues."""
        # Act
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "list-open-issues"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        # Assert
        assert result.returncode == 0
        # Should return some form of issue listing (even if empty)
        output = result.stdout.strip()
        assert len(output) >= 0  # Any output is acceptable

    def test_cli_help_commands(self, isolated_environment):
        """Test CLI help functionality."""
        # Test main help
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "--help"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        assert result.returncode == 0
        assert "usage" in result.stdout.lower() or "commands" in result.stdout.lower()

        # Test specific command help
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "show-issue", "--help"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        assert result.returncode == 0

    def test_cli_provides_helpful_error_for_unknown_commands(self, isolated_environment):
        """Test CLI provides helpful error message for unknown commands."""
        # Act
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "invalid-command"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        # Assert - Should handle gracefully
        assert result.returncode != 0
        assert "error" in result.stderr.lower() or "unknown" in result.stderr.lower()

    def test_cli_error_handling(self, isolated_environment):
        """Test CLI error handling for various scenarios."""
        # Test with missing required argument
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "show-issue"],  # Missing issue number
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        # Should provide helpful error message
        assert result.returncode != 0
        assert len(result.stderr) > 0 or "error" in result.stdout.lower()

    @pytest.mark.parametrize("issue_number", ["1", "23", "100"])
    def test_show_issue_command_multiple_issues(self, isolated_environment, issue_number):
        """Test show issue command with multiple issue numbers."""
        # Act
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "show-issue", issue_number],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd(),
            timeout=15
        )

        # Assert - Command should execute without crashing
        assert result.returncode in [0, 1]  # Allow for not found scenarios
        assert len(result.stdout + result.stderr) > 0  # Should provide some output

    def test_cli_performance(self, isolated_environment, performance_timer):
        """Test CLI command performance."""
        # Act
        performance_timer.start()
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "workspace-status"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )
        performance_timer.stop()

        # Assert
        assert result.returncode == 0
        # CLI commands should be reasonably fast
        assert performance_timer.elapsed < 10.0, f"CLI command took {performance_timer.elapsed:.2f}s"

    def test_cli_output_formatting(self, isolated_environment):
        """Test CLI output formatting and structure."""
        # Test workspace status output
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "workspace-status"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        if result.returncode == 0:
            output = result.stdout
            # Output should be readable and structured
            assert len(output.strip()) > 0
            # Should not contain obvious error traces
            assert "Traceback" not in output
            assert "Exception" not in output

    def test_cli_environment_isolation(self, test_workspace):
        """Test that CLI commands work in isolated environment."""
        # Create isolated environment
        isolated_env = {
            "MARKITECT_WORKSPACE_DIR": str(test_workspace / "isolated"),
            "MARKITECT_GITEA_URL": "http://isolated-gitea.com",
            "MARKITECT_REPO_OWNER": "isolated",
            "MARKITECT_REPO_NAME": "test",
            "PYTHONPATH": "."
        }

        # Update with current env to preserve PATH, etc.
        full_env = dict(os.environ)
        full_env.update(isolated_env)

        # Act
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "workspace-status"],
            env=full_env,
            capture_output=True,
            text=True,
            cwd=Path.cwd()
        )

        # Assert - Should work with isolated environment
        assert result.returncode == 0
        # Should use isolated workspace directory
        workspace_path = test_workspace / "isolated"
        workspace_path.mkdir(exist_ok=True)

    def test_multiple_cli_commands_can_execute_concurrently_without_conflicts(self, isolated_environment):
        """Test multiple CLI commands can execute concurrently without conflicts."""
        import threading
        import queue

        results_queue = queue.Queue()

        def run_command(command_args):
            result = subprocess.run(
                command_args,
                env=isolated_environment,
                capture_output=True,
                text=True,
                cwd=Path.cwd(),
                timeout=15
            )
            results_queue.put(result)

        # Start multiple commands concurrently
        commands = [
            [sys.executable, "tddai_cli.py", "workspace-status"],
            [sys.executable, "tddai_cli.py", "show-issue", "1"],
            [sys.executable, "tddai_cli.py", "show-issue", "2"],
        ]

        threads = []
        for cmd in commands:
            thread = threading.Thread(target=run_command, args=(cmd,))
            threads.append(thread)
            thread.start()

        # Wait for all threads to complete
        for thread in threads:
            thread.join(timeout=20)

        # Collect results
        results = []
        while not results_queue.empty():
            results.append(results_queue.get())

        # Assert
        assert len(results) == len(commands)
        # At least some commands should succeed
        successful_commands = [r for r in results if r.returncode == 0]
        assert len(successful_commands) > 0

    @pytest.mark.smoke
    def test_cli_smoke_test(self, isolated_environment):
        """Basic smoke test for CLI functionality."""
        # Test that the CLI script exists and is executable
        cli_script = Path("tddai_cli.py")
        assert_file_exists(cli_script)

        # Test basic command execution
        result = subprocess.run(
            [sys.executable, "tddai_cli.py", "--help"],
            env=isolated_environment,
            capture_output=True,
            text=True,
            cwd=Path.cwd(),
            timeout=10
        )

        # Should at least not crash
        assert result.returncode in [0, 1, 2]  # Various help return codes
        assert len(result.stdout + result.stderr) > 0