"""Tests for the --fix-contrast opt-in wiring in scripts/remediate_pdf.py.

pdf_contrast.remediate_contrast's own recolor logic is covered by
tests/test_pdf_contrast.py and is NOT re-tested here. This file only tests
the wiring: default-off is a no-op, opt-in runs after gates_ok (never before
-- see remediate_pdf.py's _run_contrast_step docstring for why), and a
veraPDF regression on the recolored file is discarded without failing the
whole remediation.

CI-light: mocks _run_e2 (no vendored ODL/java needed) and
verapdf_gate.run_verapdf (no vendored veraPDF needed), matching
test_remediate_pdf_fontflag.py's pattern.
"""
import os
import shutil
import sys

import fitz  # PyMuPDF

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))

import remediate_pdf as rp

_LOW_CONTRAST_GREEN = (61, 179, 112)


def _low_contrast_pdf(path):
    doc = fitz.open()
    page = doc.new_page(width=200, height=200)
    page.insert_text((10, 30), "Low Contrast Heading", fontsize=14,
                      color=tuple(c / 255 for c in _LOW_CONTRAST_GREEN))
    page.insert_text((10, 80), "Normal body text", fontsize=10, color=(0, 0, 0))
    doc.save(str(path))
    doc.close()
    return path


def _fake_run_e2(work_input, input_path, output_path, judgment, title, lang, notes):
    shutil.copy(str(work_input), str(output_path))
    return {"promotions": [], "alts_set": {}, "tables_flagged": []}, title or "T"


def _span_rgb(pdf_path, text_substr):
    doc = fitz.open(str(pdf_path))
    found = None
    for page in doc:
        for block in page.get_text("dict")["blocks"]:
            for line in block.get("lines", []):
                for span in line.get("spans", []):
                    if text_substr in span["text"]:
                        ci = span["color"]
                        found = ((ci >> 16) & 255, (ci >> 8) & 255, ci & 255)
    doc.close()
    return found


def _tmp_marker_exists(output_path):
    return output_path.with_name(output_path.name + ".contrast-tmp.pdf").exists()


class TestFixContrastWiring:
    def test_default_off_no_contrast_key_and_output_untouched(self, tmp_path, monkeypatch):
        p = _low_contrast_pdf(tmp_path / "in.pdf")
        monkeypatch.setattr(rp, "_run_e2", _fake_run_e2)
        monkeypatch.setattr(
            rp.verapdf_gate, "run_verapdf",
            lambda *_a, **_k: {"compliant": True, "failed_summaries": []},
        )

        out = tmp_path / "out.pdf"
        result = rp.remediate_pdf(p, out, judgment={}, cls="digital-untagged")

        assert result["ok"] is True
        assert "contrast" not in result
        assert _span_rgb(out, "Heading") == _LOW_CONTRAST_GREEN

    def test_fix_contrast_runs_after_gates_and_recolors(self, tmp_path, monkeypatch):
        p = _low_contrast_pdf(tmp_path / "in.pdf")
        monkeypatch.setattr(rp, "_run_e2", _fake_run_e2)
        monkeypatch.setattr(
            rp.verapdf_gate, "run_verapdf",
            lambda *_a, **_k: {"compliant": True, "failed_summaries": []},
        )

        out = tmp_path / "out.pdf"
        result = rp.remediate_pdf(p, out, judgment={}, cls="digital-untagged", fix_contrast=True)

        assert result["ok"] is True
        assert result["output"] == str(out)
        assert "contrast" in result
        assert result["contrast"]["fixed"]
        assert not result["contrast"].get("skipped")
        assert result["verapdf"]["compliant"] is True

        recolored = _span_rgb(out, "Heading")
        assert recolored != _LOW_CONTRAST_GREEN
        assert _span_rgb(out, "body") == (0, 0, 0)  # untouched
        assert not _tmp_marker_exists(out)

    def test_fix_contrast_skipped_when_gates_fail(self, tmp_path, monkeypatch):
        p = _low_contrast_pdf(tmp_path / "in.pdf")
        monkeypatch.setattr(rp, "_run_e2", _fake_run_e2)
        monkeypatch.setattr(
            rp.verapdf_gate, "run_verapdf",
            lambda *_a, **_k: {
                "compliant": False,
                "failed_summaries": [{"clause": "7.1", "description": "unrelated"}],
            },
        )

        out = tmp_path / "out.pdf"
        result = rp.remediate_pdf(p, out, judgment={}, cls="digital-untagged", fix_contrast=True)

        assert result["ok"] is False
        assert "contrast" not in result

    def test_fix_contrast_discards_when_verapdf_regresses(self, tmp_path, monkeypatch):
        p = _low_contrast_pdf(tmp_path / "in.pdf")
        monkeypatch.setattr(rp, "_run_e2", _fake_run_e2)

        calls = {"n": 0}

        def fake_verapdf(_path):
            calls["n"] += 1
            if calls["n"] == 1:  # main-flow gate check
                return {"compliant": True, "failed_summaries": []}
            return {  # post-contrast re-check
                "compliant": False,
                "failed_summaries": [{"clause": "7.1", "description": "regression"}],
            }

        monkeypatch.setattr(rp.verapdf_gate, "run_verapdf", fake_verapdf)

        out = tmp_path / "out.pdf"
        result = rp.remediate_pdf(p, out, judgment={}, cls="digital-untagged", fix_contrast=True)

        assert result["ok"] is True  # contrast regression never fails the whole remediation
        assert result["output"] == str(out)
        assert result["contrast"]["skipped"] == "veraPDF regressed after recolor"
        assert result["verapdf"]["compliant"] is True  # original (pre-contrast) result kept
        assert _span_rgb(out, "Heading") == _LOW_CONTRAST_GREEN  # tagged-only output kept
        assert not _tmp_marker_exists(out)
