"""Agent scaffolding — renders agent templates into project directories."""

from __future__ import annotations

import dataclasses
from dataclasses import dataclass
from pathlib import Path

from jinja2 import Environment, FileSystemLoader, TemplateSyntaxError


AGENT_TEMPLATES = ["single-agent", "researcher", "custom"]
PROVIDERS = ["anthropic", "openai", "local"]
DEFAULT_MODELS = {
    "anthropic": "claude-sonnet-4-5-20250929",
    "openai": "gpt-5",
    "local": "llama3.2",
}


@dataclass
class AgentScaffoldContext:
    """Context for rendering an agent template."""

    name: str
    description: str
    template: str
    provider: str
    model: str

    @classmethod
    def from_user_input(
        cls,
        name: str,
        description: str,
        template: str = "single-agent",
        provider: str = "anthropic",
        model: str | None = None,
    ) -> AgentScaffoldContext:
        return cls(
            name=name,
            description=description,
            template=template,
            provider=provider,
            model=model or DEFAULT_MODELS.get(provider, ""),
        )


def _get_agent_templates_dir() -> Path:
    """Return the path to the bundled agent templates directory."""
    return Path(__file__).parent / "templates"


def scaffold_agent(
    context: AgentScaffoldContext,
    output_dir: Path | None = None,
) -> Path:
    """Generate a new agent project from a template.

    Args:
        context: The agent scaffold configuration.
        output_dir: Parent directory for the new agent. Defaults to ./agents/.

    Returns:
        Path to the generated agent directory.

    Raises:
        FileExistsError: If the agent directory already exists.
        FileNotFoundError: If the requested template doesn't exist.
    """
    parent = output_dir or (Path.cwd() / "agents")
    agent_dir = parent / context.name

    if agent_dir.exists():
        raise FileExistsError(f"Agent directory already exists: {agent_dir}")

    template_dir = _get_agent_templates_dir() / context.template
    if not template_dir.is_dir():
        raise FileNotFoundError(f"Agent template not found: {context.template}")

    context_dict = dataclasses.asdict(context)
    env = Environment(
        loader=FileSystemLoader(str(template_dir)),
        keep_trailing_newline=True,
    )

    for source_path in sorted(template_dir.rglob("*")):
        if source_path.is_dir():
            continue

        relative = source_path.relative_to(template_dir)

        if source_path.suffix == ".j2":
            dest = agent_dir / relative.with_suffix("")
            dest.parent.mkdir(parents=True, exist_ok=True)

            try:
                template = env.get_template(str(relative))
                rendered = template.render(context_dict)
            except TemplateSyntaxError as e:
                raise ValueError(
                    f"Template syntax error in {relative}: {e.message} (line {e.lineno})"
                ) from e

            dest.write_text(rendered)
        else:
            dest = agent_dir / relative
            dest.parent.mkdir(parents=True, exist_ok=True)
            import shutil

            shutil.copy2(source_path, dest)

    # Create empty evals directory
    (agent_dir / "evals").mkdir(parents=True, exist_ok=True)

    return agent_dir
