import pytest

from pipelex.core.concepts.concept_structure_blueprint import ConceptStructureBlueprint, ConceptStructureBlueprintFieldType
from pipelex.core.concepts.helpers import normalize_structure_blueprint
from pipelex.core.concepts.structure_generation.exceptions import ConceptStructureValidationError
from pipelex.core.concepts.structure_generation.generator import StructureGenerator
from pipelex.core.stuffs.structured_content import StructuredContent


class TestStructureGenerator:
    def test_simple_structure_generation(self):
        """Test generation of a simple structure with basic fields."""
        structure_blueprint = {
            "name": ConceptStructureBlueprint(description="Name field", type=ConceptStructureBlueprintFieldType.TEXT, required=True),
            "age": ConceptStructureBlueprint(description="Age field", type=ConceptStructureBlueprintFieldType.INTEGER, required=False),
            "active": ConceptStructureBlueprint(
                description="Active status",
                type=ConceptStructureBlueprintFieldType.BOOLEAN,
                required=False,
                default_value=True,
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("TestModel", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class TestModel(StructuredContent):
    """Generated TestModel class"""

    name: str = Field(..., description="Name field")
    age: Optional[int] = Field(default=None, description="Age field")
    active: Optional[bool] = Field(default=True, description="Active status")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_complex_types_generation(self):
        """Test generation with complex types like lists and dicts."""
        structure_blueprint = {
            "tags": ConceptStructureBlueprint(
                description="List of tags",
                type=ConceptStructureBlueprintFieldType.LIST,
                item_type="text",
                required=False,
            ),
            "metadata": ConceptStructureBlueprint(
                description="Metadata dictionary",
                type=ConceptStructureBlueprintFieldType.DICT,
                key_type="text",
                value_type="text",
                required=False,
            ),
            "scores": ConceptStructureBlueprint(
                description="List of scores",
                type=ConceptStructureBlueprintFieldType.LIST,
                item_type="number",
                required=True,
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("ComplexModel", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class ComplexModel(StructuredContent):
    """Generated ComplexModel class"""

    tags: Optional[List[str]] = Field(default=None, description="List of tags")
    metadata: Optional[Dict[str, str]] = Field(default=None, description="Metadata dictionary")
    scores: List[float] = Field(..., description="List of scores")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_choices_generation(self):
        """Test generation with inline choices (Literal type)."""
        structure_blueprint = {
            "name": ConceptStructureBlueprint(description="Product name", type=ConceptStructureBlueprintFieldType.TEXT, required=False),
            "category": ConceptStructureBlueprint(
                description="Product category", choices=["electronics", "clothing", "food", "books"], required=True
            ),
            "size": ConceptStructureBlueprint(description="Size of the product", choices=["XS", "S", "M", "L", "XL"], required=False),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("Product", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class Product(StructuredContent):
    """Generated Product class"""

    name: Optional[str] = Field(default=None, description="Product name")
    category: Literal['electronics', 'clothing', 'food', 'books'] = Field(..., description="Product category")
    size: Optional[Literal['XS', 'S', 'M', 'L', 'XL']] = Field(default=None, description="Size of the product")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_typed_choices_generation(self):
        """Test generation with choices paired with explicit integer and number types."""
        structure_blueprint = {
            "status": ConceptStructureBlueprint(
                description="Order status",
                choices=["pending", "processing", "shipped", "delivered"],
                required=True,
            ),
            "story_points": ConceptStructureBlueprint(
                description="Fibonacci story points",
                type=ConceptStructureBlueprintFieldType.INTEGER,
                choices=["1", "3", "5", "8", "13"],
                required=True,
            ),
            "price_tier": ConceptStructureBlueprint(
                description="Price tier multiplier",
                type=ConceptStructureBlueprintFieldType.NUMBER,
                choices=["0.25", "0.5", "1", "2", "5"],
                required=False,
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("Order", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class Order(StructuredContent):
    """Generated Order class"""

    status: Literal['pending', 'processing', 'shipped', 'delivered'] = Field(..., description="Order status")
    story_points: Literal['1', '3', '5', '8', '13'] = Field(..., description="Fibonacci story points")
    price_tier: Optional[Literal['0.25', '0.5', '1', '2', '5']] = Field(default=None, description="Price tier multiplier")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_empty_structure(self):
        """Test generation of structure with no fields."""
        structure_blueprint: dict[str, ConceptStructureBlueprint] = {}

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("EmptyModel", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class EmptyModel(StructuredContent):
    """Generated EmptyModel class"""

'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_concept_get_structure_method(self):
        """Test the get_structure method on Concept class."""
        structure_blueprint = {
            "title": ConceptStructureBlueprint(description="Document title", type=ConceptStructureBlueprintFieldType.TEXT, required=True),
            "page_count": ConceptStructureBlueprint(description="Number of pages", type=ConceptStructureBlueprintFieldType.INTEGER, required=False),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("DocumentInfo", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class DocumentInfo(StructuredContent):
    """Generated DocumentInfo class"""

    title: str = Field(..., description="Document title")
    page_count: Optional[int] = Field(default=None, description="Number of pages")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_generate_from_blueprint_dict_function(self):
        """Test the convenience function for generating from blueprint dict."""
        structure_blueprint = {
            "value": ConceptStructureBlueprint(description="Test value", type=ConceptStructureBlueprintFieldType.TEXT, required=True),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("ConvenienceTest", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class ConvenienceTest(StructuredContent):
    """Generated ConvenienceTest class"""

    value: str = Field(..., description="Test value")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_all_field_types(self):
        """Test that all field types are properly handled."""
        structure_blueprint = {
            "text_field": ConceptStructureBlueprint(description="Text field", type=ConceptStructureBlueprintFieldType.TEXT, required=False),
            "number_field": ConceptStructureBlueprint(description="Number field", type=ConceptStructureBlueprintFieldType.NUMBER, required=False),
            "integer_field": ConceptStructureBlueprint(description="Integer field", type=ConceptStructureBlueprintFieldType.INTEGER, required=False),
            "boolean_field": ConceptStructureBlueprint(description="Boolean field", type=ConceptStructureBlueprintFieldType.BOOLEAN, required=False),
            "list_field": ConceptStructureBlueprint(
                description="List field",
                type=ConceptStructureBlueprintFieldType.LIST,
                item_type="text",
                required=False,
            ),
            "dict_field": ConceptStructureBlueprint(
                description="Dict field",
                type=ConceptStructureBlueprintFieldType.DICT,
                key_type="text",
                value_type="integer",
                required=False,
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("TypeMappingTest", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class TypeMappingTest(StructuredContent):
    """Generated TypeMappingTest class"""

    text_field: Optional[str] = Field(default=None, description="Text field")
    number_field: Optional[float] = Field(default=None, description="Number field")
    integer_field: Optional[int] = Field(default=None, description="Integer field")
    boolean_field: Optional[bool] = Field(default=None, description="Boolean field")
    list_field: Optional[List[str]] = Field(default=None, description="List field")
    dict_field: Optional[Dict[str, int]] = Field(default=None, description="Dict field")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_required_vs_optional_fields(self):
        """Test that fields can be marked as required vs optional."""
        structure_blueprint = {
            "title": ConceptStructureBlueprint(description="Required title", type=ConceptStructureBlueprintFieldType.TEXT, required=True),
            "optional_field": ConceptStructureBlueprint(description="Optional field", type=ConceptStructureBlueprintFieldType.TEXT, required=False),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("RequiredFieldsModel", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class RequiredFieldsModel(StructuredContent):
    """Generated RequiredFieldsModel class"""

    title: str = Field(..., description="Required title")
    optional_field: Optional[str] = Field(default=None, description="Optional field")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_default_values(self):
        """Test fields with default values."""
        structure_blueprint = {
            "name": ConceptStructureBlueprint(
                description="Person name",
                type=ConceptStructureBlueprintFieldType.TEXT,
                required=False,
                default_value="Anonymous",
            ),
            "age": ConceptStructureBlueprint(
                description="Person age",
                type=ConceptStructureBlueprintFieldType.INTEGER,
                required=False,
                default_value=0,
            ),
            "active": ConceptStructureBlueprint(
                description="Is active",
                type=ConceptStructureBlueprintFieldType.BOOLEAN,
                required=False,
                default_value=True,
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("PersonWithDefaults", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class PersonWithDefaults(StructuredContent):
    """Generated PersonWithDefaults class"""

    name: Optional[str] = Field(default="Anonymous", description="Person name")
    age: Optional[int] = Field(default=0, description="Person age")
    active: Optional[bool] = Field(default=True, description="Is active")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_nested_list_types(self):
        """Test nested list types with different item types."""
        structure_blueprint = {
            "text_list": ConceptStructureBlueprint(
                description="List of text items",
                type=ConceptStructureBlueprintFieldType.LIST,
                item_type="text",
                required=False,
            ),
            "number_list": ConceptStructureBlueprint(
                description="List of numbers",
                type=ConceptStructureBlueprintFieldType.LIST,
                item_type="number",
                required=True,
            ),
            "integer_list": ConceptStructureBlueprint(
                description="List of integers",
                type=ConceptStructureBlueprintFieldType.LIST,
                item_type="integer",
                required=False,
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("ListTypesModel", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class ListTypesModel(StructuredContent):
    """Generated ListTypesModel class"""

    text_list: Optional[List[str]] = Field(default=None, description="List of text items")
    number_list: List[float] = Field(..., description="List of numbers")
    integer_list: Optional[List[int]] = Field(default=None, description="List of integers")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_nested_dict_types(self):
        """Test nested dict types with different key/value combinations."""
        structure_blueprint = {
            "string_to_string": ConceptStructureBlueprint(
                description="String to string mapping",
                type=ConceptStructureBlueprintFieldType.DICT,
                key_type="text",
                value_type="text",
                required=False,
            ),
            "string_to_number": ConceptStructureBlueprint(
                description="String to number mapping",
                type=ConceptStructureBlueprintFieldType.DICT,
                key_type="text",
                value_type="number",
                required=True,
            ),
            "string_to_integer": ConceptStructureBlueprint(
                description="String to integer mapping",
                type=ConceptStructureBlueprintFieldType.DICT,
                key_type="text",
                value_type="integer",
                required=False,
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("DictTypesModel", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class DictTypesModel(StructuredContent):
    """Generated DictTypesModel class"""

    string_to_string: Optional[Dict[str, str]] = Field(default=None, description="String to string mapping")
    string_to_number: Dict[str, float] = Field(..., description="String to number mapping")
    string_to_integer: Optional[Dict[str, int]] = Field(default=None, description="String to integer mapping")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_mixed_complexity_structure(self):
        """Test a structure with mixed complexity - simple and complex types together."""
        structure_blueprint = {
            "id": ConceptStructureBlueprint(description="Unique identifier", type=ConceptStructureBlueprintFieldType.INTEGER, required=True),
            "name": ConceptStructureBlueprint(description="Display name", type=ConceptStructureBlueprintFieldType.TEXT, required=True),
            "tags": ConceptStructureBlueprint(
                description="Associated tags",
                type=ConceptStructureBlueprintFieldType.LIST,
                item_type="text",
                required=False,
            ),
            "metadata": ConceptStructureBlueprint(
                description="Additional metadata",
                type=ConceptStructureBlueprintFieldType.DICT,
                key_type="text",
                value_type="text",
                required=False,
            ),
            "active": ConceptStructureBlueprint(
                description="Whether item is active",
                type=ConceptStructureBlueprintFieldType.BOOLEAN,
                required=False,
                default_value=True,
            ),
            "priority": ConceptStructureBlueprint(
                description="Priority level",
                choices=["low", "medium", "high", "urgent"],
                required=False,
                default_value="medium",
            ),
        }

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("ComplexItem", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class ComplexItem(StructuredContent):
    """Generated ComplexItem class"""

    id: int = Field(..., description="Unique identifier")
    name: str = Field(..., description="Display name")
    tags: Optional[List[str]] = Field(default=None, description="Associated tags")
    metadata: Optional[Dict[str, str]] = Field(default=None, description="Additional metadata")
    active: Optional[bool] = Field(default=True, description="Whether item is active")
    priority: Optional[Literal['low', 'medium', 'high', 'urgent']] = Field(default="medium", description="Priority level")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

    def test_mixed_structure_blueprint_normalization(self):
        """Test that mixed structure blueprints (strings and ConceptStructureBlueprint objects) are properly normalized."""
        # Create a mixed structure blueprint similar to what would come from TOML parsing
        mixed_structure_blueprint: dict[str, str | ConceptStructureBlueprint] = {
            "name": "The name of the person",  # Simple string definition
            "age": ConceptStructureBlueprint(description="The age of the person", type=ConceptStructureBlueprintFieldType.NUMBER, required=True),
            "birthdate": ConceptStructureBlueprint(
                description="The birthdate of the person",
                type=ConceptStructureBlueprintFieldType.DATE,
                required=True,
            ),
        }

        normalized_structure = normalize_structure_blueprint(mixed_structure_blueprint)

        result, generated_class = StructureGenerator().generate_from_structure_blueprint("PersonInfo", normalized_structure)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from datetime import datetime
from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class PersonInfo(StructuredContent):
    """Generated PersonInfo class"""

    name: str = Field(..., description="The name of the person")
    age: float = Field(..., description="The age of the person")
    birthdate: datetime = Field(..., description="The birthdate of the person")
'''

        assert result == expected_code
        assert issubclass(generated_class, StructuredContent)

        # Verify that the string was properly converted to ConceptStructureBlueprint
        assert isinstance(normalized_structure["name"], ConceptStructureBlueprint)
        assert normalized_structure["name"].description == "The name of the person"
        assert normalized_structure["name"].type == ConceptStructureBlueprintFieldType.TEXT
        assert normalized_structure["name"].required

    def test_code_validation_success(self):
        """Test that valid generated code passes validation."""
        structure_blueprint = {
            "name": ConceptStructureBlueprint(description="Name field", type=ConceptStructureBlueprintFieldType.TEXT, required=True),
        }

        generator = StructureGenerator()
        python_code, the_class = generator.generate_from_structure_blueprint("ValidTestModel", structure_blueprint)

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class ValidTestModel(StructuredContent):
    """Generated ValidTestModel class"""

    name: str = Field(..., description="Name field")
'''

        assert python_code == expected_code
        assert isinstance(the_class, type)
        assert issubclass(the_class, StructuredContent)

        # Test validation directly
        generator.validate_generated_code(python_code=python_code, expected_class_name="ValidTestModel")

    def test_code_validation_syntax_error(self):
        """Test that invalid syntax fails validation."""
        generator = StructureGenerator()
        invalid_code = """
from pydantic import Field
from pipelex.core.stuffs.structured_content import StructuredContent

class InvalidModel(StructuredContent):
    name: str = Field(..., description="Name field"  # Missing closing parenthesis
"""

        with pytest.raises(SyntaxError):
            generator.validate_generated_code(python_code=invalid_code, expected_class_name="InvalidModel")

    def test_code_validation_missing_class(self):
        """Test that code without the expected class fails validation."""
        generator = StructureGenerator()
        code_without_expected_class = """
from pydantic import Field
from pipelex.core.stuffs.structured_content import StructuredContent

class WrongClassName(StructuredContent):
    name: str = Field(..., description="Name field")
"""

        with pytest.raises(ConceptStructureValidationError):
            generator.validate_generated_code(python_code=code_without_expected_class, expected_class_name="ExpectedClassName")

    def test_inheritance_from_text_content(self):
        """Test generating a class that inherits from TextContent."""
        structure_blueprint = {
            "author": ConceptStructureBlueprint(
                description="The author of the question",
                type=ConceptStructureBlueprintFieldType.TEXT,
                required=False,
            ),
        }

        generator = StructureGenerator()
        generated_code, generated_class = generator.generate_from_structure_blueprint(
            "Question",
            structure_blueprint,
            base_class_name="TextContent",
        )

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pipelex.core.stuffs.text_content import TextContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class Question(TextContent):
    """Generated Question class"""

    author: Optional[str] = Field(default=None, description="The author of the question")
'''

        assert generated_code == expected_code

        # Verify the generated class is valid
        from pipelex.core.stuffs.text_content import TextContent  # noqa: PLC0415

        assert issubclass(generated_class, TextContent)
        from pipelex.core.stuffs.stuff_content import StuffContent  # noqa: PLC0415

        assert issubclass(generated_class, StuffContent)

        # Test instantiation (TextContent requires 'text' field)
        instance = generated_class(text="Sample text", author="John Doe")  # pyright: ignore[reportCallIssue]
        assert instance.author == "John Doe"  # type: ignore[attr-defined]  # pyright: ignore[reportAttributeAccessIssue]

    def test_inheritance_from_image_content(self):
        """Test generating a class that inherits from ImageContent."""
        structure_blueprint = {
            "table_name": ConceptStructureBlueprint(
                description="Name of the table in the screenshot",
                type=ConceptStructureBlueprintFieldType.TEXT,
                required=False,
            ),
            "row_count": ConceptStructureBlueprint(
                description="Number of rows in the table",
                type=ConceptStructureBlueprintFieldType.INTEGER,
                required=False,
            ),
        }

        generator = StructureGenerator()
        generated_code, generated_class = generator.generate_from_structure_blueprint(
            "TableScreenshot",
            structure_blueprint,
            base_class_name="ImageContent",
        )

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.image_content import ImageContent
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class TableScreenshot(ImageContent):
    """Generated TableScreenshot class"""

    table_name: Optional[str] = Field(default=None, description="Name of the table in the screenshot")
    row_count: Optional[int] = Field(default=None, description="Number of rows in the table")
'''

        assert generated_code == expected_code

        # Verify the generated class is valid
        from pipelex.core.stuffs.image_content import ImageContent  # noqa: PLC0415

        assert issubclass(generated_class, ImageContent)
        from pipelex.core.stuffs.stuff_content import StuffContent  # noqa: PLC0415

        assert issubclass(generated_class, StuffContent)

    def test_inheritance_from_number_content(self):
        """Test generating a class that inherits from NumberContent."""
        structure_blueprint = {
            "unit": ConceptStructureBlueprint(
                description="Unit of measurement",
                type=ConceptStructureBlueprintFieldType.TEXT,
                required=False,
            ),
        }

        generator = StructureGenerator()
        generated_code, generated_class = generator.generate_from_structure_blueprint(
            "Temperature",
            structure_blueprint,
            base_class_name="NumberContent",
        )

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.number_content import NumberContent
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class Temperature(NumberContent):
    """Generated Temperature class"""

    unit: Optional[str] = Field(default=None, description="Unit of measurement")
'''

        assert generated_code == expected_code

        # Verify the generated class is valid
        from pipelex.core.stuffs.number_content import NumberContent  # noqa: PLC0415

        assert issubclass(generated_class, NumberContent)
        from pipelex.core.stuffs.stuff_content import StuffContent  # noqa: PLC0415

        assert issubclass(generated_class, StuffContent)

    def test_inheritance_from_json_content(self):
        """Test generating a class that inherits from JSONContent."""
        structure_blueprint = {
            "schema_version": ConceptStructureBlueprint(
                description="Version of the schema",
                type=ConceptStructureBlueprintFieldType.TEXT,
                required=False,
            ),
        }

        generator = StructureGenerator()
        generated_code, generated_class = generator.generate_from_structure_blueprint(
            "ConfigData",
            structure_blueprint,
            base_class_name="JSONContent",
        )

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.json_content import JSONContent
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class ConfigData(JSONContent):
    """Generated ConfigData class"""

    schema_version: Optional[str] = Field(default=None, description="Version of the schema")
'''

        assert generated_code == expected_code

        # Verify the generated class is valid
        from pipelex.core.stuffs.json_content import JSONContent  # noqa: PLC0415

        assert issubclass(generated_class, JSONContent)
        from pipelex.core.stuffs.stuff_content import StuffContent  # noqa: PLC0415

        assert issubclass(generated_class, StuffContent)

    def test_inheritance_with_empty_structure(self):
        """Test generating a class with no additional fields that just inherits from a base class."""
        structure_blueprint: dict[str, ConceptStructureBlueprint] = {}

        generator = StructureGenerator()
        generated_code, generated_class = generator.generate_from_structure_blueprint(
            "EnhancedText",
            structure_blueprint,
            base_class_name="TextContent",
        )

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.structured_content import StructuredContent
from pipelex.core.stuffs.text_content import TextContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class EnhancedText(TextContent):
    """Generated EnhancedText class"""

'''

        assert generated_code == expected_code

        # Verify the generated class is valid
        from pipelex.core.stuffs.text_content import TextContent  # noqa: PLC0415

        assert issubclass(generated_class, TextContent)
        from pipelex.core.stuffs.stuff_content import StuffContent  # noqa: PLC0415

        assert issubclass(generated_class, StuffContent)

        # Test instantiation works (TextContent requires 'text' field)
        instance = generated_class(text="Sample text")  # pyright: ignore[reportCallIssue]
        assert instance is not None

    def test_inheritance_from_document_content(self):
        """Test generating a class that inherits from DocumentContent."""
        structure_blueprint = {
            "document_type": ConceptStructureBlueprint(
                description="Type of document",
                type=ConceptStructureBlueprintFieldType.TEXT,
                required=False,
            ),
        }

        generator = StructureGenerator()
        generated_code, generated_class = generator.generate_from_structure_blueprint(
            "Invoice",
            structure_blueprint,
            base_class_name="DocumentContent",
        )

        expected_code = '''\
"""
AUTOGENERATED CODE - DO NOT EDIT

If you want to customize this structure:
  1. Copy this file to your own module
  2. Remove the 'structure' or 'refines' declaration from the concept in the MTHDS file
     and declare it in inline mode (see https://docs.pipelex.com/latest/building-methods/concepts/define_your_concepts/#basic-concept-definition)
  3. Make sure your custom class is importable and registered

To regenerate: pipelex build structures <target_directory>
"""

from enum import Enum
from pipelex.core.stuffs.document_content import DocumentContent
from pipelex.core.stuffs.structured_content import StructuredContent
from pydantic import Field
from typing import Optional, List, Dict, Any, Literal


class Invoice(DocumentContent):
    """Generated Invoice class"""

    document_type: Optional[str] = Field(default=None, description="Type of document")
'''

        assert generated_code == expected_code

        # Verify the generated class is valid
        from pipelex.core.stuffs.document_content import DocumentContent  # noqa: PLC0415

        assert issubclass(generated_class, DocumentContent)
        from pipelex.core.stuffs.stuff_content import StuffContent  # noqa: PLC0415

        assert issubclass(generated_class, StuffContent)

    def test_multiple_inheritance_scenarios(self):
        """Test multiple classes with different inheritance scenarios."""
        from pipelex.core.stuffs.stuff_content import StuffContent  # noqa: PLC0415

        test_cases = [
            ("TextContent", "text_content", "Question", {"source": "The source of the question"}),
            ("ImageContent", "image_content", "Diagram", {"diagram_type": "Type of diagram"}),
            ("NumberContent", "number_content", "Score", {"max_value": "Maximum possible score"}),
        ]

        for base_class_name, module_name, class_name, field_dict in test_cases:
            structure_blueprint = {
                field_name: ConceptStructureBlueprint(
                    description=description,
                    type=ConceptStructureBlueprintFieldType.TEXT,
                    required=False,
                )
                for field_name, description in field_dict.items()
            }

            generator = StructureGenerator()
            generated_code, generated_class = generator.generate_from_structure_blueprint(
                class_name,
                structure_blueprint,
                base_class_name=base_class_name,
            )

            # Verify correct import is present
            assert f"from pipelex.core.stuffs.{module_name} import {base_class_name}" in generated_code

            # Verify class inherits from correct base
            assert f"class {class_name}({base_class_name}):" in generated_code

            # Verify it's a valid subclass of StuffContent
            assert issubclass(generated_class, StuffContent)
