"""
Coding LLM integration for generating code from tickets.

Uses Anthropic Claude to generate code given a ticket instruction
and retrieved context. Both the control and test agents use the
same coding LLM -- only the *context* differs.
"""

from __future__ import annotations

import logging

import httpx

from .models import TokenUsage

logger = logging.getLogger("clew.bench.coding_llm")

SYSTEM_PROMPT = """\
You are a senior software engineer implementing features in an existing codebase.
You receive context about the current codebase state and a task to complete.
Write clean, production-quality code. Only output the code files that need to
be created or modified. Use the format:

### path/to/file.py
```python
<file contents>
```

If multiple files need changes, output each one separately."""

CODING_PROMPT_TEMPLATE = """\
## Current Codebase Context

{context}

## Task

{instruction}

## Success Criteria

{success_criteria}

Implement the task. Output the complete file contents for each file that needs
to be created or modified."""


class CodingLLM:
    """Generates code using Anthropic Claude."""

    def __init__(self, api_key: str, model: str = "claude-sonnet-4-20250514"):
        self.api_key = api_key
        self.model = model
        self._client = httpx.AsyncClient(timeout=120.0)

    async def generate(self, instruction: str, success_criteria: str, context: str) -> tuple[str, TokenUsage]:
        """
        Generate code for a ticket given context.

        Args:
            instruction: The ticket instruction.
            success_criteria: What success looks like.
            context: Retrieved codebase context (from Clew or RAG).

        Returns:
            Tuple of (generated_code, token_usage).
        """
        user_message = CODING_PROMPT_TEMPLATE.format(
            context=context or "(no context available)",
            instruction=instruction,
            success_criteria=success_criteria,
        )

        try:
            response = await self._client.post(
                "https://api.anthropic.com/v1/messages",
                headers={
                    "x-api-key": self.api_key,
                    "anthropic-version": "2023-06-01",
                    "content-type": "application/json",
                },
                json={
                    "model": self.model,
                    "max_tokens": 4096,
                    "system": SYSTEM_PROMPT,
                    "messages": [{"role": "user", "content": user_message}],
                },
            )
            response.raise_for_status()
            data = response.json()

            code = data["content"][0]["text"]
            usage = TokenUsage(
                input_tokens=data["usage"]["input_tokens"],
                output_tokens=data["usage"]["output_tokens"],
            )

            logger.info("Coding LLM: %d input, %d output tokens", usage.input_tokens, usage.output_tokens)
            return code, usage

        except (httpx.HTTPError, KeyError, IndexError) as e:
            logger.error("Coding LLM generation failed: %s", e)
            return f"# Generation failed: {e}", TokenUsage()

    async def close(self) -> None:
        await self._client.aclose()
