"""Tool for rendering Jinja2 templates."""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from .base import Tool


class TemplateRenderTool(Tool):
    """Render Jinja2 templates with provided variables."""

    def __init__(self, *, workspace: Path, allowed_dir: Path | None = None) -> None:
        self._workspace = workspace
        self._allowed_dir = allowed_dir

    @property
    def name(self) -> str:
        return "template_render"

    @property
    def description(self) -> str:
        return (
            "Render a Jinja2 template with given variables. "
            "Can accept inline template text or a template file from workspace."
        )

    @property
    def parameters(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "template": {
                    "type": "string",
                    "description": "Inline Jinja2 template string.",
                },
                "template_file": {
                    "type": "string",
                    "description": "Workspace-relative path to a template file.",
                },
                "variables": {
                    "type": "object",
                    "description": "Variables to pass to the template.",
                },
                "output_file": {
                    "type": "string",
                    "description": "Workspace-relative path to save rendered output.",
                },
                "strict": {
                    "type": "boolean",
                    "description": "Raise error on undefined variables. Default true.",
                },
            },
        }

    async def execute(self, **kwargs: Any) -> str:
        try:
            from jinja2 import Environment, StrictUndefined, Undefined, BaseLoader
        except ImportError:
            return json.dumps({"error": "jinja2 is not installed. Run: pip install jinja2"})

        template_str = kwargs.get("template")
        template_file = kwargs.get("template_file")
        variables = kwargs.get("variables") or {}
        output_file = kwargs.get("output_file")
        strict = kwargs.get("strict", True)

        if not template_str and not template_file:
            return json.dumps({"error": "Provide either 'template' or 'template_file'"})

        if template_file:
            path = (self._workspace / template_file).resolve()
            if not str(path).startswith(str(self._workspace.resolve())):
                return json.dumps({"error": "Path outside workspace"})
            if self._allowed_dir and not str(path).startswith(str(self._allowed_dir.resolve())):
                return json.dumps({"error": "Path outside allowed directory"})
            if not path.exists():
                return json.dumps({"error": f"Template file not found: {template_file}"})
            template_str = path.read_text(encoding="utf-8")

        try:
            undef_cls = StrictUndefined if strict else Undefined
            env = Environment(loader=BaseLoader(), undefined=undef_cls)
            tmpl = env.from_string(template_str)
            rendered = tmpl.render(**variables)
        except Exception as exc:
            return json.dumps({"error": f"Template rendering failed: {exc}"})

        result: dict[str, Any] = {
            "ok": True,
            "rendered_length": len(rendered),
        }

        if output_file:
            out_path = (self._workspace / output_file).resolve()
            if not str(out_path).startswith(str(self._workspace.resolve())):
                return json.dumps({"error": "Output path outside workspace"})
            out_path.parent.mkdir(parents=True, exist_ok=True)
            out_path.write_text(rendered, encoding="utf-8")
            result["output_file"] = str(out_path)
        else:
            if len(rendered) > 50_000:
                result["rendered"] = rendered[:50_000] + "\n... [truncated]"
            else:
                result["rendered"] = rendered

        return json.dumps(result)
