"""PromptTemplate - Prompt 模板渲染"""

import hashlib
import json
import logging
import re
from typing import Any

from agentkit.prompts.section import PromptSection

logger = logging.getLogger(__name__)


class PromptTemplate:
    """Prompt 模板

    支持变量注入、Token 预算管理、动态段落组合。
    """

    def __init__(
        self,
        sections: PromptSection,
        name: str = "",
        version: str = "1.0.0",
    ):
        self._sections = sections
        self.name = name
        self.version = version

    def render(
        self,
        variables: dict[str, Any] | None = None,
        context_budget: int = 3000,
    ) -> list[dict[str, str]]:
        """渲染 Prompt 为消息列表

        Returns:
            [{"role": "system", "content": "..."}, {"role": "user", "content": "..."}]
        """
        system_parts = []
        if self._sections.identity:
            system_parts.append(self._sections.identity)
        if self._sections.context:
            context = self._sections.context
            if variables:
                for key, value in variables.items():
                    context = re.sub(r'\$\{' + re.escape(key) + r'\}', str(value), context)
            system_parts.append(context)
        if self._sections.constraints:
            system_parts.append(self._sections.constraints)

        user_parts = []
        if self._sections.instructions:
            instructions = self._sections.instructions
            if variables:
                for key, value in variables.items():
                    instructions = re.sub(r'\$\{' + re.escape(key) + r'\}', str(value), instructions)
            user_parts.append(instructions)
        if self._sections.output_format:
            user_parts.append(self._sections.output_format)
        if self._sections.examples:
            user_parts.append(self._sections.examples)

        messages = []
        if system_parts:
            messages.append({"role": "system", "content": "\n\n".join(system_parts)})
        if user_parts:
            messages.append({"role": "user", "content": "\n\n".join(user_parts)})

        return messages

    @property
    def sections(self) -> PromptSection:
        return self._sections

    def render_cached(
        self,
        variables: dict[str, Any] | None = None,
    ) -> list[dict[str, str]]:
        """Render with caching - returns cached result for same variables

        Uses MD5 hash of the variables dict as cache key.
        Same variables will return the previously rendered result.
        """
        cache_key = hashlib.md5(
            json.dumps(variables or {}, sort_keys=True).encode()
        ).hexdigest()

        if not hasattr(self, "_render_cache"):
            self._render_cache = {}

        if cache_key in self._render_cache:
            return self._render_cache[cache_key]

        result = self.render(variables=variables)
        self._render_cache[cache_key] = result
        return result

    def clear_cache(self) -> None:
        """Clear the render cache"""
        if hasattr(self, "_render_cache"):
            self._render_cache.clear()
