#!/usr/bin/env python3
"""
Improved test script to verify crackerjack workflow fast hooks behavior.

This script creates controlled test scenarios to verify:
1. Fast hooks failure stops execution before running tests
2. Fast hooks success continues to run tests and comprehensive hooks
3. Proper workflow order
"""

import os
import subprocess
import sys
import tempfile
from pathlib import Path


def run_command(cmd, capture_output=True, timeout=60):
    """Run a command and return the result."""
    try:
        result = subprocess.run(
            cmd,
            shell=True,
            capture_output=capture_output,
            text=True,
            timeout=timeout,
        )
        return result
    except subprocess.TimeoutExpired:
        print(f"Command timed out: {cmd}")
        return None
    except Exception as e:
        print(f"Error running command: {e}")
        return None


def create_minimal_project():
    """Create a minimal test project."""
    temp_dir = tempfile.mkdtemp(prefix="crackerjack_minimal_")
    print(f"Created test directory: {temp_dir}")

    # Create a simple, clean Python file
    test_file = Path(temp_dir) / "main.py"
    test_file.write_text(
        '#!/usr/bin/env python3\n"""A simple test module."""\n\n\ndef hello():\n    """Say hello."""\n    return "Hello, World!"\n\n\nif __name__ == "__main__":\n    print(hello())\n'
    )

    # Create minimal pyproject.toml
    pyproject = Path(temp_dir) / "pyproject.toml"
    pyproject.write_text("""[project]
name = "test-project"
version = "0.1.0"
description = "Minimal test project"
requires-python = ">=3.13"

[tool.ruff]
line-length = 88
""")

    # Create minimal .pre-commit-config.yaml with only essential fast hooks
    precommit = Path(temp_dir) / ".pre-commit-config.yaml"
    precommit.write_text("""repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.9
    hooks:
      - id: ruff-format
""")

    return temp_dir


def create_project_with_formatting_issues():
    """Create a project with intentional formatting issues."""
    temp_dir = tempfile.mkdtemp(prefix="crackerjack_bad_format_")
    print(f"Created test directory: {temp_dir}")

    # Create a Python file with formatting issues that will fail fast hooks
    test_file = Path(temp_dir) / "main.py"
    # Intentional formatting issues: trailing whitespace, missing final newline, bad formatting
    test_file.write_text(
        '#!/usr/bin/env python3\n"""A test module with formatting issues."""\n\n\ndef   badly_formatted(  a,b  ):   \n    """Bad formatting."""   \n    return a+b   \n\n\nclass   BadClass:\n    def __init__(self,x):\n        pass   \n\n\nif __name__ == "__main__":\n    print(badly_formatted(1,2))   '
    )
    # Note: No final newline and trailing whitespace

    # Create pyproject.toml
    pyproject = Path(temp_dir) / "pyproject.toml"
    pyproject.write_text("""[project]
name = "test-project-bad"
version = "0.1.0"
description = "Test project with formatting issues"
requires-python = ">=3.13"

[tool.ruff]
line-length = 88
""")

    # Create .pre-commit-config.yaml with fast hooks that will catch formatting
    precommit = Path(temp_dir) / ".pre-commit-config.yaml"
    precommit.write_text("""repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.9
    hooks:
      - id: ruff-format
""")

    return temp_dir


def test_direct_crackerjack_behavior():
    """Test crackerjack behavior directly using its own hooks."""
    print("\n=== Test 1: Direct crackerjack workflow behavior ===")

    # Use crackerjack itself as test subject - run with fast hooks only first
    print("Testing fast hooks only...")
    result = run_command("python -m crackerjack --fast", timeout=45)

    if result is None:
        print("❌ Command failed to run or timed out")
        return False

    print(f"Fast hooks exit code: {result.returncode}")
    print("Fast hooks output:")
    print(result.stdout)
    if result.stderr:
        print("Fast hooks stderr:")
        print(result.stderr)

    # Now test with tests to see if it continues after fast hooks
    print("\nTesting with tests option...")
    result2 = run_command("python -m crackerjack -t", timeout=120)

    if result2 is None:
        print("❌ Command failed to run or timed out")
        return False

    print(f"Test workflow exit code: {result2.returncode}")
    output = result2.stdout + result2.stderr

    # Analyze output for workflow behavior
    has_fast_hooks = any(
        phrase in output.lower()
        for phrase in ["fast hooks", "running code quality checks", "🔍 hooks"]
    )

    has_tests = any(
        phrase in output.lower()
        for phrase in ["🧪 tests", "running test suite", "pytest", "test execution"]
    )

    has_comprehensive = any(
        phrase in output.lower()
        for phrase in ["comprehensive", "pre-push", "pyright", "bandit"]
    )

    print(
        f"Analysis: fast_hooks={has_fast_hooks}, tests={has_tests}, comprehensive={has_comprehensive}"
    )

    # If fast hooks passed, we should see tests being attempted
    if result.returncode == 0:  # Fast hooks passed
        if has_tests or result2.returncode == 0:
            print("✅ PASS: Fast hooks passed and workflow continued to tests")
            return True
        else:
            print("❌ FAIL: Fast hooks passed but workflow didn't continue to tests")
            return False
    else:  # Fast hooks failed
        # In this case, the workflow should still try tests if requested
        # The key is that the overall workflow should fail if fast hooks fail
        if result2.returncode != 0:
            print(
                "✅ PASS: Fast hooks failed and overall workflow failed appropriately"
            )
            return True
        else:
            print("❌ FAIL: Fast hooks failed but overall workflow succeeded")
            return False


def test_workflow_with_external_project():
    """Test workflow behavior with an external controlled project."""
    print("\n=== Test 2: External project with good formatting ===")

    temp_dir = create_minimal_project()
    original_dir = Path.cwd()

    try:
        os.chdir(temp_dir)

        # Initialize git
        subprocess.run(["git", "init"], capture_output=True, check=False)
        subprocess.run(["git", "add", "."], capture_output=True, check=False)
        subprocess.run(
            ["git", "commit", "-m", "initial"], capture_output=True, check=False
        )

        # Run crackerjack with tests
        result = run_command("python -m crackerjack -t", timeout=90)

        if result is None:
            print("❌ Command failed to run or timed out")
            return False

        print(f"Exit code: {result.returncode}")
        output = result.stdout + result.stderr

        # For a clean project, hooks should pass and tests should run
        # (even if tests fail due to no test files, the workflow should attempt them)
        has_hooks = "hooks" in output.lower() or "quality checks" in output.lower()
        workflow_attempted_tests = any(
            phrase in output.lower()
            for phrase in ["test", "pytest", "no tests ran", "collected 0 items"]
        )

        print(
            f"Analysis: has_hooks={has_hooks}, attempted_tests={workflow_attempted_tests}"
        )

        if has_hooks:
            print("✅ PASS: Workflow ran hooks and proceeded to test phase")
            return True
        else:
            print("❌ FAIL: Expected hooks to run in workflow")
            return False

    finally:
        os.chdir(original_dir)


def test_workflow_with_bad_formatting():
    """Test workflow behavior with intentional formatting issues."""
    print("\n=== Test 3: External project with bad formatting ===")

    temp_dir = create_project_with_formatting_issues()
    original_dir = Path.cwd()

    try:
        os.chdir(temp_dir)

        # Initialize git
        subprocess.run(["git", "init"], capture_output=True, check=False)
        subprocess.run(["git", "add", "."], capture_output=True, check=False)
        subprocess.run(
            ["git", "commit", "-m", "initial"], capture_output=True, check=False
        )

        # Run crackerjack with tests - should fail at hooks
        result = run_command("python -m crackerjack -t", timeout=90)

        if result is None:
            print("❌ Command failed to run or timed out")
            return False

        print(f"Exit code: {result.returncode}")
        output = result.stdout + result.stderr
        print("Output sample:")
        print(output[:1000] + "..." if len(output) > 1000 else output)

        # With bad formatting, hooks should fail and workflow should stop
        # Exit code should be non-zero
        if result.returncode != 0:
            print("✅ PASS: Workflow failed due to formatting issues (as expected)")
            return True
        else:
            print("❌ FAIL: Workflow should have failed due to formatting issues")
            return False

    finally:
        os.chdir(original_dir)


def check_phase_coordinator_implementation():
    """Check that the phase coordinator returns proper boolean values."""
    print("\n=== Test 4: Phase coordinator boolean return check ===")

    try:
        # Import and check the implementation
        import inspect

        from crackerjack.core.phase_coordinator import PhaseCoordinator

        # Check run_fast_hooks_only method
        fast_hooks_method = getattr(PhaseCoordinator, "run_fast_hooks_only", None)
        if not fast_hooks_method:
            print("❌ FAIL: run_fast_hooks_only method not found")
            return False

        # Get source code to verify it returns boolean
        try:
            source = inspect.getsource(fast_hooks_method)

            # Check for proper boolean return
            returns_bool = any(
                phrase in source
                for phrase in [
                    'return all(r.status == "passed" for r in hook_results)',
                    "return False",
                    "return True",
                    "-> bool",
                ]
            )

            if returns_bool:
                print("✅ PASS: run_fast_hooks_only method properly returns boolean")
                return True
            else:
                print(
                    "❌ FAIL: run_fast_hooks_only method may not return proper boolean"
                )
                print("Method source:")
                print(source)
                return False

        except Exception as e:
            print(f"❌ Could not inspect method source: {e}")
            return False

    except ImportError as e:
        print(f"❌ Could not import phase coordinator: {e}")
        return False


def main():
    """Run all tests."""
    print("Testing crackerjack fast hooks workflow behavior")
    print("=" * 60)

    # Test 1: Direct behavior test
    test1_result = test_direct_crackerjack_behavior()

    # Test 2: Clean external project
    test2_result = test_workflow_with_external_project()

    # Test 3: Bad formatting project
    test3_result = test_workflow_with_bad_formatting()

    # Test 4: Implementation check
    test4_result = check_phase_coordinator_implementation()

    # Summary
    print("\n" + "=" * 60)
    print("TEST RESULTS SUMMARY:")
    print(
        f"Test 1 (Direct workflow behavior): {'✅ PASS' if test1_result else '❌ FAIL'}"
    )
    print(
        f"Test 2 (Clean project workflow): {'✅ PASS' if test2_result else '❌ FAIL'}"
    )
    print(
        f"Test 3 (Bad formatting project): {'✅ PASS' if test3_result else '❌ FAIL'}"
    )
    print(f"Test 4 (Implementation check): {'✅ PASS' if test4_result else '❌ FAIL'}")

    all_passed = test1_result and test2_result and test3_result and test4_result

    if all_passed:
        print("\n🎉 ALL TESTS PASSED - Fast hooks workflow behavior is correct!")
        return 0
    else:
        print("\n⚠️  Some tests had issues - see details above")
        print("Note: The workflow may be working correctly even if some tests fail")
        print("due to environmental differences or hook variations.")
        return 1


if __name__ == "__main__":
    sys.exit(main())
