"""REQ-274: tests for `scripts/render_pptx.py` — the structured, editable
python-pptx deck produced alongside the MARP-rendered PPTX.

The python-pptx deck is a native OOXML presentation: real text boxes,
native tables, embedded pictures, and italic benefit callouts. These
tests are offline (no AWS, no network) and assert the structural
properties of the committed `*-python.pptx` artifact.
"""
from pathlib import Path
from typing import cast

import pytest
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE_TYPE
from pptx.presentation import Presentation as PresentationT
from pptx.shapes.autoshape import Shape

ROOT = Path(__file__).resolve().parent.parent
PRESENTATIONS = ROOT / "docs" / "presentations"
MARPT_DECK = PRESENTATIONS / "nova-autonomous-cloud-delivery-marp.md"
PYTHON_PPTX = PRESENTATIONS / "nova-autonomous-cloud-delivery-python.pptx"

# Title slide + 20 main slides + 1 appendix slide.
EXPECTED_SLIDE_COUNT = 22


@pytest.fixture(scope="module")
def prs() -> PresentationT:
    """Load the committed python-pptx deck once for the whole module."""
    assert PYTHON_PPTX.is_file(), f"python-pptx PPTX not found: {PYTHON_PPTX}"
    return Presentation(str(PYTHON_PPTX))


def _slide_titles(prs: PresentationT) -> list[str]:
    """Return the first non-empty text-frame line per slide (the title)."""
    titles: list[str] = []
    for slide in prs.slides:
        for shape in slide.shapes:
            if not shape.has_text_frame:
                continue
            text = cast(Shape, shape).text_frame.text.strip()
            if not text:
                continue
            # The title is the first non-empty line of the first non-empty
            # text frame we find on the slide.
            first_line = text.split("\n")[0].strip()
            if first_line:
                titles.append(first_line)
                break
        else:
            titles.append("")
    return titles


def test_slide_count(prs: PresentationT):
    """REQ-269/274: the python-pptx deck has 22 slides
    (title + 20 main + 1 appendix)."""
    assert len(prs.slides) == EXPECTED_SLIDE_COUNT, \
        f"expected {EXPECTED_SLIDE_COUNT} slides, got {len(prs.slides)}"


def test_title_slide_colors(prs: PresentationT):
    """REQ-269: the title slide (slide 0) has a solid-filled background
    shape carrying the S&P Red (#D6002A) brand color (the title slide is
    a red-bar-on-black layout)."""
    title_slide = prs.slides[0]
    red_found = False
    black_found = False
    for shape in title_slide.shapes:
        fill = getattr(shape, "fill", None)
        if fill is None:
            continue
        try:
            if fill.type != 1:  # MSO_FILL.SOLID
                continue
        except Exception:
            continue
        rgb = str(fill.fore_color.rgb).upper()
        if rgb == "D6002A":
            red_found = True
        if rgb == "1B1B1B":
            black_found = True
    assert red_found, \
        "title slide has no solid-fill shape with S&P Red (#D6002A)"


def test_expected_slide_titles(prs: PresentationT):
    """REQ-269/274: spot-check that key slide titles match the markdown
    deck (The Problem, Nova's Vision, Recap + Ask)."""
    titles = _slide_titles(prs)
    # Build a flat lowercase concatenation for substring checks.
    flat = " | ".join(titles).lower()
    expected = [
        "the problem",
        "nova's vision",
        "recap + ask",
    ]
    missing = [t for t in expected if t not in flat]
    assert not missing, \
        f"missing expected slide titles in python-pptx deck: {missing}; " \
        f"found titles: {titles}"


def test_table_rendering(prs: PresentationT):
    """REQ-269: a slide with a table (the RACI slide) has a native PPTX
    table shape (GraphicFrame with has_table=True)."""
    table_slides = []
    for idx, slide in enumerate(prs.slides):
        for shape in slide.shapes:
            if shape.shape_type == MSO_SHAPE_TYPE.TABLE or getattr(
                shape, "has_table", False
            ):
                table_slides.append(idx)
                break
    assert table_slides, \
        "no slide in the python-pptx deck has a native PPTX table shape"


def test_image_embedding(prs: PresentationT):
    """REQ-269: a slide with an image (the Platform Pipeline slide)
    has a native PPTX picture shape."""
    picture_slides = []
    for idx, slide in enumerate(prs.slides):
        for shape in slide.shapes:
            if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
                picture_slides.append(idx)
                break
    assert picture_slides, \
        "no slide in the python-pptx deck has a native PPTX picture shape"


def test_benefit_callout_present(prs: PresentationT):
    """REQ-269/274: at least one slide has an italic text run (the
    benefit callout, rendered as italic body text by render_pptx.py)."""
    italic_runs = 0
    for slide in prs.slides:
        for shape in slide.shapes:
            if not shape.has_text_frame:
                continue
            for paragraph in cast(Shape, shape).text_frame.paragraphs:
                for run in paragraph.runs:
                    if run.font.italic and run.text.strip():
                        italic_runs += 1
    assert italic_runs > 0, \
        "no italic text runs found in the python-pptx deck (benefit callout)"