from __future__ import annotations

from pydantic_ai import Agent
from pydantic_ai.models import Model

from probegpt.core.models import Probe
from probegpt.data import load_prompt

from .base import AbstractStrategy


def _technique_hint(techniques: list[str]) -> str:
    if not techniques:
        return ""
    tags = ", ".join(techniques)
    return f"WORKING TECHNIQUES (discovered this run — prioritise these):\n  {tags}\n\n"


class MutationStrategy(AbstractStrategy):
    """Produce variations of a seed prompt using different evasion techniques."""

    def __init__(self) -> None:
        self._template = load_prompt("strategies/mutation")

    def generate(
        self,
        seeds: list[Probe],
        model: Model,
        count: int = 5,
        technique_hints: list[str] | None = None,
        sample_fn: object = None,
        **_: object,
    ) -> list[str]:
        if not seeds:
            return []

        seed = sample_fn() if callable(sample_fn) else seeds[0]  # type: ignore[operator]

        hint = _technique_hint(technique_hints or [])
        system = self._template.replace("{count}", str(count)).replace("{technique_hint}", hint)
        agent = Agent(model, system_prompt=system)
        result = agent.run_sync(f"Test prompt to vary:\n\n{seed.content}")
        return self._parse_candidates(result.output)[:count]

    def get_name(self) -> str:
        return "mutation"

    def get_description(self) -> str:
        return "Produce variations of a seed prompt using different evasion techniques"
