"""Tests for the TextbookTexSource (#000031 §5).

Pure unit tests over the strip_tex pipeline. Network ingest is
exercised via `make textbook-hilbert` / `make textbook-boole`; this
file stays offline.
"""

from __future__ import annotations

import pytest

from arborist.sources.textbook_tex import strip_tex


# --- preamble + postmatter stripping ---------------------------------


def test_strips_preamble_and_postmatter():
    tex = r"""
% comment line
\documentclass{book}
\usepackage{amsmath}
\title{Test Book}
\begin{document}
This is the body.
\end{document}
% trailing junk
"""
    out = strip_tex(tex)
    assert "documentclass" not in out
    assert "amsmath" not in out
    assert "trailing junk" not in out
    assert "This is the body." in out


def test_drops_line_comments():
    tex = r"""
\begin{document}
First sentence. % this is a comment
Second sentence.
\end{document}
"""
    out = strip_tex(tex)
    assert "comment" not in out.lower()
    assert "First sentence." in out
    assert "Second sentence." in out


# --- environment dropping --------------------------------------------


def test_drops_tabular_environment():
    tex = r"""
\begin{document}
Before table.
\begin{tabular}{lr}
foo & bar \\
\end{tabular}
After table.
\end{document}
"""
    out = strip_tex(tex)
    assert "Before table." in out
    assert "After table." in out
    assert "foo" not in out
    assert "tabular" not in out


def test_drops_figure_environment():
    tex = r"""
\begin{document}
Body 1.
\begin{figure}
\includegraphics{img.png}
\caption{Caption text}
\end{figure}
Body 2.
\end{document}
"""
    out = strip_tex(tex)
    assert "Body 1." in out
    assert "Body 2." in out
    assert "Caption text" not in out


# --- single-arg command stripping ------------------------------------


def test_keeps_arg_for_emphasis_commands():
    tex = r"""
\begin{document}
This is \textbf{bold} and \emph{italic} text.
\end{document}
"""
    out = strip_tex(tex)
    assert "bold" in out
    assert "italic" in out
    assert "textbf" not in out
    assert "emph" not in out


def test_keeps_arg_for_section_commands():
    tex = r"""
\begin{document}
\section{Introduction}
\subsection{Background}
Body text.
\end{document}
"""
    out = strip_tex(tex)
    assert "Introduction" in out
    assert "Background" in out
    assert "Body text." in out


def test_keeps_pg_custom_commands():
    """PG uses \\rfa for roman fixed all-caps section headings."""
    tex = r"""
\begin{document}
\rfa{CONTENTS}
Body.
\end{document}
"""
    out = strip_tex(tex)
    assert "CONTENTS" in out
    assert "rfa" not in out


# --- macro substitution ----------------------------------------------


@pytest.mark.parametrize(
    "tex_in,expected",
    [
        (r"\S 5", "§ 5"),
        (r"A \to B", "A → B"),
        (r"\neg P", "¬ P"),
        (r"P \lor Q", "P ∨ Q"),
        (r"P \land Q", "P ∧ Q"),
        (r"\forall x", "∀ x"),
        (r"\exists y", "∃ y"),
        (r"\alpha + \beta", "α + β"),
        (r"\dots", "…"),
        (r"x \in S", "x ∈ S"),
    ],
)
def test_macro_substitutions(tex_in, expected):
    tex = r"\begin{document}" + "\n" + tex_in + "\n" + r"\end{document}"
    out = strip_tex(tex)
    assert expected in out


# --- structural commands dropped -------------------------------------


def test_drops_structural_commands():
    tex = r"""
\begin{document}
\noindent Body. \bigskip
\thispagestyle{empty}
\setcounter{page}{1}
\label{intro}
\index{topic}
More body.
\end{document}
"""
    out = strip_tex(tex)
    assert "Body." in out
    assert "More body." in out
    assert "noindent" not in out
    assert "thispagestyle" not in out
    assert "setcounter" not in out
    assert "label" not in out
    assert "index" not in out


# --- whitespace cleanup ----------------------------------------------


def test_collapses_multi_blank_lines():
    tex = r"""
\begin{document}
First.



Second.



Third.
\end{document}
"""
    out = strip_tex(tex)
    # No more than 2 consecutive newlines (= 1 blank line)
    assert "\n\n\n" not in out


# --- end-to-end stability --------------------------------------------


def test_idempotent_on_already_stripped_text():
    """Plain ASCII text without any LaTeX should pass through with
    only whitespace normalization."""
    tex = r"""
\begin{document}
This is plain text with no LaTeX commands at all.
Multiple sentences. No special characters.
\end{document}
"""
    out = strip_tex(tex)
    assert "This is plain text" in out
    # Round-trip: stripping again should produce the same output.
    out2 = strip_tex(r"\begin{document}" + out + r"\end{document}")
    assert out2 == out
