"""Tests para align_relations_to_entities."""

import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", ".."))

from python.functions.datascience.align_relations_to_entities import align_relations_to_entities


def _t(head, head_type, relation, tail, tail_type):
    return {
        "head": head,
        "head_type": head_type,
        "type": relation,
        "tail": tail,
        "tail_type": tail_type,
    }


def test_match_exacto_case_insensitive_resuelve_correctamente():
    triplets = [_t("pablo isla", "per", "employer", "inditex", "org")]
    entities = ["Pablo Isla", "Inditex"]
    result = align_relations_to_entities(triplets, entities)
    assert len(result) == 1
    assert result[0]["from"] == "Pablo Isla"
    assert result[0]["to"] == "Inditex"
    assert result[0]["kind"] == "employer"


def test_substring_entity_en_span_del_head():
    # mREBEL emite "esta en Bilbao" pero la entidad es "Bilbao"
    triplets = [_t("esta en Bilbao", "loc", "located in", "Espana", "loc")]
    entities = ["Bilbao", "Espana"]
    result = align_relations_to_entities(triplets, entities)
    assert len(result) == 1
    assert result[0]["from"] == "Bilbao"
    assert result[0]["to"] == "Espana"


def test_substring_span_dentro_del_nombre_de_entidad():
    # El span "Santander" esta contenido en el entity name "Banco Santander"
    triplets = [_t("Santander", "org", "owns", "Openbank", "org")]
    entities = ["Banco Santander", "Openbank"]
    result = align_relations_to_entities(triplets, entities)
    assert len(result) == 1
    assert result[0]["from"] == "Banco Santander"
    assert result[0]["to"] == "Openbank"


def test_gana_nombre_de_entidad_mas_largo_en_ambiguedad():
    # Dos entidades: "Madrid" y "Comunidad de Madrid". El span "Madrid" deberia
    # preferir "Comunidad de Madrid" si ese es el mas largo y contiene "madrid".
    # En la logica actual: substring bidireccional, gana el primero de names_by_len
    # (que ordena DESC por len). "Comunidad de Madrid" es mas largo y su lower
    # contiene "madrid", asi que gana.
    triplets = [_t("Madrid", "loc", "capital of", "Espana", "loc")]
    entities = ["Madrid", "Comunidad de Madrid", "Espana"]
    result = align_relations_to_entities(triplets, entities)
    assert len(result) == 1
    # El exacto case-insensitive resuelve "Madrid" -> "Madrid" directamente
    # (antes que la busqueda substring). Verificamos que no rompe y que
    # from/to son valores de entities.
    assert result[0]["from"] in entities
    assert result[0]["to"] in entities


def test_triplet_sin_match_se_descarta():
    triplets = [_t("Unknown Entity", "per", "works for", "Another Unknown", "org")]
    entities = ["Pablo Isla", "Inditex"]
    result = align_relations_to_entities(triplets, entities)
    assert result == []


def test_triplet_con_head_igual_tail_se_descarta_self_loop():
    triplets = [_t("Inditex", "org", "owns", "Inditex", "org")]
    entities = ["Inditex", "Zara"]
    result = align_relations_to_entities(triplets, entities)
    assert result == []


def test_lista_triplets_vacia_retorna_vacia():
    result = align_relations_to_entities([], ["Pablo Isla", "Inditex"])
    assert result == []


def test_lista_entity_names_vacia_retorna_vacia():
    triplets = [_t("Pablo Isla", "per", "employer", "Inditex", "org")]
    result = align_relations_to_entities(triplets, [])
    assert result == []


def test_multiples_triplets_con_mezcla_de_matches_y_descartes():
    triplets = [
        _t("Pablo Isla", "per", "employer", "Inditex", "org"),   # match
        _t("Ghost Entity", "per", "employer", "Inditex", "org"),  # head sin match
        _t("Pablo Isla", "per", "employer", "Pablo Isla", "per"), # self-loop
    ]
    entities = ["Pablo Isla", "Inditex"]
    result = align_relations_to_entities(triplets, entities)
    assert len(result) == 1
    assert result[0]["from"] == "Pablo Isla"
    assert result[0]["to"] == "Inditex"
