#!/usr/bin/env python3
"""
End-to-End Tests for CLI Refactor (Issues #285 and #268)

These tests verify that the unified CLI architecture works correctly:
1. Parser sync: All parsers use shared argument definitions
2. Preset system: Analyze command supports presets
3. Backward compatibility: Old flags still work with deprecation warnings
4. Integration: The complete flow from CLI to execution
"""

import pytest
import subprocess
import argparse


class TestParserSync:
    """E2E tests for parser synchronization (Issue #285)."""

    def test_scrape_interactive_flag_works(self):
        """Test that --interactive flag (previously missing) now works."""
        result = subprocess.run(
            ["skill-seekers", "scrape", "--interactive", "--help"], capture_output=True, text=True
        )
        assert result.returncode == 0, "Command should execute successfully"
        assert "--interactive" in result.stdout, "Help should show --interactive flag"
        assert "-i" in result.stdout, "Help should show short form -i"

    def test_scrape_chunk_for_rag_flag_works(self):
        """Test that --chunk-for-rag flag (previously missing) now works."""
        result = subprocess.run(
            ["skill-seekers", "scrape", "--help"], capture_output=True, text=True
        )
        assert "--chunk-for-rag" in result.stdout, "Help should show --chunk-for-rag flag"
        assert "--chunk-tokens" in result.stdout, "Help should show --chunk-tokens flag"
        assert "--chunk-overlap-tokens" in result.stdout, "Help should show --chunk-overlap-tokens flag"

    def test_scrape_verbose_flag_works(self):
        """Test that --verbose flag (previously missing) now works."""
        result = subprocess.run(
            ["skill-seekers", "scrape", "--help"], capture_output=True, text=True
        )
        assert "--verbose" in result.stdout, "Help should show --verbose flag"
        assert "-v" in result.stdout, "Help should show short form -v"

    def test_scrape_url_flag_works(self):
        """Test that --url flag (previously missing) now works."""
        result = subprocess.run(
            ["skill-seekers", "scrape", "--help"], capture_output=True, text=True
        )
        assert "--url URL" in result.stdout, "Help should show --url flag"

    def test_github_all_flags_present(self):
        """Test that github command has all expected flags."""
        result = subprocess.run(
            ["skill-seekers", "github", "--help"], capture_output=True, text=True
        )
        # Key github flags that should be present
        expected_flags = [
            "--repo",
            "--api-key",
            "--profile",
            "--non-interactive",
        ]
        for flag in expected_flags:
            assert flag in result.stdout, f"Help should show {flag} flag"


class TestPresetSystem:
    """E2E tests for preset system (Issue #268)."""

    def test_analyze_preset_flag_exists(self):
        """Test that analyze command has --preset flag."""
        result = subprocess.run(
            ["skill-seekers", "analyze", "--help"], capture_output=True, text=True
        )
        assert "--preset" in result.stdout, "Help should show --preset flag"
        assert "quick" in result.stdout, "Help should mention 'quick' preset"
        assert "standard" in result.stdout, "Help should mention 'standard' preset"
        assert "comprehensive" in result.stdout, "Help should mention 'comprehensive' preset"

    def test_analyze_preset_list_flag_exists(self):
        """Test that analyze command has --preset-list flag."""
        result = subprocess.run(
            ["skill-seekers", "analyze", "--help"], capture_output=True, text=True
        )
        assert "--preset-list" in result.stdout, "Help should show --preset-list flag"

    def test_preset_list_shows_presets(self):
        """Test that --preset-list shows all available presets."""
        result = subprocess.run(
            ["skill-seekers", "analyze", "--preset-list"], capture_output=True, text=True
        )
        assert result.returncode == 0, "Command should execute successfully"
        assert "Available presets" in result.stdout, "Should show preset list header"
        assert "quick" in result.stdout, "Should show quick preset"
        assert "standard" in result.stdout, "Should show standard preset"
        assert "comprehensive" in result.stdout, "Should show comprehensive preset"
        assert "1-2 minutes" in result.stdout, "Should show time estimates"

    def test_deprecated_quick_flag_shows_warning(self, tmp_path):
        """Test that --quick flag shows deprecation warning."""
        result = subprocess.run(
            ["skill-seekers", "analyze", "--directory", str(tmp_path), "--quick"],
            capture_output=True,
            text=True,
        )
        # Note: Deprecation warnings go to stderr or stdout
        output = result.stdout + result.stderr
        assert "DEPRECATED" in output, "Should show deprecation warning"
        assert "--preset quick" in output, "Should suggest alternative"

    def test_deprecated_comprehensive_flag_shows_warning(self, tmp_path):
        """Test that --comprehensive flag shows deprecation warning."""
        result = subprocess.run(
            ["skill-seekers", "analyze", "--directory", str(tmp_path), "--comprehensive"],
            capture_output=True,
            text=True,
        )
        output = result.stdout + result.stderr
        assert "DEPRECATED" in output, "Should show deprecation warning"
        assert "--preset comprehensive" in output, "Should suggest alternative"


class TestBackwardCompatibility:
    """E2E tests for backward compatibility."""

    def test_old_scrape_command_still_works(self):
        """Test that old scrape command invocations still work."""
        result = subprocess.run(["skill-seekers-scrape", "--help"], capture_output=True, text=True)
        assert result.returncode == 0, "Old command should still work"
        assert "documentation" in result.stdout.lower(), "Help should mention documentation"

    def test_unified_cli_and_standalone_have_same_args(self):
        """Test that unified CLI and standalone have identical arguments."""
        # Get help from unified CLI
        unified_result = subprocess.run(
            ["skill-seekers", "scrape", "--help"], capture_output=True, text=True
        )

        # Get help from standalone
        standalone_result = subprocess.run(
            ["skill-seekers-scrape", "--help"], capture_output=True, text=True
        )

        # Both should have the same key flags
        key_flags = [
            "--interactive",
            "--url",
            "--verbose",
            "--chunk-for-rag",
            "--config",
            "--max-pages",
        ]

        for flag in key_flags:
            assert flag in unified_result.stdout, f"Unified should have {flag}"
            assert flag in standalone_result.stdout, f"Standalone should have {flag}"


class TestProgrammaticAPI:
    """Test that the shared argument functions work programmatically."""

    def test_import_shared_scrape_arguments(self):
        """Test that shared scrape arguments can be imported."""
        from skill_seekers.cli.arguments.scrape import add_scrape_arguments

        parser = argparse.ArgumentParser()
        add_scrape_arguments(parser)

        # Verify key arguments were added
        args_dict = vars(parser.parse_args(["https://example.com"]))
        assert "url" in args_dict

    def test_import_shared_github_arguments(self):
        """Test that shared github arguments can be imported."""
        from skill_seekers.cli.arguments.github import add_github_arguments

        parser = argparse.ArgumentParser()
        add_github_arguments(parser)

        # Parse with --repo flag
        args = parser.parse_args(["--repo", "owner/repo"])
        assert args.repo == "owner/repo"

    def test_import_analyze_presets(self):
        """Test that analyze presets can be imported."""
        from skill_seekers.cli.presets.analyze_presets import ANALYZE_PRESETS, AnalysisPreset

        assert "quick" in ANALYZE_PRESETS
        assert "standard" in ANALYZE_PRESETS
        assert "comprehensive" in ANALYZE_PRESETS

        # Verify preset structure
        quick = ANALYZE_PRESETS["quick"]
        assert isinstance(quick, AnalysisPreset)
        assert quick.name == "Quick"
        assert quick.depth == "surface"
        # Note: enhance_level is not part of AnalysisPreset anymore.
        # It's controlled separately via --enhance-level flag (default 2)


class TestIntegration:
    """Integration tests for the complete flow."""

    def test_unified_cli_subcommands_registered(self):
        """Test that all subcommands are properly registered."""
        result = subprocess.run(["skill-seekers", "--help"], capture_output=True, text=True)

        # All major commands should be listed
        expected_commands = [
            "scrape",
            "github",
            "pdf",
            "unified",
            "analyze",
            "enhance",
            "package",
            "upload",
        ]

        for cmd in expected_commands:
            assert cmd in result.stdout, f"Should list {cmd} command"

    def test_scrape_help_detailed(self):
        """Test that scrape help shows all argument details."""
        result = subprocess.run(
            ["skill-seekers", "scrape", "--help"], capture_output=True, text=True
        )

        # Check for argument categories
        assert "url" in result.stdout.lower(), "Should show url argument"
        assert "scraping options" in result.stdout.lower() or "options" in result.stdout.lower()
        assert "enhancement" in result.stdout.lower(), "Should mention enhancement options"

    def test_analyze_help_shows_presets(self):
        """Test that analyze help prominently shows preset information."""
        result = subprocess.run(
            ["skill-seekers", "analyze", "--help"], capture_output=True, text=True
        )

        assert "--preset" in result.stdout, "Should show --preset flag"
        assert "DEFAULT" in result.stdout or "default" in result.stdout, (
            "Should indicate default preset"
        )


class TestE2EWorkflow:
    """End-to-end workflow tests."""

    @pytest.mark.slow
    def test_dry_run_scrape_with_new_args(self, tmp_path):
        """Test scraping with previously missing arguments (dry run)."""
        result = subprocess.run(
            [
                "skill-seekers",
                "scrape",
                "--url",
                "https://example.com",
                "--interactive",
                "false",  # Would fail if arg didn't exist
                "--verbose",  # Would fail if arg didn't exist
                "--dry-run",
            ],
            capture_output=True,
            text=True,
            timeout=10,
        )

        # Dry run should complete without errors
        # (it may return non-zero if --interactive false isn't valid,
        #  but it shouldn't crash with "unrecognized arguments")
        assert "unrecognized arguments" not in result.stderr.lower()

    @pytest.mark.slow
    def test_analyze_with_preset_flag(self, tmp_path):
        """Test analyze with preset flag (no dry-run available)."""
        # Create a dummy directory to analyze
        test_dir = tmp_path / "test_code"
        test_dir.mkdir()
        (test_dir / "test.py").write_text("def hello(): pass")

        # Just verify the flag is recognized (no execution)
        result = subprocess.run(
            ["skill-seekers", "analyze", "--help"],
            capture_output=True,
            text=True,
        )

        # Verify preset flag exists
        assert "--preset" in result.stdout, "Should have --preset flag"
        assert "unrecognized arguments" not in result.stderr.lower()


if __name__ == "__main__":
    pytest.main([__file__, "-v", "-s"])
