"""
End-to-end integration test for git hooks destination mapping.

This test verifies that the sync tool correctly syncs git hooks
from .claude/git-hooks/ to .git/hooks/ using destination path mapping.
"""

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

# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))

from persuade.core import SyncOptions, sync_automation


def test_git_hooks_destination_mapping() -> None:
    """Test that git hooks are synced to .git/hooks/ instead of .claude/git-hooks/."""
    with tempfile.TemporaryDirectory() as tmpdir:
        # Setup source repository
        source_path = Path(tmpdir) / "source"
        source_path.mkdir()

        # Create .claude/git-hooks/ directory with a pre-push hook
        source_claude = source_path / ".claude"
        source_claude.mkdir()
        git_hooks_dir = source_claude / "git-hooks"
        git_hooks_dir.mkdir()

        pre_push_hook = git_hooks_dir / "pre-push"
        hook_content = """#!/bin/bash
# Test pre-push hook
echo "Pre-push hook executed"
exit 0
"""
        pre_push_hook.write_text(hook_content)
        pre_push_hook.chmod(0o755)  # Make executable

        # Create README that should NOT be synced to .git/hooks/
        readme = git_hooks_dir / "README.md"
        readme.write_text("# Git Hooks Documentation")

        # Create minimal settings.json to satisfy validation
        settings = source_claude / "settings.json"
        settings.write_text('{"permissions": {"allow": []}, "hooks": {}}\n')

        # Setup target repository (with git)
        target_path = Path(tmpdir) / "target"
        target_path.mkdir()

        # Initialize git repo
        subprocess.run(["git", "init"], cwd=target_path, capture_output=True, check=True)
        subprocess.run(
            ["git", "config", "user.email", "test@example.com"],
            cwd=target_path,
            capture_output=True,
            check=True,
        )
        subprocess.run(
            ["git", "config", "user.name", "Test User"],
            cwd=target_path,
            capture_output=True,
            check=True,
        )

        # Run sync
        options = SyncOptions(quiet=True)
        result = sync_automation(source_path, target_path, options)

        # Verify sync succeeded
        assert result.status == "success", f"Sync failed: {result.message}"

        # Verify pre-push hook was synced to .git/hooks/
        dest_hook = target_path / ".git/hooks/pre-push"
        assert dest_hook.exists(), "pre-push hook should be in .git/hooks/"
        assert dest_hook.read_text() == hook_content, "Hook content should match"

        # Verify hook is executable
        assert os.access(dest_hook, os.X_OK), "Hook should be executable"

        # Verify pre-push was NOT copied to .claude/git-hooks/
        old_location = target_path / ".claude/git-hooks/pre-push"
        assert not old_location.exists(), "Hook should NOT be in .claude/git-hooks/"

        # Note: With explicit whitelist approach, README.md is excluded from git-hooks
        # destination mapping, and doesn't match any other pattern, so it's skipped entirely.
        # This is the correct behavior - documentation files in git-hooks/ are project-specific.
        readme_location = target_path / ".claude/git-hooks/README.md"
        assert not readme_location.exists(), "README.md should be skipped (explicit whitelist)"

        # Verify README.md was NOT synced to .git/hooks/
        bad_readme = target_path / ".git/hooks/README.md"
        assert not bad_readme.exists(), "README.md should NOT be in .git/hooks/"

        print("✓ test_git_hooks_destination_mapping passed")


def test_multiple_hooks() -> None:
    """Test syncing multiple git hooks at once."""
    with tempfile.TemporaryDirectory() as tmpdir:
        # Setup source repository
        source_path = Path(tmpdir) / "source"
        source_path.mkdir()

        source_claude = source_path / ".claude"
        source_claude.mkdir()
        git_hooks_dir = source_claude / "git-hooks"
        git_hooks_dir.mkdir()

        # Create multiple hooks
        hooks = {
            "pre-push": "#!/bin/bash\necho 'pre-push'\n",
            "pre-commit": "#!/bin/bash\necho 'pre-commit'\n",
            "post-merge": "#!/bin/bash\necho 'post-merge'\n",
        }

        for hook_name, content in hooks.items():
            hook_file = git_hooks_dir / hook_name
            hook_file.write_text(content)
            hook_file.chmod(0o755)

        # Create minimal settings.json
        settings = source_claude / "settings.json"
        settings.write_text('{"permissions": {"allow": []}, "hooks": {}}\n')

        # Setup target repository
        target_path = Path(tmpdir) / "target"
        target_path.mkdir()

        subprocess.run(["git", "init"], cwd=target_path, capture_output=True, check=True)
        subprocess.run(
            ["git", "config", "user.email", "test@example.com"],
            cwd=target_path,
            capture_output=True,
            check=True,
        )
        subprocess.run(
            ["git", "config", "user.name", "Test User"],
            cwd=target_path,
            capture_output=True,
            check=True,
        )

        # Run sync
        options = SyncOptions(quiet=True)
        result = sync_automation(source_path, target_path, options)

        assert result.status == "success", f"Sync failed: {result.message}"

        # Verify all hooks were synced to .git/hooks/
        for hook_name, content in hooks.items():
            dest_hook = target_path / f".git/hooks/{hook_name}"
            assert dest_hook.exists(), f"{hook_name} should be in .git/hooks/"
            assert dest_hook.read_text() == content, f"{hook_name} content should match"

            # Verify executable
            assert os.access(dest_hook, os.X_OK), f"{hook_name} should be executable"

        print("✓ test_multiple_hooks passed")


def test_hook_update() -> None:
    """Test that updating a hook syncs the new version."""
    with tempfile.TemporaryDirectory() as tmpdir:
        # Setup source and target
        source_path = Path(tmpdir) / "source"
        target_path = Path(tmpdir) / "target"

        source_path.mkdir()
        target_path.mkdir()

        source_claude = source_path / ".claude"
        source_claude.mkdir()
        git_hooks_dir = source_claude / "git-hooks"
        git_hooks_dir.mkdir()

        # Initialize git repo
        subprocess.run(["git", "init"], cwd=target_path, capture_output=True, check=True)
        subprocess.run(
            ["git", "config", "user.email", "test@example.com"],
            cwd=target_path,
            capture_output=True,
            check=True,
        )
        subprocess.run(
            ["git", "config", "user.name", "Test User"],
            cwd=target_path,
            capture_output=True,
            check=True,
        )

        # Initial sync with version 1 of hook
        hook_v1 = "#!/bin/bash\necho 'version 1'\n"
        pre_push = git_hooks_dir / "pre-push"
        pre_push.write_text(hook_v1)
        pre_push.chmod(0o755)

        # Create minimal settings.json
        settings = source_claude / "settings.json"
        settings.write_text('{"permissions": {"allow": []}, "hooks": {}}\n')

        options = SyncOptions(quiet=True)
        result = sync_automation(source_path, target_path, options)
        assert result.status == "success"

        dest_hook = target_path / ".git/hooks/pre-push"
        assert dest_hook.read_text() == hook_v1

        # Update hook to version 2
        hook_v2 = "#!/bin/bash\necho 'version 2 - updated'\n"
        pre_push.write_text(hook_v2)

        # Sync again
        result = sync_automation(source_path, target_path, options)
        assert result.status == "success"

        # Verify hook was updated
        assert dest_hook.read_text() == hook_v2, "Hook should be updated to version 2"

        print("✓ test_hook_update passed")


# Run all tests
if __name__ == "__main__":
    test_git_hooks_destination_mapping()
    test_multiple_hooks()
    test_hook_update()

    print("\n✅ All integration tests passed!")
