"""
Unit tests for GraphExporter.

Tests DOT and Mermaid export with various graph shapes.
"""

import pytest

from markitect.prompts.dependencies.models import DependencyGraph, EdgeType
from markitect.prompts.visualization.graph import GraphExporter


@pytest.fixture
def empty_graph():
    """Empty graph with no nodes."""
    return DependencyGraph()


@pytest.fixture
def single_node_graph():
    """Graph with a single isolated node."""
    g = DependencyGraph()
    g._forward["node-a"] = set()
    g._reverse["node-a"] = set()
    return g


@pytest.fixture
def linear_graph():
    """Linear chain: A -> B -> C."""
    g = DependencyGraph()
    g.add_edge("A", "B", EdgeType.REQUIRES)
    g.add_edge("B", "C", EdgeType.GENERATES)
    return g


@pytest.fixture
def diamond_graph():
    """Diamond: A -> B, A -> C, B -> D, C -> D."""
    g = DependencyGraph()
    g.add_edge("A", "B", EdgeType.REQUIRES)
    g.add_edge("A", "C", EdgeType.REQUIRES)
    g.add_edge("B", "D", EdgeType.GENERATES)
    g.add_edge("C", "D", EdgeType.INCLUDES)
    return g


class TestToDot:
    """Tests for to_dot export."""

    def test_empty_graph(self, empty_graph):
        """Test DOT output for empty graph."""
        dot = GraphExporter.to_dot(empty_graph)
        assert 'digraph "Dependencies"' in dot
        assert "rankdir=LR" in dot

    def test_single_node(self, single_node_graph):
        """Test DOT output with single node."""
        dot = GraphExporter.to_dot(single_node_graph)
        assert "node_a" in dot
        assert 'label="node-a"' in dot

    def test_linear_graph(self, linear_graph):
        """Test DOT output for linear chain."""
        dot = GraphExporter.to_dot(linear_graph)
        assert "A -> B" in dot
        assert "B -> C" in dot
        assert 'label="requires"' in dot
        assert 'label="generates"' in dot

    def test_diamond_graph(self, diamond_graph):
        """Test DOT output for diamond graph."""
        dot = GraphExporter.to_dot(diamond_graph)
        assert "A -> B" in dot
        assert "A -> C" in dot
        assert "B -> D" in dot
        assert "C -> D" in dot

    def test_custom_title(self, linear_graph):
        """Test DOT output with custom title."""
        dot = GraphExporter.to_dot(linear_graph, title="My Graph")
        assert 'digraph "My Graph"' in dot
        assert 'label="My Graph"' in dot

    def test_edge_styles(self, linear_graph):
        """Test DOT edge styles for different edge types."""
        dot = GraphExporter.to_dot(linear_graph)
        assert 'style="solid"' in dot  # REQUIRES
        assert 'style="dashed"' in dot  # GENERATES

    def test_dot_is_valid_structure(self, diamond_graph):
        """Test DOT output has valid opening/closing braces."""
        dot = GraphExporter.to_dot(diamond_graph)
        assert dot.startswith('digraph')
        assert dot.endswith("}")


class TestToMermaid:
    """Tests for to_mermaid export."""

    def test_empty_graph(self, empty_graph):
        """Test Mermaid output for empty graph."""
        mermaid = GraphExporter.to_mermaid(empty_graph)
        assert "graph LR" in mermaid

    def test_single_node(self, single_node_graph):
        """Test Mermaid output with single node."""
        mermaid = GraphExporter.to_mermaid(single_node_graph)
        assert "node-a" in mermaid

    def test_linear_graph(self, linear_graph):
        """Test Mermaid output for linear chain."""
        mermaid = GraphExporter.to_mermaid(linear_graph)
        assert "A-->|requires|B" in mermaid
        assert "B-.->|generates|C" in mermaid

    def test_diamond_graph(self, diamond_graph):
        """Test Mermaid output for diamond graph."""
        mermaid = GraphExporter.to_mermaid(diamond_graph)
        assert "A-->|requires|B" in mermaid
        assert "A-->|requires|C" in mermaid
        assert "B-.->|generates|D" in mermaid
        assert "C==>|includes|D" in mermaid

    def test_custom_title(self, linear_graph):
        """Test Mermaid output with custom title."""
        mermaid = GraphExporter.to_mermaid(linear_graph, title="Build Graph")
        assert "Build Graph" in mermaid

    def test_edge_arrows(self, diamond_graph):
        """Test Mermaid edge arrows for different types."""
        mermaid = GraphExporter.to_mermaid(diamond_graph)
        assert "-->" in mermaid   # REQUIRES
        assert "-.->" in mermaid  # GENERATES
        assert "==>" in mermaid   # INCLUDES

    def test_mermaid_starts_with_graph(self, linear_graph):
        """Test Mermaid output starts with graph directive."""
        mermaid = GraphExporter.to_mermaid(linear_graph)
        lines = mermaid.strip().split("\n")
        assert "graph LR" in lines[1]
