"""fix_registry.py — Static deterministic failure→fix rules.

Priority order: first match wins. More specific entries before general ones.
"""
from .agent import FeedbackFix, FeedbackStrategy, RefChanges
from .constants import NEVER_HEAL, SEVERITY_CEILING


FIX_REGISTRY: list[dict] = [
    # Gate 1 — Mechanical (5 entries)
    {
        "gate": "gate_1",
        "category": "anatomy_hands",
        "keywords": ["finger", "hand", "digit", "extra finger", "merged finger", "six finger"],
        "strategy": FeedbackStrategy.ANATOMY_ANCHOR,
        "ref_changes": None,
        "negative_prompt": ["extra fingers", "deformed hands", "fused digits", "six fingers"],
        "confidence": 0.50,
        "auto_injectable": True,
    },
    {
        "gate": "gate_1",
        "category": "anatomy_limbs",
        "keywords": ["limb", "arm", "leg", "extra arm", "extra leg", "three arm", "four arm", "duplicated"],
        "strategy": FeedbackStrategy.ANATOMY_ANCHOR,
        "ref_changes": None,
        "negative_prompt": ["extra limbs", "multiple arms", "extra legs", "duplicated limbs"],
        "confidence": 0.45,
        "auto_injectable": True,
    },
    {
        "gate": "gate_1",
        "category": "anatomy_face_merge",
        "keywords": ["face merge", "two face", "double face", "face blend", "merged face", "multiple face"],
        "strategy": FeedbackStrategy.FACE_ISOLATION,
        "ref_changes": RefChanges(face_crop_expression_refs=True),
        "negative_prompt": ["multiple faces", "face merge", "double face", "blended features"],
        "confidence": 0.40,
        "auto_injectable": True,
    },
    {
        "gate": "gate_1",
        "category": "artifacts",
        "keywords": ["artifact", "seam", "warp", "distort", "glitch", "noise", "banding"],
        "strategy": FeedbackStrategy.ANATOMY_ANCHOR,
        "ref_changes": None,
        "negative_prompt": ["artifacts", "seams", "warping", "digital distortion", "glitch"],
        "confidence": 0.35,
        "auto_injectable": True,
    },
    {
        "gate": "gate_1",
        "category": "background_contamination",
        "keywords": ["background", "contamination", "bleed", "spill", "background person", "crowd"],
        "strategy": FeedbackStrategy.ENVIRONMENT_REINFORCE,
        "ref_changes": RefChanges(boost_scene_ref=True),
        "negative_prompt": ["background people", "crowd", "extra person", "background contamination"],
        "confidence": 0.40,
        "auto_injectable": False,
    },

    # Gate 2A — Identity (3 entries)
    {
        "gate": "gate_2a",
        "category": "identity_drift",
        "keywords": [
            "drift", "inconsisten", "different face", "changed", "not matching", "identity",
            "face shape", "facial feature", "facial features", "eye color", "eye shape",
            "nose shape", "different facial", "facial structure", "bone structure",
            "doesn't match the hero", "doesn't match the reference",
        ],
        "strategy": FeedbackStrategy.REF_PRUNE_AND_ANCHOR,
        "ref_changes": RefChanges(keep_only=["hero"], grayscale_expression_refs=True),
        "negative_prompt": ["different person", "changed face", "inconsistent features"],
        "confidence": 0.45,
        "auto_injectable": False,
    },
    {
        "gate": "gate_2a",
        "category": "identity_wrong_person",
        "keywords": ["wrong person", "different person", "not the character", "wrong identity"],
        "strategy": None,  # Never-feedback — sentinel
        "ref_changes": None,
        "negative_prompt": [],
        "confidence": 0.0,
        "auto_injectable": False,
    },
    {
        "gate": "gate_2a",
        "category": "wardrobe",
        "keywords": [
            "wardrobe", "clothing", "outfit", "shirt", "jacket", "pants", "dress",
            "costume", "wrong clothes",
            "color wrong", "doesn't match spec", "wrong jacket", "wrong shirt",
            "wearing", "clothes",
        ],
        "strategy": FeedbackStrategy.WARDROBE_EXAGGERATION,
        "ref_changes": None,
        "negative_prompt": ["wrong clothing", "incorrect outfit", "mismatched wardrobe"],
        "confidence": 0.40,
        "auto_injectable": False,
    },

    # Gate 2B — Scene Consistency (3 entries)
    {
        "gate": "gate_2b",
        "category": "lighting",
        "keywords": [
            "lighting", "shadow", "highlight", "exposure", "dark", "bright", "contrast",
            "light direction",
            "intensity", "direction wrong", "shadows wrong", "wrong highlight",
        ],
        "strategy": FeedbackStrategy.LIGHTING_LOCK,
        "ref_changes": None,
        "negative_prompt": ["inconsistent lighting", "wrong shadows", "flat lighting"],
        "confidence": 0.35,
        "auto_injectable": False,
    },
    {
        "gate": "gate_2b",
        "category": "environment",
        "keywords": [
            "environment", "location", "background", "setting", "scene", "wrong place",
            "wrong location",
            "doesn't match location", "background wrong", "wrong environment",
        ],
        "strategy": FeedbackStrategy.ENVIRONMENT_REINFORCE,
        "ref_changes": RefChanges(boost_scene_ref=True),
        "negative_prompt": ["wrong location", "incorrect setting", "mismatched environment"],
        "confidence": 0.35,
        "auto_injectable": False,
    },
    {
        "gate": "gate_2b",
        "category": "style",
        "keywords": ["style", "aesthetic", "tone", "look", "visual style", "cinematic", "color grade"],
        "strategy": FeedbackStrategy.STYLE_ANCHOR,
        "ref_changes": None,
        "negative_prompt": ["inconsistent style", "wrong aesthetic", "mismatched tone"],
        "confidence": 0.30,
        "auto_injectable": False,
    },
]

# Never-feedback shortlist
NEVER_HEAL_CATEGORIES = NEVER_HEAL

# Auto-inject candidates (Gate 1 only)
AUTO_INJECT_CANDIDATES = {
    "anatomy_hands": {
        "prompt_hint": "Each hand has exactly five fingers with natural spacing. No merged or extra digits.",
        "auto_inject_threshold": 3,
    },
    "anatomy_limbs": {
        "prompt_hint": "Human figure with exactly two arms and two legs. No extra or duplicated limbs.",
        "auto_inject_threshold": 3,
    },
    "anatomy_face_merge": {
        "prompt_hint": "Single person visible. One clearly defined face.",
        "auto_inject_threshold": 3,
    },
    "artifacts": {
        "prompt_hint": "Clean, artifact-free image. No seams, warping, or digital distortion.",
        "auto_inject_threshold": 3,
    },
}


def match_fix(verdict, attempt_number: int) -> FeedbackFix | None:
    """Find the best matching fix for a gate verdict.

    On attempt 2, escalates wardrobe from EXAGGERATION to CONTRASTIVE.
    Returns None if no match (triggers LVLM fallback or ICU escalation).
    """
    # Check never-feedback
    failure_cat = getattr(verdict, 'details', {}).get("failure_category", "")
    if failure_cat in NEVER_HEAL_CATEGORIES:
        return None

    severity = getattr(verdict, 'details', {}).get("total_severity", 0)
    if severity > SEVERITY_CEILING:
        return None

    reason_lower = getattr(verdict, 'reason', '').lower()
    gate_name = getattr(verdict, 'gate_name', '')

    for entry in FIX_REGISTRY:
        if entry["strategy"] is None:
            continue
        if not gate_name.startswith(entry["gate"]):
            continue
        if not any(kw in reason_lower for kw in entry["keywords"]):
            continue

        strategy = entry["strategy"]
        # Escalation: wardrobe exaggeration → contrastive on attempt 2
        if strategy == FeedbackStrategy.WARDROBE_EXAGGERATION and attempt_number >= 2:
            strategy = FeedbackStrategy.WARDROBE_CONTRASTIVE

        return FeedbackFix(
            strategy=strategy,
            ref_changes=entry["ref_changes"],
            negative_prompt_additions=list(entry["negative_prompt"]),
            confidence=entry["confidence"],
            rationale=f"Registry match: {entry['category']} (attempt {attempt_number})",
            diagnosis_cost=0.00,
        )

    return None
