"""Tests for Topic class."""

import pytest

from py_xmind16.topic import Topic


class TestTopicCreation:
    """Tests for topic creation."""
    
    def test_create_empty_topic(self):
        """Test creating an empty topic."""
        topic = Topic()
        assert topic.title == ""
        assert topic.id is not None
        assert len(topic.id) == 32  # UUID without dashes
    
    def test_create_topic_with_title(self):
        """Test creating a topic with a title."""
        topic = Topic(title="My Topic")
        assert topic.title == "My Topic"
    
    def test_create_topic_with_id(self):
        """Test creating a topic with a specific ID."""
        custom_id = "custom123"
        topic = Topic(id=custom_id)
        assert topic.id == custom_id
    
    def test_topic_title_setter(self):
        """Test setting topic title."""
        topic = Topic()
        topic.title = "New Title"
        assert topic.title == "New Title"


class TestTopicHierarchy:
    """Tests for topic hierarchy operations."""
    
    def test_add_subtopic(self):
        """Test adding a subtopic."""
        parent = Topic(title="Parent")
        child = parent.add_subtopic("Child")
        
        assert child.title == "Child"
        assert child.parent == parent
        assert child in parent.subtopics
    
    def test_add_multiple_subtopics(self):
        """Test adding multiple subtopics."""
        parent = Topic(title="Parent")
        child1 = parent.add_subtopic("Child 1")
        child2 = parent.add_subtopic("Child 2")
        
        assert len(parent.subtopics) == 2
        assert child1 in parent.subtopics
        assert child2 in parent.subtopics
    
    def test_remove_subtopic(self):
        """Test removing a subtopic."""
        parent = Topic(title="Parent")
        child = parent.add_subtopic("Child")
        
        result = parent.remove_subtopic(child)
        
        assert result is True
        assert child not in parent.subtopics
        assert child.parent is None
    
    def test_remove_nonexistent_subtopic(self):
        """Test removing a subtopic that doesn't exist."""
        parent = Topic(title="Parent")
        other = Topic(title="Other")
        
        result = parent.remove_subtopic(other)
        
        assert result is False
    
    def test_find_subtopic(self):
        """Test finding a subtopic by title."""
        parent = Topic(title="Parent")
        child = parent.add_subtopic("Target")
        parent.add_subtopic("Other")
        
        found = parent.find_subtopic("Target")
        
        assert found == child
    
    def test_find_subtopic_not_found(self):
        """Test finding a nonexistent subtopic."""
        parent = Topic(title="Parent")
        parent.add_subtopic("Child")
        
        found = parent.find_subtopic("Nonexistent")
        
        assert found is None
    
    def test_find_subtopic_recursive(self, topic_with_children):
        """Test recursive subtopic search."""
        found = topic_with_children.find_subtopic_recursive("Grandchild")
        
        assert found is not None
        assert found.title == "Grandchild"
    
    def test_walk_topics(self, topic_with_children):
        """Test walking through all topics."""
        topics = list(topic_with_children.walk())
        
        assert len(topics) == 4  # Root + 2 children + 1 grandchild
        titles = [t.title for t in topics]
        assert "Root" in titles
        assert "Child 1" in titles
        assert "Child 2" in titles
        assert "Grandchild" in titles


class TestTopicAttributes:
    """Tests for topic attributes."""
    
    def test_notes(self):
        """Test setting and getting notes."""
        topic = Topic()
        topic.notes = "Some notes"
        
        assert topic.notes == "Some notes"
    
    def test_add_label(self):
        """Test adding a label."""
        topic = Topic()
        topic.add_label("important")
        
        assert "important" in topic.labels
    
    def test_add_duplicate_label(self):
        """Test adding a duplicate label."""
        topic = Topic()
        topic.add_label("important")
        topic.add_label("important")
        
        assert topic.labels.count("important") == 1
    
    def test_remove_label(self):
        """Test removing a label."""
        topic = Topic()
        topic.add_label("important")
        result = topic.remove_label("important")
        
        assert result is True
        assert "important" not in topic.labels
    
    def test_remove_nonexistent_label(self):
        """Test removing a nonexistent label."""
        topic = Topic()
        result = topic.remove_label("nonexistent")
        
        assert result is False
    
    def test_add_marker(self):
        """Test adding a marker."""
        topic = Topic()
        topic.add_marker("priority-1")
        
        assert "priority-1" in topic.markers
    
    def test_remove_marker(self):
        """Test removing a marker."""
        topic = Topic()
        topic.add_marker("priority-1")
        result = topic.remove_marker("priority-1")
        
        assert result is True
        assert "priority-1" not in topic.markers


class TestTopicSerialization:
    """Tests for topic serialization."""
    
    def test_to_dict_basic(self):
        """Test basic topic to dict conversion."""
        topic = Topic(title="Test", id="test123")
        data = topic.to_dict()
        
        assert data["id"] == "test123"
        assert data["title"] == "Test"
    
    def test_to_dict_with_children(self):
        """Test topic with children to dict conversion."""
        parent = Topic(title="Parent")
        parent.add_subtopic("Child")
        data = parent.to_dict()
        
        assert "children" in data
        assert "attached" in data["children"]
        assert len(data["children"]["attached"]) == 1
        assert data["children"]["attached"][0]["title"] == "Child"
    
    def test_to_dict_with_notes(self):
        """Test topic with notes to dict conversion."""
        topic = Topic(title="Test")
        topic.notes = "Some notes"
        data = topic.to_dict()
        
        assert data["notes"] == "Some notes"
    
    def test_from_dict_basic(self):
        """Test basic dict to topic conversion."""
        data = {"id": "test123", "title": "Test"}
        topic = Topic.from_dict(data)
        
        assert topic.id == "test123"
        assert topic.title == "Test"
    
    def test_from_dict_with_children(self):
        """Test dict with children to topic conversion."""
        data = {
            "id": "parent",
            "title": "Parent",
            "children": [
                {"id": "child", "title": "Child"}
            ]
        }
        topic = Topic.from_dict(data)
        
        assert len(topic.subtopics) == 1
        assert topic.subtopics[0].title == "Child"
        assert topic.subtopics[0].parent == topic
    
    def test_round_trip_serialization(self):
        """Test round-trip serialization."""
        original = Topic(title="Root")
        original.notes = "Notes"
        original.add_label("label1")
        child = original.add_subtopic("Child")
        child.add_marker("marker1")
        
        data = original.to_dict()
        restored = Topic.from_dict(data)
        
        assert restored.title == original.title
        assert restored.notes == original.notes
        assert restored.labels == original.labels
        assert len(restored.subtopics) == 1
        assert restored.subtopics[0].title == "Child"


class TestTopicEquality:
    """Tests for topic equality."""
    
    def test_same_id_equal(self):
        """Test topics with same ID are equal."""
        topic1 = Topic(title="A", id="same")
        topic2 = Topic(title="B", id="same")
        
        assert topic1 == topic2
    
    def test_different_id_not_equal(self):
        """Test topics with different IDs are not equal."""
        topic1 = Topic(title="A", id="id1")
        topic2 = Topic(title="A", id="id2")
        
        assert topic1 != topic2
    
    def test_not_equal_to_non_topic(self):
        """Test topic is not equal to non-topic."""
        topic = Topic()
        
        assert topic != "not a topic"
        assert topic != 123
