"""
Tests for Issue #6: Generate a Markdown Stub from a Schema.

This module tests the functionality to create markdown template files
from JSON schemas with appropriate placeholder content and structure.
"""

import json
import pytest
from pathlib import Path
from tempfile import NamedTemporaryFile, TemporaryDirectory

from markitect.stub_generator import StubGenerator
from markitect.schema_generator import SchemaGenerator


class TestIssue6StubGeneration:
    """Test suite for markdown stub generation from schemas."""

    @pytest.fixture
    def sample_schema(self):
        """Sample JSON schema for testing."""
        return {
            "$schema": "http://json-schema.org/draft-07/schema#",
            "type": "object",
            "title": "Blog Post Schema",
            "description": "Schema for blog post structure",
            "properties": {
                "headings": {
                    "type": "object",
                    "properties": {
                        "level_1": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "content": {"type": "string"},
                                    "level": {"type": "integer"}
                                }
                            },
                            "minItems": 1,
                            "maxItems": 1
                        },
                        "level_2": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "content": {"type": "string"},
                                    "level": {"type": "integer"}
                                }
                            },
                            "minItems": 3,
                            "maxItems": 3
                        }
                    }
                }
            }
        }

    @pytest.fixture
    def stub_generator(self):
        """Create a StubGenerator instance."""
        return StubGenerator()

    def test_stub_generator_can_be_created(self, stub_generator):
        """StubGenerator class should be importable and instantiable."""
        assert stub_generator is not None
        assert isinstance(stub_generator, StubGenerator)

    def test_generate_stub_from_schema_dict(self, stub_generator, sample_schema):
        """Should generate markdown stub from schema dictionary."""
        result = stub_generator.generate_stub_from_schema(sample_schema)

        assert result is not None
        assert isinstance(result, str)

        # Should contain appropriate heading structure
        lines = result.strip().split('\n')
        assert any(line.startswith('# ') for line in lines)  # H1 heading
        assert any(line.startswith('## ') for line in lines)  # H2 headings

        # Should have placeholder content
        assert 'TODO' in result or 'placeholder' in result.lower()

    def test_generate_stub_creates_proper_heading_hierarchy(self, stub_generator, sample_schema):
        """Generated stub should have correct heading levels and count."""
        result = stub_generator.generate_stub_from_schema(sample_schema)
        lines = result.strip().split('\n')

        h1_count = len([line for line in lines if line.startswith('# ') and not line.startswith('## ')])
        h2_count = len([line for line in lines if line.startswith('## ')])

        # Based on schema: 1 H1, 3 H2
        assert h1_count == 1
        assert h2_count == 3

    def test_generate_stub_from_file_path(self, stub_generator, sample_schema):
        """Should generate stub from schema file path."""
        with NamedTemporaryFile(mode='w', suffix='.json', delete=False) as temp_file:
            json.dump(sample_schema, temp_file)
            temp_file.flush()

            try:
                result = stub_generator.generate_stub_from_file(Path(temp_file.name))
                assert result is not None
                assert isinstance(result, str)
                assert '# ' in result  # Should contain headings
            finally:
                Path(temp_file.name).unlink()

    def test_generate_stub_with_output_file(self, stub_generator, sample_schema):
        """Should save generated stub to output file."""
        with TemporaryDirectory() as temp_dir:
            output_file = Path(temp_dir) / "generated_stub.md"

            stub_generator.generate_stub_to_file(sample_schema, output_file)

            assert output_file.exists()
            content = output_file.read_text()
            assert '# ' in content
            assert len(content.strip()) > 0

    def test_generate_stub_with_custom_placeholders(self, stub_generator):
        """Should support custom placeholder text generation."""
        schema = {
            "$schema": "http://json-schema.org/draft-07/schema#",
            "type": "object",
            "title": "Custom Schema",
            "properties": {
                "headings": {
                    "type": "object",
                    "properties": {
                        "level_1": {
                            "type": "array",
                            "minItems": 1,
                            "maxItems": 1
                        }
                    }
                }
            }
        }

        result = stub_generator.generate_stub_from_schema(schema, placeholder_style="custom")
        assert result is not None
        # Should contain some form of placeholder content
        assert any(keyword in result.lower() for keyword in ['todo', 'placeholder', 'content', 'section'])

    def test_generate_stub_handles_empty_schema(self, stub_generator):
        """Should handle empty or minimal schemas gracefully."""
        empty_schema = {
            "$schema": "http://json-schema.org/draft-07/schema#",
            "type": "object"
        }

        result = stub_generator.generate_stub_from_schema(empty_schema)
        assert result is not None
        assert isinstance(result, str)
        # Should at least create a basic document structure

    def test_generate_stub_handles_complex_hierarchy(self, stub_generator):
        """Should handle complex heading hierarchies correctly."""
        complex_schema = {
            "$schema": "http://json-schema.org/draft-07/schema#",
            "type": "object",
            "properties": {
                "headings": {
                    "type": "object",
                    "properties": {
                        "level_1": {"type": "array", "minItems": 1, "maxItems": 1},
                        "level_2": {"type": "array", "minItems": 2, "maxItems": 2},
                        "level_3": {"type": "array", "minItems": 4, "maxItems": 4},
                        "level_4": {"type": "array", "minItems": 1, "maxItems": 1}
                    }
                }
            }
        }

        result = stub_generator.generate_stub_from_schema(complex_schema)
        lines = result.strip().split('\n')

        h1_count = len([l for l in lines if l.startswith('# ') and not l.startswith('## ')])
        h2_count = len([l for l in lines if l.startswith('## ') and not l.startswith('### ')])
        h3_count = len([l for l in lines if l.startswith('### ') and not l.startswith('#### ')])
        h4_count = len([l for l in lines if l.startswith('#### ') and not l.startswith('##### ')])

        assert h1_count == 1
        assert h2_count == 2
        assert h3_count == 4
        assert h4_count == 1

    def test_round_trip_validation(self, stub_generator):
        """Generated stub should validate against original schema."""
        # First create a schema from a sample document
        schema_generator = SchemaGenerator()
        sample_doc = Path("sample_blog.md")  # Using existing sample

        if sample_doc.exists():
            schema = schema_generator.generate_schema_from_file(sample_doc)
            stub = stub_generator.generate_stub_from_schema(schema)

            # Create temporary file with generated stub
            with NamedTemporaryFile(mode='w', suffix='.md', delete=False) as temp_file:
                temp_file.write(stub)
                temp_file.flush()

                try:
                    # Generate schema from the stub and compare basic structure
                    stub_schema = schema_generator.generate_schema_from_file(Path(temp_file.name))

                    # Should have similar heading structure
                    original_headings = schema.get('properties', {}).get('headings', {}).get('properties', {})
                    stub_headings = stub_schema.get('properties', {}).get('headings', {}).get('properties', {})

                    # Should have same heading levels
                    assert set(original_headings.keys()) == set(stub_headings.keys())

                finally:
                    Path(temp_file.name).unlink()


class TestStubGeneratorErrorHandling:
    """Test error handling for stub generation."""

    def test_handles_invalid_schema_file(self):
        """Should handle invalid schema file gracefully."""
        generator = StubGenerator()

        with pytest.raises(FileNotFoundError):
            generator.generate_stub_from_file(Path("nonexistent_schema.json"))

    def test_handles_invalid_json_schema(self):
        """Should handle malformed JSON schema files."""
        generator = StubGenerator()

        with NamedTemporaryFile(mode='w', suffix='.json', delete=False) as temp_file:
            temp_file.write("invalid json content")
            temp_file.flush()

            try:
                with pytest.raises(json.JSONDecodeError):
                    generator.generate_stub_from_file(Path(temp_file.name))
            finally:
                Path(temp_file.name).unlink()

    def test_handles_schema_without_headings(self):
        """Should handle schemas that don't define heading structure."""
        generator = StubGenerator()
        schema = {
            "$schema": "http://json-schema.org/draft-07/schema#",
            "type": "object",
            "properties": {
                "other_stuff": {"type": "string"}
            }
        }

        result = generator.generate_stub_from_schema(schema)
        assert result is not None
        assert isinstance(result, str)
        # Should create a minimal document even without heading structure