"""Root cause analysis prompt templates.

Templates for AI-powered root cause analysis of test failures
and flaky tests.
"""

from __future__ import annotations

# System prompt for root cause analysis
ROOT_CAUSE_SYSTEM_PROMPT = """You are an expert software debugging assistant specializing in root cause analysis of flaky tests.

Your task is to analyze test failures and identify the FUNDAMENTAL cause of the issue, not just symptoms.

## Analysis Framework

When analyzing failures, systematically consider:
1. The exact error type and message — what directly failed
2. The stack trace and code context — where it failed
3. I/O transcripts (HTTP, SQL, Redis calls) — what external calls were made
4. Environmental factors (timing, ordering, resources) — what varied between runs
5. Test isolation and shared state — whether other tests influence this one
6. The divergence point — the first place where passing and failing runs differ

## Flakiness Categories

Categorize into ONE of these types:
- TIMING: Race conditions, missing awaits, sleep-dependent logic, tight timeouts, clock skew
- ORDERING: SQL without ORDER BY, dict/set iteration, non-deterministic sorting, hash randomization
- RESOURCE: Port conflicts, file locks, disk space, memory limits, temp file collisions
- STATE: Shared mutable state between tests, fixture pollution, database leakage, global mutations
- NETWORK: External API instability, DNS resolution, certificate expiry, rate limiting
- CONCURRENCY: Thread safety violations, deadlocks, missing locks, async task leaks

## Output Requirements

Always provide:
1. A clear, concise explanation of the root cause (start with "This test is flaky because...")
2. Concrete evidence from the provided context supporting your conclusion
3. The exact location in code where the issue originates (file, line, function)
4. Recommended fixes ranked by likelihood of success

## Important Constraints

- Only cite evidence that is present in the provided context — do not hallucinate details
- Distinguish between root cause (why it fails) and trigger (what makes it fail THIS time)
- If uncertain, state your confidence level and what additional information would help
- Confidence calibration: 0.9+ means you would bet money on this diagnosis
"""


# Chain of thought prompt for root cause analysis
ROOT_CAUSE_COT_PROMPT = """Analyze this test failure step by step using chain-of-thought reasoning.

## Error Information
Exception Type: {exception_type}
Message: {error_message}

## Stack Trace
{stack_trace}

## Code Context
{code_context}

## I/O Transcripts
HTTP Calls: {http_count}
SQL Queries: {sql_count}
Redis Commands: {redis_count}

## Divergence (if available)
{divergence_info}

Think through this systematically:

### Step 1: Initial Observation
What does the error tell us directly? What type of failure is this?

### Step 2: Divergence Analysis
Where did the passing and failing runs first differ? What changed?

### Step 3: Evidence Collection
What patterns in the I/O transcripts, stack trace, or local variables support a hypothesis?
List each piece of evidence with its significance.

### Step 4: Root Cause Identification
What is the FUNDAMENTAL cause (not just the trigger)?
Apply the 5-whys technique: keep asking "why?" until you reach the root.

### Step 5: Flakiness Category
Which category does this fall into? Justify with evidence.
Consider and explicitly reject alternative categories.

### Step 6: Confidence Assessment
- How certain are you? (0.0-1.0)
- What could make your diagnosis wrong?
- What additional information would increase confidence?

### Step 7: Fix Recommendations
Provide the top 3 fixes, ranked by likelihood of success.
For each: what to change, why it fixes the root cause, and potential risks.

Provide your analysis:
"""


# Prompt for categorizing flakiness
CATEGORIZE_FLAKINESS_PROMPT = """Categorize this test failure into exactly one flakiness type.

Test: {test_name}
Error: {error_type}: {error_message}
Divergence Type: {divergence_type}

## Decision Tree (follow in order)

1. Does the error involve timing, async/await, sleep, or timeout?
   → If YES and there's a race condition or missing synchronization → TIMING

2. Does the divergence show different data ordering (SQL results, collection iteration)?
   → If YES and the assertion compares ordered sequences → ORDERING

3. Does the error involve external HTTP/DNS/API calls?
   → If YES and the divergence is in external call results → NETWORK

4. Does the error involve file paths, ports, disk, or memory?
   → If YES and resources vary between runs → RESOURCE

5. Does the error suggest test pollution or shared state?
   → If YES and state leaks between test runs → STATE

6. Does the error involve threads, locks, or concurrent access?
   → If YES and there's unsynchronized shared access → CONCURRENCY

## Required Output
- Category: exactly one of TIMING, ORDERING, RESOURCE, STATE, NETWORK, CONCURRENCY
- Primary evidence: the strongest signal supporting your choice
- Alternative considered: which other category you considered and why you rejected it

Category:"""


# Prompt for identifying divergence
IDENTIFY_DIVERGENCE_PROMPT = """Compare these passing and failing runs to find where they diverge:

## Passing Run
{passing_events}

## Failing Run
{failing_events}

Find:
1. The first event where they differ
2. What changed (request, response, timing)
3. Why this might cause the failure

Divergence Point:"""


# Prompt for explaining root cause
EXPLAIN_ROOT_CAUSE_PROMPT = """Explain why this test is flaky in plain English that any developer can understand.

## Test Information
Test: {test_name}
File: {file_path}

## Root Cause Analysis
Category: {category}
Divergence: {divergence_type}

## Evidence
{evidence}

## Examples of Good vs Bad Explanations

GOOD: "This test is flaky because the SQL query on line 42 returns rows in non-deterministic order (no ORDER BY clause), and the assertion on line 45 compares against a hardcoded expected list. When the database returns rows in a different order, the equality check fails."

BAD: "This test has a flakiness issue related to ordering."

BAD: "The test sometimes fails due to an error in the database query."

## Requirements

Write a clear explanation (2-4 sentences) that:
1. Starts with "This test is flaky because..."
2. Names the SPECIFIC line number or function causing the issue
3. Explains the MECHANISM — how does non-determinism enter the test?
4. States why it's INTERMITTENT — what varies between runs?
5. Uses simple language but includes technical specifics

Explanation:"""


# Prompt for generating fix recommendations
GENERATE_FIX_RECOMMENDATIONS_PROMPT = """Generate fix recommendations for this flaky test.

## Root Cause
{root_cause}

## Category
{category}

## Code Location
File: {file_path}
Lines: {line_numbers}

## Code Context
```python
{code_context}
```

## Anti-Patterns (DO NOT generate these)
- Adding `time.sleep()` to fix timing issues — use explicit waits/conditions instead
- Wrapping code in `try/except: pass` to suppress errors
- Adding `@pytest.mark.flaky` or `@retry` decorators — these mask the problem
- Sorting results in the assertion instead of fixing the query/source
- Adding broad `except Exception` handlers

## Quality Checklist (each fix MUST satisfy ALL)
- Addresses the root cause identified above, not just the symptom
- Changes <= 10 lines of code (prefer minimal diffs)
- Does not change test behavior for passing cases
- Uses the codebase's existing patterns (imports, naming conventions)
- Would pass code review by a senior engineer

For each fix, provide:
1. Description of the change (1-2 sentences)
2. Why it addresses the root cause (specific reasoning)
3. Confidence score (0.0-1.0, calibrated: 0.9+ means near-certain)
4. Potential risks or edge cases

Generate up to 3 fixes, ranked by likelihood of success:"""


def format_root_cause_prompt(
    exception_type: str,
    error_message: str,
    stack_trace: str,
    code_context: str = "",
    http_count: int = 0,
    sql_count: int = 0,
    redis_count: int = 0,
    divergence_info: str = "",
) -> str:
    """Format the root cause analysis prompt with context."""
    return ROOT_CAUSE_COT_PROMPT.format(
        exception_type=exception_type,
        error_message=error_message,
        stack_trace=stack_trace,
        code_context=code_context or "Not available",
        http_count=http_count,
        sql_count=sql_count,
        redis_count=redis_count,
        divergence_info=divergence_info or "No divergence data",
    )


def format_categorize_prompt(
    test_name: str,
    error_type: str,
    error_message: str,
    divergence_type: str = "",
) -> str:
    """Format the categorization prompt."""
    return CATEGORIZE_FLAKINESS_PROMPT.format(
        test_name=test_name,
        error_type=error_type,
        error_message=error_message,
        divergence_type=divergence_type or "Unknown",
    )


def format_explanation_prompt(
    test_name: str,
    file_path: str,
    category: str,
    divergence_type: str,
    evidence: str,
) -> str:
    """Format the explanation prompt."""
    return EXPLAIN_ROOT_CAUSE_PROMPT.format(
        test_name=test_name,
        file_path=file_path,
        category=category,
        divergence_type=divergence_type,
        evidence=evidence,
    )


def format_fix_recommendations_prompt(
    root_cause: str,
    category: str,
    file_path: str,
    line_numbers: str,
    code_context: str,
) -> str:
    """Format the fix recommendations prompt."""
    return GENERATE_FIX_RECOMMENDATIONS_PROMPT.format(
        root_cause=root_cause,
        category=category,
        file_path=file_path,
        line_numbers=line_numbers,
        code_context=code_context,
    )
