"""Pure classification and action building for Document Reconciliation v2 backfills."""
from __future__ import annotations

from collections import Counter, defaultdict
from typing import Any, Dict, Iterable, List


def select_complete_group_batch(rows: Iterable[Dict[str, Any]], batch_size: int,
                                resume_from: tuple[str, str] | None = None) -> List[Dict[str, Any]]:
    """Reference group paginator used by tests and non-SQL callers."""
    ordered = sorted(rows, key=lambda row: (str(row["opportunity_id"]),
        str(row["document_kind"]), str(row.get("created_at") or ""), str(row["id"])))
    keys = []
    for row in ordered:
        key = (str(row["opportunity_id"]), str(row["document_kind"]))
        if resume_from and key <= resume_from:
            continue
        if key not in keys:
            if len(keys) >= max(1, int(batch_size)):
                continue
            keys.append(key)
    selected = set(keys)
    return [row for row in ordered if (str(row["opportunity_id"]), str(row["document_kind"])) in selected]


def _document_identity(row: Dict[str, Any]) -> str:
    return str(row.get("external_id") or row.get("document_number") or row["id"])


def _is_cancelled(row: Dict[str, Any]) -> bool:
    return str(row.get("status") or "").upper() in {"CANCELLED", "CANCELED"}


def classify_group(rows: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """Classify documents from one opportunity and document-kind group."""
    active_primaries = [
        row
        for row in rows
        if bool(row.get("is_primary"))
        and str(row.get("role") or "").lower() in {"current", "accepted"}
    ]
    duplicate_identity = len({_document_identity(row) for row in rows}) < len(rows)
    ambiguous = len(active_primaries) > 1 or duplicate_identity
    actions = []
    for row in rows:
        role = str(row.get("role") or "").lower()
        evidence = row.get("payload") if isinstance(row.get("payload"), dict) else {}
        if ambiguous:
            relationship, reason = "REVIEW_REQUIRED", "multiple primaries or duplicate association"
        elif _is_cancelled(row) and row in active_primaries:
            relationship, reason = "REVIEW_REQUIRED", "cancelled document was inferred primary"
        elif len(active_primaries) == 1 and row["id"] == active_primaries[0]["id"]:
            relationship, reason = "PRIMARY", "single unambiguous legacy primary"
        elif role == "historical":
            relationship, reason = "HISTORICAL", "explicit legacy historical role"
        elif role in {"related", "accepted"}:
            relationship, reason = "SECONDARY", "explicit non-primary related/accepted role"
        elif role == "detached" and any(
            evidence.get(key)
            for key in ("manual_unlinked_from_opportunity_id", "removed_reason", "detached_evidence")
        ):
            relationship, reason = "REMOVED", "explicit legacy detach evidence"
        else:
            relationship, reason = "REVIEW_REQUIRED", "legacy evidence is not unambiguous"
        actions.append(
            {
                **row,
                "relationship": relationship,
                "decision_reason": reason,
                "cancelled": _is_cancelled(row),
            }
        )
    return actions


def build_backfill_result(
    rows: Iterable[Dict[str, Any]],
    *,
    lines_without_document: int = 0,
    documents_in_multiple_opportunities: int = 0,
) -> Dict[str, Any]:
    """Build backfill actions and summary from already-loaded document rows."""
    groups: Dict[tuple, List[Dict[str, Any]]] = defaultdict(list)
    for row in rows:
        groups[(row["opportunity_id"], row["document_kind"])].append(row)

    actions = [action for group in groups.values() for action in classify_group(group)]
    counts = Counter(action["relationship"] for action in actions)
    current_total = sum(
        float(action.get("total_amount") or action.get("amount") or 0) for action in actions
    )
    primary_total = sum(
        float(action.get("total_amount") or action.get("amount") or 0)
        for action in actions
        if action["relationship"] == "PRIMARY"
    )
    duplicates = sum(
        1
        for group in groups.values()
        if len({_document_identity(row) for row in group}) < len(group)
    )
    return {
        "summary": {
            "total_opportunities": len({action["opportunity_id"] for action in actions}),
            "total_documents": len(actions),
            "auto_PRIMARY": counts["PRIMARY"],
            "auto_SECONDARY": counts["SECONDARY"],
            "auto_HISTORICAL": counts["HISTORICAL"],
            "REVIEW_REQUIRED": counts["REVIEW_REQUIRED"],
            "cancelled": sum(1 for action in actions if action["cancelled"]),
            "duplicates": duplicates,
            "conflicts": counts["REVIEW_REQUIRED"],
            "lines_without_document": lines_without_document,
            "documents_in_multiple_opportunities": documents_in_multiple_opportunities,
            "current_total": current_total,
            "primary_total": primary_total,
        },
        "actions": actions,
    }
