"""Post-filtrado tipado de relaciones: descarta pares con tipos incompatibles."""

from __future__ import annotations


def filter_relations_by_entity_types(
    relations: dict,
    name_to_type: dict,
    allowed: dict,
) -> tuple[list, list]:
    """Filter relations by allowed (head_type, tail_type) per relation kind.

    Validates that each (head, tail) pair in a relation has the expected entity
    types. Relations with unknown types (not in name_to_type) are dropped when
    the relation_type appears in allowed.

    Args:
        relations: Dict mapping rel_type -> list of (head_name, tail_name) tuples.
                   E.g. {"president_of": [("Carlos Torres", "BBVA")], ...}
        name_to_type: Dict mapping lowercased entity name -> entity type.
                      E.g. {"carlos torres": "person", "bbva": "organization"}
        allowed: Dict mapping rel_type -> (allowed_head_types, allowed_tail_types).
                 Each value is a tuple/list of two lists of strings.
                 If a rel_type is NOT in allowed, all its pairs are kept.
                 E.g. {"president_of": (["person"], ["organization"])}

    Returns:
        Tuple (kept, dropped) where each is a list of dicts:
        {"from": str, "kind": str, "to": str, "head_type": str|None, "tail_type": str|None}
    """
    kept: list[dict] = []
    dropped: list[dict] = []

    for rt, pairs in relations.items():
        rule = allowed.get(rt)
        for h, t in pairs:
            ht = name_to_type.get(h.lower().strip())
            tt = name_to_type.get(t.lower().strip())
            row = {"from": h, "kind": rt, "to": t, "head_type": ht, "tail_type": tt}
            if rule is None:
                kept.append(row)
            else:
                head_ok, tail_ok = rule
                if ht in head_ok and tt in tail_ok:
                    kept.append(row)
                else:
                    dropped.append(row)

    return kept, dropped
