"""Framework overlap upsell hints per SPEC-004 / §A.2.3.3."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from complyform.core.assessor.control_matcher import Finding
    from complyform.core.profiles.models import CrossMappingIndex


def compute_overlap_hints(
    findings: list[Finding],
    cross_mapping_index: CrossMappingIndex,
    user_remediate_frameworks: frozenset[str],
    all_frameworks: frozenset[str],
) -> list[dict[str, object]] | None:
    """Compute upsell-oriented overlap hints.

    Returns list of dicts or None if no opportunities.
    Only frameworks where overlap > 30%, max 5, sorted by overlap_pct desc.
    Excludes frameworks the user already has.
    """
    assessed_controls: dict[str, set[str]] = {}
    passing_controls: dict[str, set[str]] = {}

    for f in findings:
        if f.status in ("PASS", "FAIL"):
            assessed_controls.setdefault(f.framework, set()).add(f.control_id)
            if f.status == "PASS":
                passing_controls.setdefault(f.framework, set()).add(f.control_id)

    hints: list[dict[str, object]] = []

    for target_fw in all_frameworks:
        if target_fw in user_remediate_frameworks:
            continue

        shared = 0
        passing_shared = 0

        for mapping in cross_mapping_index.mappings:
            for src_fw, src_controls in assessed_controls.items():
                if (
                    mapping.source_framework == src_fw
                    and mapping.source_control in src_controls
                    and mapping.target_framework == target_fw
                ):
                    shared += 1
                    if mapping.source_control in passing_controls.get(src_fw, set()):
                        passing_shared += 1

        if shared == 0:
            continue

        total_assessed = sum(len(ctrls) for ctrls in assessed_controls.values())
        if total_assessed == 0:
            continue

        overlap_pct = round((shared / total_assessed) * 100, 1)
        if overlap_pct <= 30.0:
            continue

        hints.append(
            {
                "framework": target_fw,
                "shared_controls": shared,
                "passing_shared": passing_shared,
                "overlap_pct": overlap_pct,
            }
        )

    if not hints:
        return None

    def _overlap_key(h: dict[str, object]) -> float:
        v = h.get("overlap_pct", 0)
        return float(v) if isinstance(v, (int, float)) else 0.0

    hints.sort(key=_overlap_key, reverse=True)
    return hints[:5]
