"""
Prompt caching example: build cache-optimized prompts for OpenRouter.

Demonstrates:
- PromptBuilder for stable-prefix, append-only prompt construction
- Explicit cache_control breakpoints for Anthropic models
- CacheMetrics tracking across an agent session
- Provider detection for model-specific caching strategy

Applies best practices from:
- OpenAI Codex agent loop (stable prefix, append-only growth)
- Anthropic cache_control breakpoints (explicit caching for Claude models)
- OpenRouter sticky routing (provider-level cache affinity)

Usage:
    OPENROUTER_API_KEY=sk-or-... python examples/prompt_caching.py
"""

import os

import httpx

from agent_preflight import (
    PromptBuilder,
    detect_provider,
    format_cache_report,
    stable_system_prompt,
)
from agent_preflight.provision import OR_BASE

API_KEY = os.environ["OPENROUTER_API_KEY"]

# --- Example 1: Build a cache-optimized prompt for Anthropic Claude ---

# System prompt from stable, reusable sections — NO timestamps or request IDs.
# This is the key insight from the Codex agent loop: keep the prefix identical
# across requests so every turn gets a cache hit.
system = stable_system_prompt(
    "You are a meticulous coding assistant.",
    "Follow the user's instructions precisely.",
    "Always explain your reasoning before writing code.",
    "Use Python 3.11+ features when appropriate.",
)

# Tool definitions — keep in fixed order, identical every request
tools = [
    {
        "type": "function",
        "function": {
            "name": "read_file",
            "description": "Read a file from disk",
            "parameters": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "File path to read"},
                },
                "required": ["path"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "write_file",
            "description": "Write content to a file",
            "parameters": {
                "type": "object",
                "properties": {
                    "path": {"type": "string", "description": "File path to write"},
                    "content": {"type": "string", "description": "File content"},
                },
                "required": ["path", "content"],
            },
        },
    },
]

# Detect provider to choose caching strategy
MODEL = "anthropic/claude-sonnet-4"
provider = detect_provider(MODEL)
print(f"Model: {MODEL}")
print(f"Provider: {provider}")
print(f"Caching strategy: {'explicit cache_control breakpoints' if provider == 'anthropic' else 'automatic prefix caching'}")
print()

# Build the prompt
builder = PromptBuilder(
    system=system,
    tools=tools,
    provider=provider,  # or "auto" to detect from model ID
)


def chat(user_message: str) -> str:
    """Send a message and track cache metrics."""
    builder.add_user(user_message)

    payload = builder.build(model=MODEL, max_tokens=256)

    resp = httpx.post(
        f"{OR_BASE}/chat/completions",
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        json=payload,
        timeout=60.0,
    )
    resp.raise_for_status()
    data = resp.json()

    # Track cache metrics from the response
    usage = data.get("usage", {})
    builder.metrics.record(usage)

    # Log cache performance for this request
    cached = usage.get("cache_read_input_tokens", 0)
    details = usage.get("prompt_tokens_details", {})
    cached += details.get("cached_tokens", 0) if details else 0
    prompt_tokens = usage.get("prompt_tokens", 0)
    print(f"  [usage] prompt={prompt_tokens} cached={cached} "
          f"({'HIT' if cached > 0 else 'MISS'})")

    reply = data["choices"][0]["message"]["content"]
    builder.add_assistant(reply)
    return reply


def main():
    # Multi-turn conversation — each turn preserves the cached prefix
    print("--- Turn 1 (cache write expected) ---")
    reply = chat("What is a Python decorator? Keep it to one sentence.")
    print(f"  Reply: {reply[:100]}...")
    print()

    print("--- Turn 2 (cache hit expected — prefix unchanged) ---")
    reply = chat("Show me a simple example of one.")
    print(f"  Reply: {reply[:100]}...")
    print()

    print("--- Turn 3 (cache hit expected — append-only growth) ---")
    reply = chat("Now make it accept arguments.")
    print(f"  Reply: {reply[:100]}...")
    print()

    # Print cache performance summary
    print("=" * 60)
    print(format_cache_report(builder.metrics, MODEL))
    print()
    print(f"Lifetime metrics: {builder.metrics.summary()}")


if __name__ == "__main__":
    main()
