#!/usr/bin/env python3

"""Tests for the RunCommand with lint."""

import os
import unittest

from codemcp.testing import MCPEndToEndTestCase


class RunCommandLintTest(MCPEndToEndTestCase):
    """Test the RunCommand with lint subtool."""

    async def test_lint_with_run_subtool(self):
        """Test that RunCommand with lint commits changes made by linting."""
        # Create a file that needs linting
        unlinted_file_path = os.path.join(self.temp_dir.name, "unlinted.py")
        unlinted_content = """import math
import os
import sys
from typing import List, Dict, Any

def unused_param(x, y):
    # Unused parameter 'y' that linter would remove
    return x * 2

def main():
    # Unused import
    # Variables defined but not used
    unused_var = 42
    return True
"""

        with open(unlinted_file_path, "w") as f:
            f.write(unlinted_content)

        # Add it to git
        await self.git_run(["add", unlinted_file_path])

        # Commit it
        await self.git_run(["commit", "-m", "Add unlinted file"])

        # Create a simple lint script that simulates ruff linting
        lint_script_path = os.path.join(self.temp_dir.name, "run_lint.sh")
        with open(lint_script_path, "w") as f:
            f.write("""#!/bin/bash
# Simple mock linter that fixes linting issues in the unlinted.py file
if [ -f unlinted.py ]; then
    # Replace with properly linted version (removed unused imports and variables)
    cat > unlinted.py << 'EOF'
import math
from typing import List, Dict, Any

def unused_param(x):
    # Linter removed unused parameter 'y'
    return x * 2

def main():
    return True
EOF
    echo "Linted unlinted.py"
fi
""")

        # Make it executable
        os.chmod(lint_script_path, 0o755)

        # Create a codemcp.toml file with lint subtool
        codemcp_toml_path = os.path.join(self.temp_dir.name, "codemcp.toml")
        with open(codemcp_toml_path, "w") as f:
            f.write("""[project]
name = "test-project"

[commands]
lint = ["./run_lint.sh"]
""")

        # Record the current commit hash before linting
        commit_before = await self.git_run(
            ["rev-parse", "HEAD"], capture_output=True, text=True
        )

        async with self.create_client_session() as session:
            # First initialize project to get chat_id
            init_result_text = await self.call_tool_assert_success(
                session,
                "codemcp",
                {
                    "subtool": "InitProject",
                    "path": self.temp_dir.name,
                    "user_prompt": "Test initialization for lint test",
                    "subject_line": "test: initialize for lint test",
                    "reuse_head_chat_id": False,
                },
            )

            # Extract chat_id from the init result
            chat_id = self.extract_chat_id_from_text(init_result_text)

            # Call the RunCommand tool with lint command and chat_id
            result_text = await self.call_tool_assert_success(
                session,
                "codemcp",
                {
                    "subtool": "RunCommand",
                    "path": self.temp_dir.name,
                    "command": "lint",
                    "chat_id": chat_id,
                },
            )

            # Verify the success message
            self.assertIn("Code lint successful", result_text)

            # Verify the file was linted correctly
            with open(unlinted_file_path) as f:
                file_content = f.read()

            expected_content = """import math
from typing import List, Dict, Any

def unused_param(x):
    # Linter removed unused parameter 'y'
    return x * 2

def main():
    return True
"""
            self.assertEqual(file_content, expected_content)

            # Verify git state shows clean working tree after commit
            status = await self.git_run(["status"], capture_output=True, text=True)

            # Verify that the working tree is clean (changes were committed)
            self.assertExpectedInline(
                status,
                """\
On branch main
nothing to commit, working tree clean""",
            )

            # Verify that a new commit was created
            commit_after = await self.git_run(
                ["rev-parse", "HEAD"], capture_output=True, text=True
            )

            # The commit hash should be different
            self.assertNotEqual(commit_before, commit_after)

            # Verify the commit message indicates it was a linting change
            commit_msg = await self.git_run(
                ["log", "-1", "--pretty=%B"], capture_output=True, text=True
            )

            self.assertIn("Auto-commit lint changes", commit_msg)


if __name__ == "__main__":
    unittest.main()
