"""Tests for brand guide generator."""

from __future__ import annotations

from pathlib import Path

import pytest
from pptx import Presentation

from pptx_mcp.brand.defaults import PRESETS, get_preset
from pptx_mcp.engine.brand_guide import generate_brand_guide
from pptx_mcp.models.brand import BrandConfig, ColorPalette, FontConfig, ToneStyle


def test_brand_guide_default_preset(tmp_path: Path):
    """Generate with executive preset, verify slide count."""
    brand = get_preset("executive")
    out = tmp_path / "guide.pptx"
    result = generate_brand_guide(brand, out)
    assert Path(result).exists()
    prs = Presentation(str(result))
    assert len(prs.slides) == 13


@pytest.mark.parametrize("preset_name", list(PRESETS.keys()))
def test_brand_guide_each_preset(preset_name: str, tmp_path: Path):
    """Each of the 12 presets should render a brand guide successfully."""
    brand = get_preset(preset_name)
    out = tmp_path / f"guide_{preset_name}.pptx"
    result = generate_brand_guide(brand, out)
    assert Path(result).exists()
    prs = Presentation(str(result))
    assert len(prs.slides) == 13


def test_brand_guide_color_slide_content(tmp_path: Path):
    """Verify color hex values appear in the color swatch slide text."""
    brand = get_preset("consulting")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    # Slide 2 (index 1) is the color swatches visual specimen
    color_slide = prs.slides[1]
    all_text = " ".join(
        shape.text_frame.text
        for shape in color_slide.shapes
        if shape.has_text_frame
    )
    assert brand.colors.primary.upper() in all_text.upper()
    assert brand.colors.accent.upper() in all_text.upper()


def test_brand_guide_typography_slide(tmp_path: Path):
    """Verify font names appear in the typography slide."""
    brand = get_preset("startup")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    # Slide 3 (index 2) is the typography visual specimen
    typo_slide = prs.slides[2]
    all_text = " ".join(
        shape.text_frame.text
        for shape in typo_slide.shapes
        if shape.has_text_frame
    )
    assert brand.fonts.heading_font in all_text
    assert brand.fonts.body_font in all_text


def test_brand_guide_custom_brand(tmp_path: Path):
    """Generate with a fully custom BrandConfig (not a preset)."""
    brand = BrandConfig(
        name="Custom Corp",
        colors=ColorPalette(
            primary="#FF0000",
            secondary="#00FF00",
            accent="#0000FF",
        ),
        fonts=FontConfig(
            heading_font="Arial",
            body_font="Verdana",
        ),
        tone=ToneStyle.CORPORATE,
    )
    out = tmp_path / "custom_guide.pptx"
    result = generate_brand_guide(brand, out)
    assert Path(result).exists()
    prs = Presentation(str(result))
    assert len(prs.slides) == 13


def test_brand_guide_title_slide_text(tmp_path: Path):
    """Title slide should contain the brand name."""
    brand = get_preset("finance")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    title_slide = prs.slides[0]
    all_text = " ".join(
        shape.text_frame.text
        for shape in title_slide.shapes
        if shape.has_text_frame
    )
    assert "Finance" in all_text


def test_brand_guide_closing_slide_info(tmp_path: Path):
    """Closing slide should mention shape style details."""
    brand = get_preset("consulting")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    closing_slide = prs.slides[-1]
    all_text = " ".join(
        shape.text_frame.text
        for shape in closing_slide.shapes
        if shape.has_text_frame
    )
    # Should mention shadow and slide number config
    assert "Shadow" in all_text or "Slide Number" in all_text


def test_brand_guide_dashboard_slide_has_kpis(tmp_path: Path):
    """Dashboard slide should have KPI-like text content."""
    brand = get_preset("healthcare")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    # Slide 6 (index 5) is the dashboard (after 4 visual specimen slides)
    dashboard_slide = prs.slides[5]
    all_text = " ".join(
        shape.text_frame.text
        for shape in dashboard_slide.shapes
        if shape.has_text_frame
    )
    # Should have KPI values from our sample data
    assert "$2.4M" in all_text or "Revenue" in all_text


def test_brand_guide_output_path_validation(tmp_path: Path):
    """Invalid output path should raise an error."""
    brand = get_preset("executive")
    out = tmp_path / "guide.txt"  # Wrong extension
    with pytest.raises(Exception):
        generate_brand_guide(brand, out)


def test_brand_guide_spacing_slide(tmp_path: Path):
    """Spacing diagram slide should contain margin values."""
    brand = get_preset("executive")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    # Slide 4 (index 3) is the spacing diagram
    spacing_slide = prs.slides[3]
    all_text = " ".join(
        shape.text_frame.text
        for shape in spacing_slide.shapes
        if shape.has_text_frame
    )
    assert "Margin" in all_text
    assert "Content Area" in all_text


def test_brand_guide_shape_style_slide(tmp_path: Path):
    """Shape style slide should show corner radius info."""
    brand = get_preset("consulting")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    # Slide 5 (index 4) is the shape style showcase
    shape_slide = prs.slides[4]
    all_text = " ".join(
        shape.text_frame.text
        for shape in shape_slide.shapes
        if shape.has_text_frame
    )
    assert "Corner Radius" in all_text
    assert "Shadow" in all_text or "Pill" in all_text


def test_brand_guide_dos_and_donts_slide(tmp_path: Path):
    """Do's and Don'ts slide should have check and X mark items."""
    brand = get_preset("minimal")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    # Slide 12 (index 11) is Do's and Don'ts
    dos_slide = prs.slides[11]
    all_text = " ".join(
        shape.text_frame.text
        for shape in dos_slide.shapes
        if shape.has_text_frame
    )
    assert "Do" in all_text
    assert "Don't" in all_text
    assert "brand colors" in all_text.lower()


def test_brand_guide_two_column_slide(tmp_path: Path):
    """Two-column slide should be present in the deck."""
    brand = get_preset("creative")
    out = tmp_path / "guide.pptx"
    generate_brand_guide(brand, out)
    prs = Presentation(str(out))
    # Slide 11 (index 10) is the two-column layout
    two_col_slide = prs.slides[10]
    all_text = " ".join(
        shape.text_frame.text
        for shape in two_col_slide.shapes
        if shape.has_text_frame
    )
    assert "visual hierarchy" in all_text.lower() or "Two-Column" in all_text
