"""Tests for scripts/fidelity_gate.py and scripts/verapdf_gate.py.

fidelity_gate tests are CI-light (PyMuPDF only). verapdf_gate tests split:
the vendor-missing error path is CI-light; an actual compliance run needs
the remediation_tools marker (vendored java + veraPDF)."""

import os
import sys

import fitz  # PyMuPDF
import pytest

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

import fidelity_gate
import setup_remediation
import verapdf_gate

REMEDIATION_TOOLS_READY = bool(setup_remediation.get_java() and setup_remediation.get_verapdf())


def _blank_pdf(path, text="Hello world", w=200, h=200):
    doc = fitz.open()
    page = doc.new_page(width=w, height=h)
    if text:
        page.insert_text((10, 20), text, fontsize=12)
    doc.save(str(path))
    doc.close()
    return path


class TestPixelDiff:
    def test_identical_files_are_identical(self, tmp_path):
        a = _blank_pdf(tmp_path / "a.pdf")
        result = fidelity_gate.pixel_diff(a, a)
        assert result["identical"] is True
        assert result["worst_pct"] == 0.0
        assert result["pages_diff"] == []

    def test_different_visible_content_is_not_identical(self, tmp_path):
        a = _blank_pdf(tmp_path / "a.pdf", text="Hello world")
        b = _blank_pdf(tmp_path / "b.pdf", text="Something else entirely, much longer text")
        result = fidelity_gate.pixel_diff(a, b)
        assert result["identical"] is False
        assert result["worst_pct"] > 0
        assert result["pages_diff"][0]["page"] == 1

    def test_page_count_mismatch_is_not_identical(self, tmp_path):
        a = _blank_pdf(tmp_path / "a.pdf")
        doc = fitz.open()
        doc.new_page(width=200, height=200)
        doc.new_page(width=200, height=200)
        b = tmp_path / "b.pdf"
        doc.save(str(b))
        doc.close()

        result = fidelity_gate.pixel_diff(a, b)
        assert result["identical"] is False
        assert result["reason"] == "page_count_mismatch"

    def test_threshold_pct_allows_bounded_diff(self, tmp_path):
        a = _blank_pdf(tmp_path / "a.pdf", text="Hello world")
        b = _blank_pdf(tmp_path / "b.pdf", text="Hello world!")  # small diff
        exact = fidelity_gate.pixel_diff(a, b)
        assert exact["identical"] is False
        worst = exact["worst_pct"]

        assert fidelity_gate.pixel_diff(a, b, threshold_pct=worst)["identical"] is True
        assert fidelity_gate.pixel_diff(a, b, threshold_pct=max(worst - 0.0001, 0))["identical"] is False

    def test_threshold_pct_default_is_exact_zero(self, tmp_path):
        a = _blank_pdf(tmp_path / "a.pdf", text="Hello world")
        b = _blank_pdf(tmp_path / "b.pdf", text="Hello world!")
        assert fidelity_gate.pixel_diff(a, b)["identical"] is \
            fidelity_gate.pixel_diff(a, b, threshold_pct=0.0)["identical"]

    def test_invisible_render_mode_3_text_does_not_count_as_diff(self, tmp_path):
        """render_mode=3 (invisible) is exactly what ocr_text_layer relies on
        to add a text layer without breaking the fidelity gate — prove it here
        without needing OCR/Vision."""
        a = _blank_pdf(tmp_path / "a.pdf")
        doc = fitz.open(str(a))
        doc[0].insert_text((50, 100), "invisible OCR text", fontsize=10, render_mode=3)
        b = tmp_path / "b.pdf"
        doc.save(str(b))
        doc.close()

        result = fidelity_gate.pixel_diff(a, b)
        assert result["identical"] is True


class TestPixelDiffCli:
    def test_cli_default_threshold_is_exact_zero(self, tmp_path, monkeypatch):
        a = _blank_pdf(tmp_path / "a.pdf", text="Hello world")
        b = _blank_pdf(tmp_path / "b.pdf", text="Hello world!")
        monkeypatch.setattr(sys, "argv", ["fidelity_gate.py", str(a), str(b), "--json"])
        with pytest.raises(SystemExit) as exc:
            fidelity_gate.main()
        assert exc.value.code == 1  # differs at the default exact-zero bar

    def test_cli_threshold_pct_flag_widens_the_bar(self, tmp_path, monkeypatch):
        a = _blank_pdf(tmp_path / "a.pdf", text="Hello world")
        b = _blank_pdf(tmp_path / "b.pdf", text="Hello world!")
        worst = fidelity_gate.pixel_diff(a, b)["worst_pct"]
        monkeypatch.setattr(sys, "argv",
                             ["fidelity_gate.py", str(a), str(b), "--threshold-pct", str(worst)])
        with pytest.raises(SystemExit) as exc:
            fidelity_gate.main()
        assert exc.value.code == 0


class TestVerapdfGateVendorMissing:
    def test_raises_clear_error_when_vendor_absent(self, monkeypatch):
        monkeypatch.setattr(verapdf_gate.setup_remediation, "get_java", lambda: None)
        monkeypatch.setattr(verapdf_gate.setup_remediation, "get_verapdf", lambda: None)
        with pytest.raises(RuntimeError, match="not installed"):
            verapdf_gate.run_verapdf("/nonexistent.pdf")


@pytest.mark.remediation_tools
@pytest.mark.skipif(not REMEDIATION_TOOLS_READY, reason="vendored java/verapdf not installed")
class TestVerapdfGateLive:
    def test_untagged_pdf_is_not_compliant(self, tmp_path):
        p = _blank_pdf(tmp_path / "untagged.pdf")
        result = verapdf_gate.run_verapdf(p)
        assert result["compliant"] is False
        assert result["failed_rules"] > 0
        assert result["matterhorn_human_checkpoints"] == 47
        assert "PDF/UA-1" in result["profile"]

    def test_nonexistent_file_raises_runtime_error(self, tmp_path):
        with pytest.raises(RuntimeError):
            verapdf_gate.run_verapdf(tmp_path / "does_not_exist.pdf")
