"""
Regression test for: AttributeError: module 'tkinter' has no attribute 'filedialog'

On some Python installs (e.g., embedded distributions, or installs where
the Tcl/Tk runtime is missing), the `tkinter` package imports cleanly but
the `tkinter.filedialog` sub-module fails to load. The original `_LazyModule`
in src/gui_2.py used `getattr(tkinter, 'filedialog')` which raises a
confusing AttributeError at the call site. With 14 call sites in
render_projects_panel, render_workspace_settings_hub, render_fonts_panel,
and render_gemini_cli_settings, this AttributeError spammed the GUI's
stderr at 60fps whenever the Project Settings window was open.

The fix must make `_LazyModule` fall back to a stub that mimics
`tkinter.filedialog`'s public API (askopenfilename, askdirectory,
asksaveasfilename, askopenfilenames) so the GUI does not crash.

This test uses a deliberately-missing sub-module to exercise the fallback
path, making it deterministic across Python installs.
"""
import pytest
import importlib

from src.gui_2 import _LazyModule


def test_lazymodule_falls_back_to_stub_on_attribute_error() -> None:
 """
 Resolution must NOT raise AttributeError when the sub-module is
 missing. Instead, _resolve() must return a stub that exposes the
 public filedialog API. Before the fix, this test fails with
 AttributeError: module 'os' has no attribute 'this_submodule_does_not_exist'.
 """
 bad = _LazyModule("os", "this_submodule_does_not_exist")
 resolved = bad._resolve()
 assert resolved is not None
 assert hasattr(resolved, "askopenfilename")
 assert hasattr(resolved, "askdirectory")
 assert hasattr(resolved, "asksaveasfilename")
 assert hasattr(resolved, "askopenfilenames")


def test_lazymodule_stub_returns_empty_strings() -> None:
 """
 The stub functions must return safe empty values:
 - askopenfilename, askdirectory, asksaveasfilename: empty string ""
 - askopenfilenames: empty tuple ()
 This ensures downstream code that does `if p and p not in app.x:`
 or `if paths:` treats the missing-dialog as a no-op.
 """
 bad = _LazyModule("os", "this_submodule_does_not_exist")
 resolved = bad._resolve()
 assert resolved.askopenfilename() == ""
 assert resolved.askdirectory() == ""
 assert resolved.asksaveasfilename() == ""
 assert resolved.askopenfilenames() == ()


def test_lazymodule_stub_ignores_kwargs() -> None:
 """
 The stub must accept the same kwargs the real tkinter.filedialog
 accepts (title, filetypes, defaultextension, initialdir) and return
 the empty sentinel. This prevents TypeError if a call site passes
 kwargs that the stub does not know about.
 """
 bad = _LazyModule("os", "this_submodule_does_not_exist")
 resolved = bad._resolve()
 assert resolved.askopenfilename(title="x", filetypes=[("All", "*.*")]) == ""
 assert resolved.askdirectory(title="y", initialdir="/") == ""
 assert resolved.asksaveasfilename(title="z", defaultextension=".toml", filetypes=[("TOML", "*.toml")]) == ""
 assert resolved.askopenfilenames(filetypes=[("Image", "*.png")]) == ()


def test_lazymodule_real_filedialog_resolves_when_tkinter_works() -> None:
 """
 On a working tkinter install (with Tcl/Tk runtime), the
 `_LazyModule("tkinter", "filedialog")` instance must resolve to the
 real tkinter.filedialog module. This is the smoke test: if tkinter
 is healthy, the lazy import works as before.
 """
 import tkinter as tk_root
 try:
  import tkinter.filedialog as real_filedialog
 except (ImportError, AttributeError, tk_root.TclError):
  pytest.skip("tkinter.filedialog not available in this Python install")
 lazy = _LazyModule("tkinter", "filedialog")
 resolved = lazy._resolve()
 assert resolved is real_filedialog


def test_lazymodule_real_filedialog_does_not_raise_attribute_error() -> None:
 """
 On a working tkinter install, calling .askopenfilename() through the
 lazy module must not raise AttributeError. (Tests the call path
 used by 14 call sites in render_projects_panel etc.)
 """
 lazy = _LazyModule("tkinter", "filedialog")
 resolved = lazy._resolve()
 assert hasattr(resolved, "askopenfilename")
 assert hasattr(resolved, "askdirectory")
 assert hasattr(resolved, "asksaveasfilename")
 assert hasattr(resolved, "askopenfilenames")
