"""Helpers for deterministic headless UI regression tests on buildboxes."""
from __future__ import annotations

import sys
import types
import tkinter as tk


def install_headless_audio_stub() -> None:
    """Avoid requiring PortAudio for UI construction/screenshot tests."""
    if "sounddevice" in sys.modules:
        return
    module = types.ModuleType("sounddevice")

    class CallbackStop(Exception):
        pass

    class OutputStream:
        def __init__(self, *args, **kwargs):
            self.active = False
        def start(self):
            self.active = True
        def stop(self):
            self.active = False
        def close(self):
            self.active = False

    module.CallbackStop = CallbackStop
    module.OutputStream = OutputStream
    sys.modules["sounddevice"] = module


def install_tk9_menu_compat() -> None:
    """Adapt Tk 9 empty Menu.index semantics for CustomTkinter 5.2.2 tests."""
    if tk.TkVersion < 9.0 or getattr(tk.Menu, "_autoremaster_test_patch", False):
        return

    def index(self, index):
        result = self.tk.call(self._w, "index", index)
        if result == "":
            return None
        return self.tk.getint(result)

    tk.Menu.index = index
    tk.Menu._autoremaster_test_patch = True


def prepare_headless_ui() -> None:
    install_headless_audio_stub()
    install_tk9_menu_compat()


def reset_module_registry() -> None:
    """Reset process-global module discovery between isolated app tests."""
    from ui.modules import ModuleRegistry
    ModuleRegistry._instance = None
    ModuleRegistry._modules = {}
    ModuleRegistry._initialized = False
    ModuleRegistry._discovery_queue = []
    ModuleRegistry._queue_populated = False


def shutdown_test_app(app) -> None:
    """Cancel recurring jobs before destroying a headless test app."""
    try:
        if getattr(app, "spectrum_display", None):
            app.spectrum_display.stop()
    except Exception:
        pass
    for name in ("_playback_ui_timer", "_live_preview_timer", "_preview_update_timer"):
        job = getattr(app, name, None)
        if job:
            try:
                app.after_cancel(job)
            except Exception:
                pass
            setattr(app, name, None)
    try:
        if getattr(app, "waveform_frame", None):
            app.waveform_frame.cleanup()
    except Exception:
        pass
    try:
        app.destroy()
    except Exception:
        pass
