"""
Transclusion engine implementation.

Provides the core engine for processing transclusion directives,
managing context, and producing final rendered content.
"""

from pathlib import Path
from typing import Dict, Any, Optional, List

from .context import TransclusionContext
from .directives import DirectiveParser, Directive
from ..errors import TransclusionError


class TransclusionEngine:
    """
    Core engine for processing transclusion directives.

    Handles file inclusion, variable substitution, conditional content,
    and maintains processing context with circular reference detection.
    """

    def __init__(self, base_path: Optional[Path] = None,
                 variables: Optional[Dict[str, Any]] = None,
                 max_depth: int = 10):
        """
        Initialize the transclusion engine.

        Args:
            base_path: Base path for relative file resolution
            variables: Initial variables for substitution
            max_depth: Maximum inclusion depth
        """
        self.base_path = base_path or Path.cwd()
        self.initial_variables = variables or {}
        self.max_depth = max_depth

    def process_content(self, content: str,
                       context: Optional[TransclusionContext] = None) -> str:
        """
        Process transclusion directives in content.

        Args:
            content: Content containing transclusion directives
            context: Processing context (created if None)

        Returns:
            Processed content with directives resolved
        """
        if context is None:
            context = TransclusionContext(
                base_path=self.base_path,
                variables=self.initial_variables.copy(),
                max_depth=self.max_depth
            )

        # Parse all directives
        directives = DirectiveParser.parse_directives(content)

        # Process directives in reverse order to maintain positions
        processed_content = content
        for directive in reversed(directives):
            try:
                replacement = self._process_directive(directive, context)
                processed_content = (
                    processed_content[:directive.start_pos] +
                    replacement +
                    processed_content[directive.end_pos:]
                )
            except Exception as e:
                # Replace with error message in development
                error_msg = f"[TRANSCLUSION ERROR: {str(e)}]"
                processed_content = (
                    processed_content[:directive.start_pos] +
                    error_msg +
                    processed_content[directive.end_pos:]
                )

        return processed_content

    def process_file(self, file_path: Path,
                    context: Optional[TransclusionContext] = None) -> str:
        """
        Process a file with transclusion directives.

        Args:
            file_path: Path to file to process
            context: Processing context (created if None)

        Returns:
            Processed file content
        """
        if context is None:
            context = TransclusionContext(
                base_path=file_path.parent,
                variables=self.initial_variables.copy(),
                max_depth=self.max_depth
            )

        try:
            # Enter file processing
            context.enter_file(file_path)

            # Read file content
            if not file_path.exists():
                raise TransclusionError(f"File not found: {file_path}")

            content = file_path.read_text(encoding='utf-8')

            # Process transclusion directives
            processed_content = self.process_content(content, context)

            # Exit file processing
            context.exit_file(file_path)

            return processed_content

        except Exception as e:
            # Exit file processing on error
            context.exit_file(file_path)
            raise TransclusionError(f"Error processing file {file_path}: {e}")

    def _process_directive(self, directive: Directive,
                          context: TransclusionContext) -> str:
        """
        Process a single directive.

        Args:
            directive: Directive to process
            context: Processing context

        Returns:
            Replacement content for the directive
        """
        if directive.type == 'include':
            return self._process_include_directive(directive, context)
        elif directive.type == 'variable':
            return self._process_variable_directive(directive, context)
        elif directive.type == 'conditional':
            return self._process_conditional_directive(directive, context)
        else:
            raise TransclusionError(f"Unknown directive type: {directive.type}")

    def _process_include_directive(self, directive: Directive,
                                 context: TransclusionContext) -> str:
        """
        Process a file include directive.

        Args:
            directive: Include directive
            context: Processing context

        Returns:
            Content of included file
        """
        file_path_str = directive.args['file']
        file_path = context.resolve_path(file_path_str)

        # Create child context for the included file
        child_context = context.create_child_context(file_path.parent)

        # Add any directive arguments as variables
        for key, value in directive.args.items():
            if key != 'file':
                child_context.set_variable(key, value)

        # Process the included file
        return self.process_file(file_path, child_context)

    def _process_variable_directive(self, directive: Directive,
                                  context: TransclusionContext) -> str:
        """
        Process a variable substitution directive.

        Args:
            directive: Variable directive
            context: Processing context

        Returns:
            Variable value as string
        """
        var_name = directive.args['name']
        value = context.get_variable(var_name, f"{{{{UNDEFINED: {var_name}}}}}")
        return str(value)

    def _process_conditional_directive(self, directive: Directive,
                                     context: TransclusionContext) -> str:
        """
        Process a conditional content directive.

        Args:
            directive: Conditional directive
            context: Processing context

        Returns:
            Conditional content if condition is true, empty string otherwise
        """
        condition = directive.args['condition']

        # Simple condition evaluation (just variable existence for now)
        if condition in context.variables:
            var_value = context.get_variable(condition)
            # Evaluate truthy/falsy
            if var_value and str(var_value).lower() not in ('false', '0', ''):
                # Process the content block recursively
                return self.process_content(directive.content or '', context)

        return ''