#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""
Gate Feedback — Template functions.

Classifies failure types, extracts changed files, generates anti-pattern
text and corrective constraints from failure context.
"""
from __future__ import annotations

_FAILURE_TYPES = {
    "diff-guard": "diff_guard",
    "smoke-test": "smoke_test",
    "agent-crash": "agent_crash",
    "zero-work": "zero_work",
}


def _classify_failure(gate_failures: list[str]) -> tuple[str, str]:
    """Classify failure type and extract detail from gate failure strings."""
    if not gate_failures:
        return "unknown", "No failure detail"
    raw = gate_failures[0]
    for prefix, ftype in _FAILURE_TYPES.items():
        if raw.startswith(prefix):
            return ftype, raw
    return "unknown", raw


def _extract_top_files(
    post_snapshot: dict[str, tuple[int, int]] | None,
    max_files: int = 3,
) -> list[str]:
    """Extract most-changed files from diff snapshot."""
    if not post_snapshot:
        return []
    scored = []
    for f, (added, removed) in post_snapshot.items():
        scored.append((added + removed, f))
    scored.sort(reverse=True)
    return [f for _, f in scored[:max_files]]


def _generate_anti_pattern(
    failure_type: str,
    detail: str,
    top_files: list[str],
    title: str,
) -> str:
    """Generate natural-language anti-pattern from failure context."""
    short_title = title[:50]
    files_str = ", ".join(top_files[:3]) if top_files else "unknown files"

    templates = {
        "diff_guard": (
            f"Don't modify too many lines in a single task — "
            f"hit limit on '{short_title}' ({files_str})"
        ),
        "smoke_test": (
            f"Smoke test broke after changes to {files_str} "
            f"in task '{short_title}' — {detail[:100]}"
        ),
        "agent_crash": (
            f"Agent crash on task '{short_title}' — "
            f"likely missing context or import error"
        ),
        "zero_work": (
            f"Zero-work detected on '{short_title}' — "
            f"agent produced no file changes"
        ),
    }
    return templates.get(
        failure_type,
        f"Gate failure on '{short_title}': {detail[:100]}",
    )


def _generate_corrective(
    failure_type: str,
    top_files: list[str],
    title: str,
    description: str,
) -> str:
    """Generate corrective constraint for retry."""
    files_str = ", ".join(top_files[:3]) if top_files else "the target files"

    templates = {
        "diff_guard": (
            f"Retry with smaller scope. Split by file: {files_str}. "
            f"Change fewer files per pass."
        ),
        "smoke_test": (
            f"Retry with explicit smoke test validation before completing. "
            f"Focus on: {files_str}"
        ),
        "agent_crash": (
            "Retry with simpler approach. "
            "Read the task description carefully before starting."
        ),
        "zero_work": (
            "Retry — ensure you actually modify files. "
            "Read the task, make changes, verify."
        ),
    }
    return templates.get(
        failure_type,
        f"Retry task '{title[:50]}' with more careful approach.",
    )
