"""Filter Tier 1 false positives using LLM code analysis."""

from rewardprobe.tier2.code_analyzer import CodeAnalysis
from rewardprobe.types import Finding

# Attacks that only make sense for CORRECTNESS functions
_CORRECTNESS_ONLY_ATTACKS = {
    "ground_truth",
    "signal_variance",
    "echo_prompt",
    "constant_output",
    "format_only",
    "common_prefix",
    "answer_in_reasoning",
}

# Attacks that only make sense for functions that CHECK CONTENT (not length/auxiliary)
_CONTENT_CHECKING_ATTACKS = {
    "empty",
    "whitespace",
    "random_tokens",
}

# Attacks relevant for format-checking functions
_FORMAT_ATTACKS = {
    "multiple_tags",
    "regex_greediness",
    "malformed_xml",
    "duplicate_answers",
    "format_variation",
}


def filter_tier1_findings(
    findings: list[Finding],
    analyses: dict[str, CodeAnalysis],
) -> tuple[list[Finding], list[Finding]]:
    """Filter Tier 1 findings based on LLM code analysis.

    Returns (kept_findings, removed_findings).
    """
    kept = []
    removed = []

    for finding in findings:
        # Try to match finding to a code analysis by fn name in recommendation
        analysis = None
        for fn_name, a in analyses.items():
            if fn_name in finding.recommendation:
                analysis = a
                break

        if analysis is None:
            kept.append(finding)
            continue

        fn_type = analysis.function_type.lower()
        eb = analysis.expected_behavior
        attack = finding.attack

        should_remove = False

        # Rule 1: Correctness-only attacks on non-correctness functions
        if attack in _CORRECTNESS_ONLY_ATTACKS and not eb.checks_answer_correctness:
            should_remove = True

        # Rule 2: Content-checking attacks on auxiliary functions
        # Only remove SCORE findings, not CRASH findings
        if attack in _CONTENT_CHECKING_ATTACKS and fn_type == "auxiliary":
            if finding.error is None:  # Score finding, not crash
                should_remove = True

        # Rule 3: Format attacks on non-format functions
        if attack in _FORMAT_ATTACKS and not eb.checks_output_format and fn_type == "auxiliary":
            should_remove = True

        if should_remove:
            removed.append(finding)
        else:
            kept.append(finding)

    return kept, removed
