"""
Test directory structure creation functionality for Issue #138: Explode Markdown file to markdown directory.

This test module covers the creation of filesystem directory structures that match
the hierarchical organization of markdown documents.
"""

import pytest
import tempfile
import shutil
from pathlib import Path
from unittest.mock import Mock, patch

# Import will fail initially (RED phase) until implementation exists
try:
    from markitect.plugins.builtin.markdown_commands import (
        create_directory_structure,
        explode_markdown_file,
        DirectoryStructureBuilder,
        MarkdownSection
    )
except ImportError:
    # Expected during RED phase - tests should fail initially
    create_directory_structure = None
    explode_markdown_file = None
    DirectoryStructureBuilder = None
    MarkdownSection = None


class TestDirectoryStructureCreation:
    """Test creation of directory structures from markdown hierarchy."""

    def setup_method(self):
        """Set up temporary directory for each test."""
        self.temp_dir = Path(tempfile.mkdtemp())

    def teardown_method(self):
        """Clean up temporary directory after each test."""
        if self.temp_dir.exists():
            shutil.rmtree(self.temp_dir)

    def test_create_simple_directory_structure(self):
        """Test creating a simple directory structure from markdown sections."""
        # This should fail initially (RED phase)

        # Mock sections representing a simple book structure
        sections = [
            Mock(level=1, title="Part 1: Introduction", children=[
                Mock(level=2, title="Chapter 1: Getting Started", children=[],
                     content="Content for chapter 1"),
                Mock(level=2, title="Chapter 2: Basics", children=[],
                     content="Content for chapter 2")
            ], content="Introduction content"),
        ]

        result = create_directory_structure(sections, self.temp_dir)

        # Verify directory structure
        part_dir = self.temp_dir / "part_1_introduction"
        assert part_dir.exists()
        assert part_dir.is_dir()

        chapter1_file = part_dir / "chapter_1_getting_started.md"
        chapter2_file = part_dir / "chapter_2_basics.md"

        assert chapter1_file.exists()
        assert chapter2_file.exists()

        # Verify content was written
        assert "Content for chapter 1" in chapter1_file.read_text()
        assert "Content for chapter 2" in chapter2_file.read_text()

    def test_create_nested_directory_structure(self):
        """Test creating deeply nested directory structures."""
        # This should fail initially (RED phase)

        sections = [
            Mock(level=1, title="Part 1", children=[
                Mock(level=2, title="Chapter 1", children=[
                    Mock(level=3, title="Section 1.1", children=[
                        Mock(level=4, title="Subsection 1.1.1", children=[],
                             content="Deep content")
                    ], content="Section content")
                ], content="Chapter content")
            ], content="Part content")
        ]

        result = create_directory_structure(sections, self.temp_dir)

        # Verify nested structure
        deep_path = (self.temp_dir / "part_1" / "chapter_1" / "section_1_1" /
                     "subsection_1_1_1.md")

        # Note: Exact structure depends on implementation decisions
        # This test defines expected behavior
        assert any(path.name == "subsection_1_1_1.md" for path in self.temp_dir.rglob("*.md"))

    def test_create_structure_with_duplicate_names(self):
        """Test handling duplicate heading names in directory structure."""
        # This should fail initially (RED phase)

        sections = [
            Mock(level=1, title="Introduction", children=[], content="First intro"),
            Mock(level=1, title="Introduction", children=[], content="Second intro")
        ]

        result = create_directory_structure(sections, self.temp_dir)

        # Should create unique directories/files
        intro1_path = self.temp_dir / "introduction"
        intro2_path = self.temp_dir / "introduction_2"

        # One of these patterns should exist
        assert (intro1_path.exists() or
                (self.temp_dir / "introduction.md").exists() or
                (self.temp_dir / "introduction_2.md").exists())

    def test_create_structure_handles_existing_directories(self):
        """Test behavior when target directories already exist."""
        # This should fail initially (RED phase)

        # Pre-create a directory
        existing_dir = self.temp_dir / "chapter_1"
        existing_dir.mkdir()

        sections = [
            Mock(level=1, title="Chapter 1", children=[], content="New content")
        ]

        # Should handle existing directory gracefully
        result = create_directory_structure(sections, self.temp_dir)

        # Should either merge, skip, or create alternative name
        assert result is not None  # Function should complete without error

    def test_create_structure_with_special_characters(self):
        """Test directory creation with headings containing special characters."""
        # This should fail initially (RED phase)

        sections = [
            Mock(level=1, title="Chapter 1: What's New?", children=[],
                 content="Content with special chars"),
            Mock(level=1, title="File/Path Issues", children=[],
                 content="Path content")
        ]

        result = create_directory_structure(sections, self.temp_dir)

        # Verify safe directory names were created
        safe_names = [path.name for path in self.temp_dir.iterdir()]

        # Should contain sanitized versions
        assert any("whats_new" in name.lower() for name in safe_names)
        assert any("file_path" in name.lower() for name in safe_names)

    def test_create_structure_preserves_markdown_formatting(self):
        """Test that markdown formatting is preserved in extracted files."""
        # This should fail initially (RED phase)

        markdown_content = """## Chapter Title

This content has **bold** and *italic* text.

```python
def example():
    return "code block"
```

- List item 1
- List item 2
"""

        sections = [
            Mock(level=1, title="Test Chapter", children=[], content=markdown_content)
        ]

        result = create_directory_structure(sections, self.temp_dir)

        # Find the created file
        md_files = list(self.temp_dir.rglob("*.md"))
        assert len(md_files) > 0

        content = md_files[0].read_text()

        # Verify markdown formatting is preserved
        assert "**bold**" in content
        assert "*italic*" in content
        assert "```python" in content
        assert "- List item 1" in content


class TestDirectoryStructureBuilder:
    """Test the DirectoryStructureBuilder class."""

    def setup_method(self):
        """Set up temporary directory for each test."""
        self.temp_dir = Path(tempfile.mkdtemp())

    def teardown_method(self):
        """Clean up temporary directory after each test."""
        if self.temp_dir.exists():
            shutil.rmtree(self.temp_dir)

    def test_builder_initialization(self):
        """Test DirectoryStructureBuilder initialization."""
        # This should fail initially (RED phase)

        builder = DirectoryStructureBuilder(
            output_dir=self.temp_dir,
            max_depth=3,
            file_extension=".md"
        )

        assert builder.output_dir == self.temp_dir
        assert builder.max_depth == 3
        assert builder.file_extension == ".md"

    def test_builder_depth_limiting(self):
        """Test that builder respects maximum depth settings."""
        # This should fail initially (RED phase)

        builder = DirectoryStructureBuilder(
            output_dir=self.temp_dir,
            max_depth=2
        )

        # Create deep structure that exceeds max depth
        sections = [
            Mock(level=1, title="Level 1", children=[
                Mock(level=2, title="Level 2", children=[
                    Mock(level=3, title="Level 3", children=[
                        Mock(level=4, title="Level 4", children=[], content="Deep content")
                    ], content="L3 content")
                ], content="L2 content")
            ], content="L1 content")
        ]

        result = builder.build(sections)

        # Should flatten or handle deep structures appropriately
        # Exact behavior depends on implementation
        assert result is not None


class TestMarkdownExplosion:
    """Test the complete markdown file explosion process."""

    def setup_method(self):
        """Set up temporary directory for each test."""
        self.temp_dir = Path(tempfile.mkdtemp())

    def teardown_method(self):
        """Clean up temporary directory after each test."""
        if self.temp_dir.exists():
            shutil.rmtree(self.temp_dir)

    def test_explode_simple_markdown_file(self):
        """Test complete explosion of a simple markdown file."""
        # This should fail initially (RED phase)

        markdown_content = """# Part 1: Introduction
This is the introduction to our document.

## Chapter 1: Getting Started
Here's how to get started.

### Section 1.1: Installation
Installation instructions.

## Chapter 2: Advanced Usage
Advanced topics.
"""

        # Create input file
        input_file = self.temp_dir / "input.md"
        input_file.write_text(markdown_content)

        # Create output directory
        output_dir = self.temp_dir / "exploded"

        # Explode the file
        result = explode_markdown_file(input_file, output_dir)

        # Verify structure was created
        assert output_dir.exists()
        assert len(list(output_dir.rglob("*.md"))) > 0

        # Verify content distribution
        md_files = list(output_dir.rglob("*.md"))
        all_content = ""
        for md_file in md_files:
            all_content += md_file.read_text()

        # Original content should be distributed across files
        assert "This is the introduction" in all_content
        assert "Here's how to get started" in all_content
        assert "Installation instructions" in all_content

    def test_explode_file_with_front_matter(self):
        """Test explosion of file with YAML front matter."""
        # This should fail initially (RED phase)

        markdown_content = """---
title: "My Document"
author: "Test Author"
---

# Chapter 1
Content here.
"""

        input_file = self.temp_dir / "input.md"
        input_file.write_text(markdown_content)

        output_dir = self.temp_dir / "exploded"

        result = explode_markdown_file(input_file, output_dir)

        # Front matter should be handled appropriately
        # (preserved in root, copied to sections, or handled per implementation)
        assert result is not None

    def test_explode_file_error_handling(self):
        """Test error handling for invalid inputs."""
        # This should fail initially (RED phase)

        # Non-existent input file
        with pytest.raises(FileNotFoundError):
            explode_markdown_file(Path("nonexistent.md"), self.temp_dir)

        # Invalid output directory
        with pytest.raises((PermissionError, OSError)):
            explode_markdown_file(Path("test.md"), Path("/invalid/path"))