"""Generator that converts guardrail suggestions into validation @tool function code."""

from __future__ import annotations

import logging

import litellm

from sage_evaluator.exceptions import SuggestionError
from sage_evaluator.models import GeneratedTool, Suggestion, SuggestionCategory
from sage_evaluator.suggestion.tool_generator import _extract_function_name, _strip_code_fences

logger = logging.getLogger(__name__)

_GUARDRAIL_GENERATION_PROMPT_TEMPLATE = """\
You are an expert Python developer working with the Apollo Agent SDK.

A code review has identified the following safety / validation gap in an agent:

Title: {title}
Description: {description}
Problem context:
{before}

Proposed resolution hint:
{after}

## Task

Generate a complete Python guardrail function using the Apollo Agent @tool decorator.
The function must:
1. Import `tool` from `sage.tools.decorator`
2. Be decorated with `@tool(description="Validates ...")`
3. Have a clear, snake_case function name starting with `validate_` or `check_`
4. Include a docstring that explains what it validates and why
5. Implement DETERMINISTIC validation logic — no LLM calls, no network I/O
6. Return a human-readable string: start with "ok:" on success, "error: <reason>"
   on failure so callers can inspect the prefix
7. Use only Python standard library imports
8. Have typed parameters and return type `str`

Return ONLY the Python source code — no markdown fences, no explanation.

Example output:
from sage.tools.decorator import tool


@tool(description="Validates that a URL is absolute and uses https://.")
def validate_url_scheme(url: str) -> str:
    \"\"\"Guardrail: ensure the provided URL is an absolute HTTPS URL.

    Rejects plain HTTP, relative paths, and other schemes to prevent
    accidental data leakage over unencrypted channels.

    Args:
        url: The URL string to validate.

    Returns:
        "ok: URL is valid" on success, or "error: <reason>" on failure.
    \"\"\"
    from urllib.parse import urlparse

    parsed = urlparse(url)
    if parsed.scheme != "https":
        return f"error: URL must use https://, got '{{parsed.scheme or '(none)'}}'"
    if not parsed.netloc:
        return "error: URL must be absolute (include a host)"
    return "ok: URL is valid"
"""


class GuardrailGenerator:
    """Generates deterministic validation ``@tool`` functions from guardrail suggestions.

    Only suggestions whose category is
    :attr:`~sage_evaluator.models.SuggestionCategory.GUARDRAIL` are
    processed; all others are silently ignored.

    Example usage::

        generator = GuardrailGenerator(model="azure_ai/claude-opus-4-6")
        guardrails = await generator.generate_guardrails(report.suggestions)
        for g in guardrails:
            print(g.source_code)
    """

    def __init__(self, model: str) -> None:
        self.model = model

    async def generate_guardrails(self, suggestions: list[Suggestion]) -> list[GeneratedTool]:
        """Generate guardrail @tool functions from guardrail-category suggestions.

        Args:
            suggestions: Full list of suggestions from the analyzer. Non-
                ``guardrail`` entries are ignored.

        Returns:
            A list of :class:`~sage_evaluator.models.GeneratedTool` objects,
            one per processed suggestion. The ``category`` field is set to
            ``"guardrail"``.

        Raises:
            SuggestionError: If the LLM call fails for any suggestion.
        """
        candidates = [s for s in suggestions if s.category == SuggestionCategory.GUARDRAIL]
        if not candidates:
            logger.debug("No guardrail suggestions to process.")
            return []

        logger.info("Generating guardrails from %d suggestion(s)", len(candidates))
        generated: list[GeneratedTool] = []
        for suggestion in candidates:
            guardrail = await self._generate_single_guardrail(suggestion)
            generated.append(guardrail)

        logger.info("Guardrail generation complete: %d guardrail(s) generated", len(generated))
        return generated

    async def _generate_single_guardrail(self, suggestion: Suggestion) -> GeneratedTool:
        """Call the LLM to produce source code for a single guardrail suggestion."""
        prompt = _GUARDRAIL_GENERATION_PROMPT_TEMPLATE.format(
            title=suggestion.title,
            description=suggestion.description,
            before=suggestion.before or "(not specified)",
            after=suggestion.after or "(not specified)",
        )

        logger.debug("Generating guardrail for suggestion: '%s'", suggestion.title)

        try:
            response = await litellm.acompletion(
                model=self.model,
                messages=[{"role": "user", "content": prompt}],
                temperature=0.0,
            )
        except Exception as exc:
            raise SuggestionError(
                f"LLM call failed while generating guardrail for '{suggestion.title}': {exc}"
            ) from exc

        source_code: str = response.choices[0].message.content or ""
        source_code = _strip_code_fences(source_code)

        name = _extract_function_name(source_code)
        logger.debug("Generated guardrail '%s' (%d chars)", name, len(source_code))

        return GeneratedTool(
            name=name,
            description=suggestion.description,
            source_code=source_code,
            category="guardrail",
        )
