"""Tests for parsing and round-trip conversion."""

import pytest
import pywasot


class TestParsing:
    """Test parsing Wasot content."""

    def test_parse_simple_block(self):
        """Test parsing a simple block."""
        wasot = ".note\nThis is a note"
        result = pywasot.loads(wasot)

        assert isinstance(result, dict)
        assert result['name'] == "note"
        assert "This is a note" in result['text']

    def test_parse_block_with_attributes(self):
        """Test parsing block with attributes."""
        wasot = '.note importance="high" author=Alice\nImportant note'
        result = pywasot.loads(wasot)

        assert result['name'] == "note"
        # Note: kwargs parsing depends on the parser
        assert "Important note" in result['text']

    def test_parse_nested_blocks(self):
        """Test parsing nested blocks."""
        wasot = """.section
..note
This is nested
../
./"""
        result = pywasot.loads(wasot)

        assert result['name'] == "section"
        assert len(result['children']) > 0

        # Find the nested note
        note = None
        for child in result['children']:
            if child.get('name') == 'note':
                note = child
                break

        assert note is not None
        assert "This is nested" in note['text']

    def test_parse_multiple_blocks(self):
        """Test parsing multiple top-level blocks."""
        wasot = """.note
Note 1
./
.idea
Idea 1
./"""
        doc = pywasot.loads(wasot)

        assert doc['name'] == 'document'
        assert len(doc['children']) == 2
        assert doc['children'][0]['name'] == "note"
        assert doc['children'][1]['name'] == "idea"


class TestRoundTrip:
    """Test round-trip conversion (dict -> Wasot -> dict)."""

    def test_simple_roundtrip(self):
        """Test round-trip for simple document."""
        doc1 = {
            'name': 'note',
            'args': [],
            'kwargs': {},
            'text': 'Hello world',
            'children': []
        }

        # Convert to Wasot
        wasot = pywasot.dumps(doc1)

        # Parse back
        result = pywasot.loads(wasot)

        assert result['name'] == "note"
        assert "Hello world" in result['text']

    def test_attributes_roundtrip(self):
        """Test that attributes survive round-trip."""
        doc1 = {
            'name': 'note',
            'args': [],
            'kwargs': {'importance': 'high', 'id': 'n1'},
            'text': 'Test note',
            'children': []
        }

        wasot = pywasot.dumps(doc1)
        result = pywasot.loads(wasot)

        assert result['name'] == "note"
        # Note: roundtrip may affect kwargs parsing

    def test_nested_roundtrip(self):
        """Test round-trip for nested structures."""
        doc1 = {
            'name': 'section',
            'args': [],
            'kwargs': {'title': 'Main'},
            'text': '',
            'children': [{
                'name': 'subsection',
                'args': [],
                'kwargs': {},
                'text': '',
                'children': [{
                    'name': 'note',
                    'args': [],
                    'kwargs': {},
                    'text': 'Deep content',
                    'children': []
                }]
            }]
        }

        wasot = pywasot.dumps(doc1)
        result = pywasot.loads(wasot)

        assert result['name'] == "section"
        assert len(result['children']) > 0

    def test_multiline_text_roundtrip(self):
        """Test that multi-line text is preserved."""
        doc1 = {
            'name': 'note',
            'args': [],
            'kwargs': {},
            'text': 'Line 1\nLine 2\nLine 3',
            'children': []
        }

        wasot = pywasot.dumps(doc1)
        result = pywasot.loads(wasot)

        assert "Line 1" in result['text']
        assert "Line 2" in result['text']
        assert "Line 3" in result['text']


class TestEdgeCases:
    """Test edge cases in parsing."""

    def test_empty_document(self):
        """Test parsing empty content."""
        doc = pywasot.loads("")
        assert isinstance(doc, dict)
        assert doc['name'] == 'document'
        assert len(doc['children']) == 0

    def test_text_only(self):
        """Test parsing text without blocks."""
        wasot = "Just some text\nwithout any blocks"
        doc = pywasot.loads(wasot)

        assert isinstance(doc, dict)
        assert doc['name'] == 'document'
        assert "Just some text" in doc['text']
        assert "without any blocks" in doc['text']

    def test_block_without_content(self):
        """Test parsing block with no content."""
        wasot = ".note\n./"
        result = pywasot.loads(wasot)

        assert result['name'] == "note"
        assert result['text'] == ""

    def test_complex_nesting(self):
        """Test deeply nested structures."""
        wasot = """.level1
..level2
...level3
....level4
Text at level 4
..../
.../
../
./"""
        result = pywasot.loads(wasot)

        assert result['name'] == "level1"

        # Find deep text
        def find_text(node):
            if node.get('text'):
                return node['text']
            for child in node.get('children', []):
                text = find_text(child)
                if text:
                    return text
            return ''

        assert "Text at level 4" in find_text(result)


class TestErrorHandling:
    """Test handling of malformed input."""

    def test_unclosed_block(self):
        """Test handling of unclosed blocks."""
        wasot = ".note\nThis block is not closed"
        # Should not crash
        result = pywasot.loads(wasot)
        assert isinstance(result, dict)

    def test_mismatched_closing(self):
        """Test handling of mismatched closing tags."""
        wasot = ".note\n../\n./"  # Wrong nesting
        # Should handle gracefully
        result = pywasot.loads(wasot)
        assert isinstance(result, dict)

    def test_invalid_attributes(self):
        """Test handling of malformed attributes."""
        wasot = '.note importance="high\nBroken quote'
        # Should handle gracefully
        result = pywasot.loads(wasot)
        assert isinstance(result, dict)
