"""Message d'aide localisant les documents non livrés (P1-5) + ouverture dossier.

Pur : pas de display. ``failure_hint`` formate un texte ; ``open_in_file_manager``
dispatch vers la bonne commande OS (monkeypatchée).
"""
from __future__ import annotations

from pathlib import Path

import pytest

import gui_v6.fsutil as fsutil
from gui_v6.processing_runner import RunSummary
from gui_v6.tabs.tab_usage import failure_hint


def test_no_hint_when_all_ok():
    s = RunSummary(total=3, succeeded=3, failed=0)
    assert failure_hint(s, Path("/out")) is None


def test_hint_when_failures_mentions_output_dir():
    s = RunSummary(total=3, succeeded=2, failed=1)
    hint = failure_hint(s, Path("/out/anonymise"))
    assert hint is not None
    assert "/out/anonymise" in hint
    # Honnêteté : préciser que les échecs ne sont PAS anonymisés.
    assert "pas" in hint.lower()


def test_hint_when_stopped():
    s = RunSummary(total=3, succeeded=1, failed=0, stopped=True)
    assert failure_hint(s, Path("/out")) is not None


def test_no_hint_without_output_dir():
    s = RunSummary(total=1, succeeded=0, failed=1)
    assert failure_hint(s, None) is None


def test_open_in_file_manager_dispatches(monkeypatch):
    calls = {}
    monkeypatch.setattr(fsutil.sys, "platform", "linux")
    monkeypatch.setattr(fsutil.subprocess, "Popen", lambda args, **k: calls.setdefault("args", args))
    fsutil.open_in_file_manager(Path("/out"))
    assert calls["args"][0] == "xdg-open"
    assert calls["args"][1] == "/out"


def test_no_claim_written_when_zero_succeeded():
    """0 succès : ne pas prétendre qu'un dossier contient des documents écrits."""
    s = RunSummary(total=2, succeeded=0, failed=2)
    hint = failure_hint(s, Path("/out"))
    assert hint is not None
    assert "écrits dans" not in hint
    assert "Aucun document" in hint


def test_hint_with_path_when_some_succeeded():
    """≥1 succès : localiser le dossier de sortie effectif."""
    s = RunSummary(total=3, succeeded=2, failed=1)
    hint = failure_hint(s, Path("/out"))
    assert hint is not None
    assert "/out" in hint
    assert "écrits dans" in hint


# -- garde anti-régression du bug Critical (empilement de widgets) -----------


@pytest.fixture
def usage_tab():
    """``UsageTab`` headless (Xvfb) — skip propre si pas de display."""
    pytest.importorskip("customtkinter")
    try:
        import customtkinter as ctk

        from gui_v6.tabs.tab_usage import UsageTab

        root = ctk.CTk()
        root.withdraw()
        tab = UsageTab(root)
    except Exception as exc:  # pas de display Tk
        pytest.skip(f"display Tk indisponible: {exc}")
    try:
        yield tab
    finally:
        try:
            root.destroy()
        except Exception:
            pass


def test_show_failure_hint_does_not_accumulate(usage_tab):
    """Bug Critical : deux runs en échec ne doivent pas empiler de hints sous
    ``_rsec`` (handle ``_hint_row`` détruit inconditionnellement)."""
    usage_tab._last_output_dir = Path("/out")
    summary = RunSummary(total=3, succeeded=2, failed=1)

    usage_tab._show_failure_hint(summary)
    count_after_first = len(usage_tab._rsec.winfo_children())

    usage_tab._show_failure_hint(summary)
    count_after_second = len(usage_tab._rsec.winfo_children())

    assert count_after_second == count_after_first


def test_show_failure_hint_clears_stale_hint(usage_tab):
    """Un run en échec suivi d'un run nominal ne doit pas laisser de hint périmé."""
    usage_tab._last_output_dir = Path("/out")
    usage_tab._show_failure_hint(RunSummary(total=3, succeeded=2, failed=1))
    with_hint = len(usage_tab._rsec.winfo_children())

    usage_tab._show_failure_hint(RunSummary(total=3, succeeded=3, failed=0))
    without_hint = len(usage_tab._rsec.winfo_children())

    assert without_hint == with_hint - 1
