"""Word template renderer — docxtpl + Jinja2 sandbox.

Fills Jinja2 placeholders ({{var}}, {% for %}, {% if %}) in a .docx
template using python-docx-template. The Jinja2 environment is sandboxed
to prevent SSTI (Server-Side Template Injection) attacks — untrusted
templates cannot access dunder attributes or execute arbitrary code.
"""

from __future__ import annotations

import logging
from pathlib import Path

from docxtpl import DocxTemplate
from jinja2.sandbox import SandboxedEnvironment

logger = logging.getLogger(__name__)


class TemplateRenderer:
    """Fill Jinja2 placeholders in a .docx template.

    This renderer is registered under the "word" format key alongside
    WordRenderer. DocumentService dispatches to ``render_template`` when
    a template_path is provided (Word only).
    """

    def render(self, markdown_content: str, output_path: Path) -> Path:
        """Fallback render — not used for template filling.

        TemplateRenderer is invoked via render_template(), not render().
        This method exists only to satisfy the renderer protocol so the
        same renderer can be registered for "word" format. If called
        directly, it raises to surface misuse.
        """
        raise NotImplementedError(
            "TemplateRenderer does not support Markdown rendering. "
            "Use render_template() with a .docx template path."
        )

    def render_template(
        self, template_path: str | Path, data: dict[str, object], output_path: Path
    ) -> Path:
        """Fill a .docx template with data using Jinja2 sandbox.

        Args:
            template_path: Path to the .docx template file.
            data: Dict of variable values for Jinja2 placeholders.
            output_path: Destination .docx path.

        Returns:
            The output_path.
        """
        template_path = Path(template_path)
        if not template_path.exists():
            raise FileNotFoundError(f"Template not found: {template_path}")

        # SandboxedEnvironment prevents access to dunder attributes and
        # unsafe builtins — this is the security boundary against SSTI.
        # docxtpl uses jinja2 internally; we pass our sandboxed env so
        # the same restrictions apply to template rendering.
        env = SandboxedEnvironment(
            autoescape=False,  # docx content is not HTML
            trim_blocks=True,
            lstrip_blocks=True,
        )

        doc = DocxTemplate(str(template_path))
        # Attach our sandboxed environment to the template's jinja_env
        # so render() uses our restrictions.
        doc.jinja_env = env

        try:
            doc.render(data)
        except Exception as exc:
            # Jinja2 errors (undefined variables, syntax errors) surface here.
            # We let them propagate — the caller (DocumentService) wraps
            # the call and returns an error result.
            logger.error(f"Template rendering failed: {exc}")
            raise

        output_path.parent.mkdir(parents=True, exist_ok=True)
        doc.save(str(output_path))
        return output_path
