import string

from promptlock.exceptions import TemplateRenderError


class PromptTemplate:
    """Represents a prompt string with named placeholders."""

    def __init__(self, text: str):
        self.text = text
        self._variables = self._parse_variables()

    def _parse_variables(self) -> list[str]:
        formatter = string.Formatter()
        return [
            field_name
            for _, field_name, _, _ in formatter.parse(self.text)
            if field_name is not None
        ]

    @property
    def variables(self) -> list[str]:
        """Returns the list of variable names found in the template."""
        return self._variables

    def render(self, **kwargs) -> str:
        """Render the template with the provided variables.

        Raises:
            TemplateRenderError: if any required variable is missing.
        """
        missing = [var for var in self._variables if var not in kwargs]
        if missing:
            raise TemplateRenderError(missing_vars=missing)
        return self.text.format(**kwargs)

    def __repr__(self) -> str:
        return f"PromptTemplate(variables={self._variables})"