"""Surface checks for the web-search stall timing + summary-surfacing fixes.

The full Assistant can't be instantiated in tests (it loads audio/ASR/SLM/TTS),
so — like test_assistant_ack.py — these assert the wiring via source inspection.

Two behaviours are pinned:
  1. The "searching the web" stall plays BEFORE dispatching the search tool
     (so it covers the slow SearXNG round-trip), not only before the fast
     summarise step that follows.
  2. A web-search summary produced earlier in the turn is surfaced in the
     final spoken output even when a later side-effect action (e.g. write_note)
     is what terminates the turn.
"""

import inspect
import sys
import types
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))


def _import_assistant_module():
    fake = {
        "core.audio": ["AudioCapture"],
        "core.asr": ["load_asr_pipeline"],
        "core.tts": [
            "set_voice", "warmup_model", "synthesize", "play_chunks",
            "speak_stream", "set_output_device", "set_tts_active_event",
            "model",
        ],
        "core.slm": ["load_slm", "generate_slm"],
    }
    for name, attrs in fake.items():
        if name in sys.modules:
            continue
        mod = types.ModuleType(name)
        for attr in attrs:
            setattr(mod, attr, lambda *a, **k: None)
        sys.modules[name] = mod

    import core.assistant as assistant  # noqa: E402
    return assistant


def test_search_stall_plays_before_dispatch():
    a = _import_assistant_module()
    src = inspect.getsource(a.Assistant._handle_wakeword)
    # The stall must be gated on is_web_search and sit before handle_action.
    assert "is_web_search" in src, "search stall not gated on is_web_search"
    stall_pos = src.index("is_web_search")
    dispatch_pos = src.index("intents.handle_action")
    assert stall_pos < dispatch_pos, "stall must play before the search dispatch"


def test_summary_surfaced_in_spoken_output():
    a = _import_assistant_module()
    src = inspect.getsource(a.Assistant._handle_wakeword)
    # The web summary is tracked across replan iterations and folded into the
    # terminal spoken output so a trailing write_note doesn't bury it.
    assert "web_summary_text" in src, "web summary not tracked for spoken output"


def test_is_web_search_importable():
    import utils.intents as intents
    assert callable(intents.is_web_search)
    assert intents.WEB_SEARCH_TOOL == "external_information"
