"""Step definitions for tdd_tui_prompt_input_live_refresh.feature.

Regression guard for issue #11249: _PromptTextInput must override
virtual_size with layout=False to prevent full layout recalculations
on every keystroke, which blocked Textual's WriterThread from flushing
stdout and made typed characters invisible until Enter was pressed.
"""

from __future__ import annotations

from pathlib import Path
from typing import Any

from behave import given, then


@given("the _PromptTextInput class is available")
def step_prompt_text_input_available(context: Any) -> None:
    """Import _PromptTextInput from the prompt module."""
    from cleveragents.tui.widgets.prompt import _PromptInputBase

    context._prompt_input_cls = _PromptInputBase


@then("its virtual_size reactive should have layout=False")
def step_virtual_size_layout_false(context: Any) -> None:
    """Assert that _PromptTextInput.virtual_size has layout=False.

    Bug #11249: if layout=True, every keystroke triggers a full layout
    recalculation that keeps the WriterThread queue non-empty and prevents
    stdout from flushing, making typed characters invisible until Enter.
    """
    cls = context._prompt_input_cls

    if not hasattr(cls, "virtual_size"):
        # Fallback class (Textual not available) — skip, no reactive to check
        return

    vs_reactive = cls.__dict__.get("virtual_size")
    assert vs_reactive is not None, (
        "Bug #11249 regression: _PromptTextInput must define its own "
        "virtual_size reactive (overriding Widget.virtual_size)."
    )
    assert not getattr(vs_reactive, "_layout", True), (
        "Bug #11249 regression: _PromptTextInput.virtual_size must have "
        "layout=False to prevent refresh(layout=True) on every keystroke. "
        "Characters will be invisible while typing if layout=True."
    )


@given("the _TextualPromptInput class is available")
def step_textual_prompt_input_available(context: Any) -> None:
    """Import _TextualPromptInput (the Horizontal wrapper) from the prompt module."""
    from cleveragents.tui.widgets import prompt as prompt_mod

    context._textual_prompt_cls = getattr(prompt_mod, "_TextualPromptInput", None)
    context._prompt_input_base = prompt_mod._PromptInputBase


@then("its inner _input should be a _PromptTextInput instance")
def step_inner_input_is_prompt_text_input(context: Any) -> None:
    """Assert the inner Input widget is our subclass, not raw textual.Input.

    Verifies that _TextualPromptInput uses _PromptInputBase (the subclass
    with layout=False virtual_size) rather than the raw _InputBase.
    """
    cls = context._textual_prompt_cls
    if cls is None:
        return  # Textual not available — skip

    # Instantiate and check the _input type
    instance = cls.__new__(cls)
    # Access _input type via the class __init__ source check
    # (avoid actually instantiating which requires a running app)
    import inspect

    src = inspect.getsource(cls.__init__)
    assert "_PromptInputBase" in src, (
        "Bug #11249 regression: _TextualPromptInput.__init__ must create "
        "_input using _PromptInputBase (not _InputBase) so the virtual_size "
        "layout=False override is active."
    )
    del instance  # avoid unused warning


@given("the TUI CSS file is loaded")
def step_css_file_loaded(context: Any) -> None:
    """Load the TUI CSS file content."""
    css_path = (
        Path(__file__).resolve().parents[2]
        / "src"
        / "cleveragents"
        / "tui"
        / "cleveragents.tcss"
    )
    context._css_content = css_path.read_text(encoding="utf-8")


@then("the prompt Input rule should use a fixed height not auto")
def step_prompt_input_fixed_height(context: Any) -> None:
    """Assert the #prompt > Input CSS rule uses a fixed height, not height:auto.

    Bug #11249: with ``height: auto``, ``Input.styles.auto_dimensions``
    returns True, causing ``_watch_value`` to call ``refresh(layout=True)``
    on every keystroke — a second source of layout recalculations that
    adds to the WriterThread queue pressure.
    """
    css = context._css_content

    # Find the #prompt > Input block
    import re

    match = re.search(r"#prompt\s*>\s*Input\s*\{([^}]+)\}", css, re.DOTALL)
    assert match, "CSS must contain a '#prompt > Input' rule block."

    block = match.group(1)
    assert "height: auto" not in block, (
        "Bug #11249 regression: '#prompt > Input' must not use 'height: auto'. "
        "Auto height sets auto_dimensions=True which triggers refresh(layout=True) "
        "on every keystroke. Use a fixed height (e.g. 'height: 1')."
    )
    assert re.search(r"height:\s*\d", block), (
        "Bug #11249 regression: '#prompt > Input' must have a fixed numeric "
        "height (e.g. 'height: 1') to prevent auto_dimensions layout refreshes."
    )
