"""CLI smoke tests using click.testing.CliRunner."""

from __future__ import annotations

import json
from pathlib import Path

import pytest
from click.testing import CliRunner

from pptx_mcp.brand.defaults import executive_default
from pptx_mcp.cli import main
from pptx_mcp.engine.generator import DeckGenerator
from pptx_mcp.models.slides import (
    PresentationDefinition,
    PresentationMetadata,
    SlideDefinition,
    SlideType,
)


@pytest.fixture
def runner() -> CliRunner:
    return CliRunner()


@pytest.fixture
def sample_deck_json() -> str:
    """Path to the bundled sample_deck.json in the examples directory."""
    return str(Path(__file__).resolve().parent.parent / "examples" / "sample_deck.json")


def _generate_pptx(tmp_path: Path) -> Path:
    """Generate a real pptx for CLI tests that need an existing file."""
    definition = PresentationDefinition(
        metadata=PresentationMetadata(title="CLI Test"),
        slides=[
            SlideDefinition(slide_type=SlideType.TITLE, title="CLI Deck", subtitle="Test"),
            SlideDefinition(
                slide_type=SlideType.CONTENT,
                title="Content",
                bullets=["Point 1", "Point 2"],
            ),
        ],
    )
    generator = DeckGenerator(brand=executive_default())
    out = tmp_path / "cli_test.pptx"
    generator.generate(definition, out)
    return out


class TestHelpCommand:
    """Test that --help works."""

    def test_help_returns_zero(self, runner: CliRunner) -> None:
        result = runner.invoke(main, ["--help"])
        assert result.exit_code == 0
        assert "PPTX MCP" in result.output

    def test_generate_help(self, runner: CliRunner) -> None:
        result = runner.invoke(main, ["generate", "--help"])
        assert result.exit_code == 0
        assert "DEFINITION_PATH" in result.output

    def test_plan_help(self, runner: CliRunner) -> None:
        result = runner.invoke(main, ["plan", "--help"])
        assert result.exit_code == 0
        assert "TOPIC" in result.output

    def test_review_help(self, runner: CliRunner) -> None:
        result = runner.invoke(main, ["review", "--help"])
        assert result.exit_code == 0
        assert "FILE_PATH" in result.output


class TestPlanCommand:
    """Test the 'plan' subcommand."""

    def test_plan_outputs_json(self, runner: CliRunner) -> None:
        result = runner.invoke(main, ["plan", "Test Topic", "-n", "5"])
        assert result.exit_code == 0
        parsed = json.loads(result.output)
        assert "slides" in parsed
        assert len(parsed["slides"]) >= 3

    def test_plan_with_audience(self, runner: CliRunner) -> None:
        result = runner.invoke(main, ["plan", "Tech Review", "-n", "5", "-a", "technical"])
        assert result.exit_code == 0
        parsed = json.loads(result.output)
        assert "slides" in parsed


class TestGenerateCommand:
    """Test the 'generate' subcommand."""

    def test_generate_from_sample_json(
        self, runner: CliRunner, sample_deck_json: str, tmp_path: Path
    ) -> None:
        out = str(tmp_path / "generated.pptx")
        result = runner.invoke(main, ["generate", sample_deck_json, out])
        assert result.exit_code == 0
        assert Path(out).exists()
        assert "Generated:" in result.output

    def test_generate_with_preset(
        self, runner: CliRunner, sample_deck_json: str, tmp_path: Path
    ) -> None:
        out = str(tmp_path / "branded.pptx")
        result = runner.invoke(main, ["generate", sample_deck_json, out, "-p", "technical"])
        assert result.exit_code == 0
        assert Path(out).exists()


class TestReadCommand:
    """Test the 'read' subcommand."""

    def test_read_outputs_json(self, runner: CliRunner, tmp_path: Path) -> None:
        pptx_path = _generate_pptx(tmp_path)
        result = runner.invoke(main, ["read", str(pptx_path)])
        assert result.exit_code == 0
        parsed = json.loads(result.output)
        assert "slides" in parsed
        assert len(parsed["slides"]) == 2

    def test_read_to_output_file(self, runner: CliRunner, tmp_path: Path) -> None:
        pptx_path = _generate_pptx(tmp_path)
        out_json = str(tmp_path / "parsed.json")
        result = runner.invoke(main, ["read", str(pptx_path), "-o", out_json])
        assert result.exit_code == 0
        assert Path(out_json).exists()


class TestReviewCommand:
    """Test the 'review' subcommand."""

    def test_review_outputs_score(self, runner: CliRunner, tmp_path: Path) -> None:
        pptx_path = _generate_pptx(tmp_path)
        result = runner.invoke(main, ["review", str(pptx_path)])
        assert result.exit_code == 0
        assert "Score:" in result.output
        assert "/10.0" in result.output

    def test_review_to_output_file(self, runner: CliRunner, tmp_path: Path) -> None:
        pptx_path = _generate_pptx(tmp_path)
        out_json = str(tmp_path / "review.json")
        result = runner.invoke(main, ["review", str(pptx_path), "-o", out_json])
        assert result.exit_code == 0
        assert Path(out_json).exists()
        parsed = json.loads(Path(out_json).read_text())
        assert "overall_score" in parsed
