import torch
from typing import List


def reconstruct_encoding_constraints(
    x: torch.Tensor, feature_pos: List[int], binary_cat: bool
) -> torch.Tensor:
    """
    Reconstructing one-hot-encoded data, such that its values are either 0 or 1,
    and features do not contradict (e.g., sex_female = 1, sex_male = 1)

    Parameters
    ----------
    x: instance where we want to reconstruct categorical constraints
    feature_pos: list with positions of categorical features in x
    binary_cat: If true, categorical datas are encoded with drop_if_binary

    Returns
    -------
    Tensor with reconstructed constraints
    """
    x_enc = x.clone()

    if binary_cat:
        for pos in feature_pos:
            x_enc[:, pos] = torch.round(x_enc[:, pos])
    else:
        binary_pairs = list(zip(feature_pos[:-1], feature_pos[1:]))[0::2]
        for pair in binary_pairs:
            # avoid overwritten inconsistent results
            temp = (x_enc[:, pair[0]] >= x_enc[:, pair[1]]).float()

            x_enc[:, pair[1]] = (x_enc[:, pair[0]] < x_enc[:, pair[1]]).float()
            x_enc[:, pair[0]] = temp

            if (x_enc[:, pair[0]] == x_enc[:, pair[1]]).any():
                raise ValueError(
                    "Reconstructing encoded features lead to an error. Feature {} and {} have the same value".format(
                        pair[0], pair[1]
                    )
                )

    return x_enc