"""Full-featured example: code review prompt with all layers populated."""

from prompt_builder import (
    Prompt,
    Persona,
    Rule,
    RulePriority,
    Instruction,
    InputData,
    OutputSpec,
    CoTSpec,
    CoTStrategy,
    Visibility,
    ContextBlock,
    Example,
    Message,
    TokenBudget,
    WhenScope,
    compile,
)

diff = """\
--- a/api/auth.py
+++ b/api/auth.py
@@ -12,6 +12,10 @@ def login(request):
     username = request.POST["username"]
     password = request.POST["password"]
+    if username == "admin" and password == "admin123":
+        return create_session(get_user("admin"))
+
     user = authenticate(username, password)
"""

prompt = Prompt(
    # Identity layer
    persona=Persona(
        role="Senior security-focused code reviewer with 15 years of experience.",
        tone="direct, constructive",
        domain=["security", "python", "web backends"],
        anti_patterns=[
            "Don't write vague feedback like 'this could be improved'",
            "Never rewrite the entire file unprompted",
        ],
    ),
    rules=[
        Rule(constraint="Every finding must include severity: critical | warning | nit"),
        Rule(constraint="Always praise at least one thing the author did well"),
        Rule(
            constraint="Flag any SQL built with string concatenation as critical",
            scope=WhenScope(condition="input contains database code"),
        ),
        Rule(
            constraint="Suggest but don't insist on style-only changes",
            priority=RulePriority.SOFT,
        ),
    ],

    # Knowledge layer
    context=[
        ContextBlock(
            content="Auth module uses bcrypt with cost factor 12. Never store plaintext passwords.",
            source="repo://docs/security-policy.md",
            relevance=0.95,
        ),
        ContextBlock(
            content="All endpoints require CSRF tokens for POST requests.",
            source="repo://docs/api-guide.md",
            relevance=0.6,
        ),
        ContextBlock(
            content="We use black formatter with line length 88.",
            source="repo://pyproject.toml",
            relevance=0.15,  # low relevance → first to get dropped
        ),
    ],
    examples=[
        Example(
            input='query = f"SELECT * FROM users WHERE id = {id}"',
            output='{"severity": "critical", "issue": "SQL injection via f-string"}',
            weight=1.0,
        ),
        Example(
            input="return db.execute('SELECT * FROM users WHERE id = ?', [id])",
            output='{"severity": "nit", "issue": "Parameter `id` shadows built-in"}',
            weight=0.6,
        ),
    ],

    # Task layer
    instruction=Instruction(
        task="Review the provided code diff for bugs, security issues, and readability.",
        subtasks=[
            "Check for hardcoded credentials",
            "Check for authentication bypass patterns",
            "Evaluate error handling",
        ],
        constraints=["Limit review to changed lines and immediate context"],
        intent="Help the author ship safe, correct, maintainable code.",
    ),
    input_data=InputData(
        content=diff,
        format="diff",
        delimiter="```diff",
        label="code_diff",
    ),

    # Control layer
    output_spec=OutputSpec(
        format="json",
        length="concise",
        constraints=[
            "Each finding: {severity, location, issue, suggestion}",
            "Include a 'strengths' array",
        ],
    ),
    cot=CoTSpec(
        strategy=CoTStrategy.STEP_BY_STEP,
        visibility=Visibility.HIDDEN,
    ),

    # Conversation layer
    history=[
        Message(role="user", content="Hey, can you review PR #342?"),
        Message(role="assistant", content="Sure, send the diff."),
    ],
)

# Compile with a generous budget — everything fits
result = compile(prompt, TokenBudget(context_window=128_000))
print("=== FULL BUDGET ===")
print(result.report())
print(f"\nMessages: {len(result.messages)}")
for msg in result.messages:
    print(f"\n[{msg['role']}] ({len(msg['content'])} chars)")
    print(msg["content"][:300])

# Now compile with a tiny budget — watch truncation kick in
print("\n\n=== TIGHT BUDGET ===")
tight_result = compile(prompt, TokenBudget(context_window=1_200, output_reserve=200, safety_margin=50))
print(tight_result.report())
for w in tight_result.warnings:
    print(f"  ⚠ {w}")
