"""
Unit tests for export module.
"""

import unittest
import sys
from pathlib import Path

# Add src to path
sys.path.insert(0, str(Path(__file__).parent.parent / 'src'))

from bmd.parser import BlockMDParser
from bmd.export import TreeView, TableView, ListView, BMDExporter, export_to_bmd


class TestTreeView(unittest.TestCase):
    """Test TreeView formatting."""
    
    def setUp(self):
        """Set up test fixtures."""
        self.parser = BlockMDParser()
        self.sample_bmd = """# Root
`type`: project

Content for root block.

## Child 1
`status`: active

Child 1 content.

### Grandchild
`status`: done

Nested content.

## Child 2
`status`: pending

Child 2 content.
"""
        self.blocks = self.parser.parse(self.sample_bmd)
    
    def test_tree_view_basic(self):
        """Test basic tree view rendering."""
        view = TreeView()
        # Flatten all blocks for tree view
        all_blocks = self._flatten_blocks(self.blocks)
        result = view.render(all_blocks)
        
        # Check that it contains tree structure symbols
        self.assertIn('└──', result)
        self.assertIn('Root', result)
        self.assertIn('Child 1', result)
        self.assertIn('Child 2', result)
        self.assertIn('Grandchild', result)
    
    def test_tree_view_properties(self):
        """Test tree view includes properties."""
        view = TreeView()
        all_blocks = self._flatten_blocks(self.blocks)
        result = view.render(all_blocks)
        
        # Properties should be shown in brackets
        self.assertIn('[type=project]', result)
        self.assertIn('status=active', result)
        self.assertIn('status=done', result)
    
    def test_tree_view_filtered_blocks(self):
        """Test tree view with filtered block list."""
        view = TreeView()
        # Only get blocks with status property
        filtered = [b for b in self._flatten_blocks(self.blocks) if b.has_property('status')]
        result = view.render(filtered)
        
        # Should contain filtered blocks
        self.assertIn('Child 1', result)
        self.assertIn('Grandchild', result)
        self.assertIn('Child 2', result)
    
    def _flatten_blocks(self, blocks):
        """Helper to flatten block hierarchy."""
        result = []
        for block in blocks:
            result.append(block)
            result.extend(self._flatten_blocks(block.children))
        return result


class TestTableView(unittest.TestCase):
    """Test TableView formatting."""
    
    def setUp(self):
        """Set up test fixtures."""
        self.parser = BlockMDParser()
        self.sample_bmd = """# Task 1
`status`: done
`priority`: high

Task 1 description.

# Task 2
`status`: in-progress
`priority`: medium

Task 2 description.

# Task 3
`status`: todo
`priority`: low

Task 3 description.
"""
        self.blocks = self.parser.parse(self.sample_bmd)
    
    def test_table_view_basic(self):
        """Test basic table rendering."""
        view = TableView(['title', 'status', 'priority'])
        result = view.render(self.blocks)
        
        # Check table structure
        self.assertIn('title', result)
        self.assertIn('status', result)
        self.assertIn('priority', result)
        self.assertIn('|', result)  # Column separator
        self.assertIn('-+-', result)  # Header separator
    
    def test_table_view_content(self):
        """Test table contains correct data."""
        view = TableView(['title', 'status'])
        result = view.render(self.blocks)
        
        self.assertIn('Task 1', result)
        self.assertIn('Task 2', result)
        self.assertIn('Task 3', result)
        self.assertIn('done', result)
        self.assertIn('in-progress', result)
        self.assertIn('todo', result)
    
    def test_table_view_empty(self):
        """Test table with no blocks."""
        view = TableView(['title', 'status'])
        result = view.render([])
        
        self.assertEqual(result, "No results")
    
    def test_table_view_level_field(self):
        """Test table with level field."""
        view = TableView(['title', 'level'])
        result = view.render(self.blocks)
        
        self.assertIn('level', result)
        self.assertIn('1', result)  # Level 1 blocks


class TestListView(unittest.TestCase):
    """Test ListView formatting."""
    
    def setUp(self):
        """Set up test fixtures."""
        self.parser = BlockMDParser()
        self.sample_bmd = """# Item 1
`type`: feature
`status`: active

# Item 2
`type`: bug
`status`: fixed

# Item 3
`type`: feature
`status`: pending
"""
        self.blocks = self.parser.parse(self.sample_bmd)
    
    def test_list_view_default(self):
        """Test list view with default format."""
        view = ListView()
        result = view.render(self.blocks)
        
        # Should have numbered list
        self.assertIn('1.', result)
        self.assertIn('2.', result)
        self.assertIn('3.', result)
        self.assertIn('Item 1', result)
        self.assertIn('level 1', result)
    
    def test_list_view_with_fields(self):
        """Test list view with custom fields."""
        view = ListView(['title', 'type', 'status'])
        result = view.render(self.blocks)
        
        self.assertIn('Item 1', result)
        self.assertIn('type=feature', result)
        self.assertIn('status=active', result)
        self.assertIn('type=bug', result)
        self.assertIn('status=fixed', result)
    
    def test_list_view_empty(self):
        """Test list view with no blocks."""
        view = ListView()
        result = view.render([])
        
        self.assertEqual(result, "No results")


class TestBMDExporter(unittest.TestCase):
    """Test BMD format export."""
    
    def setUp(self):
        """Set up test fixtures."""
        self.parser = BlockMDParser()
        self.sample_bmd = """# Project
`type`: project
`version`: 1.0

Project description.

## Module A
`status`: active

Module A content.

### Feature 1
`priority`: high

Feature 1 details.

## Module B
`status`: pending

Module B content.
"""
        self.blocks = self.parser.parse(self.sample_bmd)
    
    def test_export_basic(self):
        """Test basic BMD export."""
        exporter = BMDExporter()
        result = exporter.export(self.blocks)
        
        # Check headers are present
        self.assertIn('# Project', result)
        self.assertIn('## Module A', result)
        self.assertIn('### Feature 1', result)
        self.assertIn('## Module B', result)
    
    def test_export_properties(self):
        """Test properties are exported."""
        exporter = BMDExporter()
        result = exporter.export(self.blocks)
        
        # Properties should be in backtick format on separate lines
        self.assertIn('`type`: project', result)
        self.assertIn('`version`: 1.0', result)
        self.assertIn('`status`: active', result)
        self.assertIn('`priority`: high', result)
    
    def test_export_content(self):
        """Test content is exported."""
        exporter = BMDExporter()
        result = exporter.export(self.blocks)
        
        self.assertIn('Project description.', result)
        self.assertIn('Module A content.', result)
        self.assertIn('Feature 1 details.', result)
    
    def test_export_round_trip(self):
        """Test parsing exported BMD produces same structure."""
        exporter = BMDExporter()
        exported = exporter.export(self.blocks)
        
        # Parse the exported content
        reparsed = self.parser.parse(exported)
        
        # Should have same number of root blocks
        self.assertEqual(len(self.blocks), len(reparsed))
        
        # Check first block
        self.assertEqual(self.blocks[0].title, reparsed[0].title)
        self.assertEqual(self.blocks[0].level, reparsed[0].level)
        self.assertEqual(len(self.blocks[0].children), len(reparsed[0].children))
    
    def test_export_filtered_blocks(self):
        """Test exporting filtered subset of blocks."""
        exporter = BMDExporter()
        
        # Get only blocks with status property
        all_blocks = self._flatten_blocks(self.blocks)
        filtered = [b for b in all_blocks if b.has_property('status')]
        
        result = exporter.export(filtered)
        
        # Should contain filtered blocks
        self.assertIn('Module A', result)
        self.assertIn('Module B', result)
    
    def test_export_to_file(self, tmp_path=None):
        """Test exporting to file."""
        import tempfile
        
        with tempfile.NamedTemporaryFile(mode='w', suffix='.bmd', delete=False) as f:
            temp_path = f.name
        
        try:
            exporter = BMDExporter()
            exporter.export_to_file(self.blocks, temp_path)
            
            # Read back the file
            content = Path(temp_path).read_text()
            
            # Verify content
            self.assertIn('# Project', content)
            self.assertIn('## Module A', content)
        finally:
            Path(temp_path).unlink()
    
    def _flatten_blocks(self, blocks):
        """Helper to flatten block hierarchy."""
        result = []
        for block in blocks:
            result.append(block)
            result.extend(self._flatten_blocks(block.children))
        return result


class TestExportConvenienceFunctions(unittest.TestCase):
    """Test convenience functions."""
    
    def setUp(self):
        """Set up test fixtures."""
        self.parser = BlockMDParser()
        self.sample_bmd = """# Simple
`status`: test

Content here.
"""
        self.blocks = self.parser.parse(self.sample_bmd)
    
    def test_export_to_bmd_string(self):
        """Test export_to_bmd returns string."""
        result = export_to_bmd(self.blocks)
        
        self.assertIsInstance(result, str)
        self.assertIn('# Simple', result)
        self.assertIn('`status`: test', result)
    
    def test_export_to_bmd_file(self):
        """Test export_to_bmd with file path."""
        import tempfile
        
        with tempfile.NamedTemporaryFile(mode='w', suffix='.bmd', delete=False) as f:
            temp_path = f.name
        
        try:
            result = export_to_bmd(self.blocks, temp_path)
            
            # Should still return string
            self.assertIsInstance(result, str)
            
            # File should exist and contain content
            self.assertTrue(Path(temp_path).exists())
            content = Path(temp_path).read_text()
            self.assertIn('# Simple', content)
        finally:
            Path(temp_path).unlink()


if __name__ == '__main__':
    unittest.main()
