"""Per-cluster conflict critics with hard evidence and image caps."""

from typing import Dict, List

from backend import config
from backend.agents.base import AgentResult, AgentScope, AgentUsage, failure
from backend.llm import call_json
from backend.pipeline.conflict_checker import _evidence_block, _valid_conflict
from backend.prompts import CONFLICT_SYSTEM_PROMPT, CONFLICT_USER_INSTRUCTION


def _as_finding(conflict: Dict, scope_id: str) -> Dict:
    return {
        "issue_id": conflict.get("conflict_id") or "",
        "source_stage": "conflict",
        "category": conflict.get("category") or "uncategorized",
        "severity": conflict.get("severity") or "medium",
        "confidence": conflict.get("confidence") or "medium",
        "location": conflict.get("location") or "",
        "disciplines": conflict.get("disciplines") or [],
        "sheets": conflict.get("sheets") or [],
        "description": conflict.get("description") or "",
        "evidence": conflict.get("evidence") or [],
        "recommended_resolution": conflict.get("recommended_resolution") or "",
        "code_reference": None,
        "agent": "conflict_critic",
        "scope_id": scope_id,
    }


class ConflictCriticAgent:
    name = "conflict_critic"

    def __init__(self, usage: AgentUsage) -> None:
        self.usage = usage

    def run(self, scope: AgentScope) -> AgentResult:
        try:
            cluster = dict(scope.payload["cluster"])
            cluster["assertions"] = (
                cluster.get("assertions") or []
            )[:config.AGENT_CLUSTER_MAX_ASSERTIONS]
            page_to_b64: Dict[int, str] = scope.payload.get("page_to_b64") or {}
            images: List[str] = []
            for page_number in (
                cluster.get("page_numbers") or []
            )[:config.AGENT_CONFLICT_MAX_IMAGES]:
                if page_to_b64.get(page_number):
                    images.append(page_to_b64[page_number])
            instruction = (
                CONFLICT_USER_INSTRUCTION
                .replace("{location}", cluster.get("location") or "")
                .replace("{evidence}", _evidence_block(cluster))
            )
            parsed = call_json(
                system_prompt=CONFLICT_SYSTEM_PROMPT,
                user_text=instruction,
                images_b64=images,
                max_tokens=config.REASON_MAX_TOKENS,
                model=config.AGENT_CONFLICT_MODEL,
                usage_tracker=self.usage,
                usage_stage="agent.conflict",
                reasoning_effort=config.EXTRACT_REASONING_EFFORT or None,
                reasoning_max_tokens=config.EXTRACT_REASONING_MAX_TOKENS or None,
            )
            candidates = parsed if isinstance(parsed, list) else (
                parsed.get("conflicts") if isinstance(parsed, dict) else []
            )
            findings = []
            for candidate in candidates or []:
                conflict = _valid_conflict(candidate, cluster)
                if conflict:
                    findings.append(_as_finding(conflict, scope.scope_id))
            return AgentResult(scope_id=scope.scope_id, artifacts=findings)
        except Exception as exc:
            return failure(scope, exc)
