"""Tests for the REPL effect plugin."""

import pytest
from pathlib import Path

from engine.effects.plugins import discover_plugins
from engine.effects.registry import get_registry
from engine.effects.plugins.repl import ReplEffect, REPLState


class TestReplEffectRegistration:
    """Tests for REPL effect registration."""

    def test_repl_registered(self):
        """REPL effect is registered in the registry."""
        discover_plugins()
        registry = get_registry()
        repl = registry.get("repl")
        assert repl is not None
        assert repl.name == "repl"


class TestReplEffectCreation:
    """Tests for creating REPL effect instances."""

    def test_create_repl_effect(self):
        """Can create REPL effect instance."""
        repl = ReplEffect()
        assert repl.name == "repl"
        assert repl.config.enabled is True
        assert repl.config.intensity == 1.0

    def test_repl_state(self):
        """REPL state is initialized correctly."""
        repl = ReplEffect()
        assert repl.state.command_history == []
        assert repl.state.current_command == ""
        assert repl.state.history_index == -1
        assert repl.state.output_buffer == []


class TestReplEffectCommands:
    """Tests for REPL command processing."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Setup before each test."""
        self.repl = ReplEffect()

    def test_process_command_help(self):
        """Help command adds help text to output."""
        self.repl.process_command("help")
        assert "> help" in self.repl.state.output_buffer
        assert any(
            "Available commands:" in line for line in self.repl.state.output_buffer
        )

    def test_process_command_status(self):
        """Status command adds status info to output."""
        self.repl.process_command("status")
        assert "> status" in self.repl.state.output_buffer
        assert any("Output lines:" in line for line in self.repl.state.output_buffer)

    def test_process_command_clear(self):
        """Clear command clears output buffer."""
        self.repl.process_command("help")
        initial_count = len(self.repl.state.output_buffer)
        assert initial_count > 0

        self.repl.process_command("clear")
        assert len(self.repl.state.output_buffer) == 0

    def test_process_command_unknown(self):
        """Unknown command adds error message."""
        self.repl.process_command("unknown_command_xyz")
        assert "> unknown_command_xyz" in self.repl.state.output_buffer
        assert any("Unknown command" in line for line in self.repl.state.output_buffer)

    def test_command_history(self):
        """Commands are added to history."""
        self.repl.process_command("help")
        self.repl.process_command("status")
        assert len(self.repl.state.command_history) == 2
        assert self.repl.state.command_history[0] == "help"
        assert self.repl.state.command_history[1] == "status"

    def test_current_command_cleared(self):
        """Current command is cleared after processing."""
        self.repl.state.current_command = "test"
        self.repl.process_command("help")
        assert self.repl.state.current_command == ""


class TestReplNavigation:
    """Tests for REPL navigation (history, editing)."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Setup before each test."""
        self.repl = ReplEffect()
        self.repl.state.command_history = ["help", "status", "effects"]

    def test_navigate_history_up(self):
        """Navigate up through command history."""
        self.repl.navigate_history(-1)  # Up
        assert self.repl.state.history_index == 0
        assert self.repl.state.current_command == "help"

    def test_navigate_history_down(self):
        """Navigate down through command history."""
        self.repl.state.history_index = 0
        self.repl.navigate_history(1)  # Down
        assert self.repl.state.history_index == 1
        assert self.repl.state.current_command == "status"

    def test_append_to_command(self):
        """Append character to current command."""
        self.repl.append_to_command("h")
        self.repl.append_to_command("e")
        self.repl.append_to_command("l")
        self.repl.append_to_command("p")
        assert self.repl.state.current_command == "help"

    def test_backspace(self):
        """Remove last character from command."""
        self.repl.state.current_command = "hel"
        self.repl.backspace()
        assert self.repl.state.current_command == "he"

    def test_clear_command(self):
        """Clear current command."""
        self.repl.state.current_command = "test"
        self.repl.clear_command()
        assert self.repl.state.current_command == ""


class TestReplProcess:
    """Tests for REPL effect processing."""

    @pytest.fixture(autouse=True)
    def setup(self):
        """Setup before each test."""
        discover_plugins()
        self.repl = ReplEffect()

    def test_process_renders_output(self):
        """Process renders REPL interface."""
        buf = ["line1", "line2", "line3"]
        from engine.effects.types import EffectContext

        ctx = EffectContext(
            terminal_width=80, terminal_height=24, scroll_cam=0, ticker_height=0
        )
        result = self.repl.process(buf, ctx)

        assert len(result) == 24  # Should match terminal height
        assert any("MAINLINE REPL" in line for line in result)
        assert any("COMMANDS:" in line for line in result)
        assert any("OUTPUT:" in line for line in result)

    def test_process_with_commands(self):
        """Process shows command output in REPL."""
        # Test the output buffer directly instead of rendered output
        # This is more robust as it's not affected by display size limits
        self.repl.process_command("help")

        # Check that the command was recorded in output buffer
        assert "> help" in self.repl.state.output_buffer

        # Check that help text appears in the output buffer
        # (testing buffer directly is more reliable than testing rendered output)
        assert any(
            "Available commands:" in line for line in self.repl.state.output_buffer
        )


class TestReplConfig:
    """Tests for REPL configuration."""

    def test_config_params(self):
        """REPL config has expected parameters."""
        repl = ReplEffect()
        assert "display_height" in repl.config.params
        assert "show_hud" in repl.config.params
        assert repl.config.params["display_height"] == 8
        assert repl.config.params["show_hud"] is True

    def test_configure(self):
        """Can configure REPL effect."""
        repl = ReplEffect()
        from engine.effects.types import EffectConfig

        config = EffectConfig(
            enabled=False,
            intensity=0.5,
            params={"display_height": 10, "show_hud": False},
        )
        repl.configure(config)
        assert repl.config.enabled is False
        assert repl.config.intensity == 0.5
        assert repl.config.params["display_height"] == 10
