from langchain_community.vectorstores import Neo4jVector
from llm import Embedding
import os
import ssl

# 设置SSL证书路径（解决SSL验证问题）
os.environ["SSL_CERT_FILE"] = ssl.get_default_verify_paths().cafile


# 创建一个适配器类，将我们的Embedding类适配为LangChain所期望的接口
class EmbeddingAdapter:
    def __init__(self, embedding_model):
        self.model = embedding_model

    def embed_query(self, text):
        """LangChain期望的方法名"""
        return self.model.embed(text)

    def embed_documents(self, documents):
        """LangChain可能也期望这个方法"""
        return [self.model.embed(doc) for doc in documents]


# 初始化 Embedding 模型
raw_embeddings = Embedding(url="http://172.20.0.145:9995/v1", api_key="xxx", model_name="bge-m3")
# 使用适配器包装
embeddings = EmbeddingAdapter(raw_embeddings)

url = "bolt://172.20.0.145:7687"
username = "neo4j"
password = "password"

# 定义要搜索的节点标签
node_labels = [
    "ProjectDivisionSet",
    "ProjectDivisionTree",
    "ProjectDivisionItem",
    # "ProjectQuantity",  # 注意：这将匹配带有ProjectQuantity标签的节点
    # "Quota",
    # "MainMaterial",
    # "Equipment",
    # "MaterialOrEquipment",
    # "FeeTableTemplateSet",
    # "FeeTableTemplateItem",
    # "FeeCollection",
    # "FeeScheduleSet",
    # "FeeScheduleItem",
    # "Fee",
]

# 构建 Cypher 条件字符串
where_label_clause = " OR ".join([f"n:{label}" for label in node_labels])

# 自定义检索查询
retrieval_query = f"""
MATCH (n)
WHERE ({where_label_clause})
  AND n.name IS NOT NULL
  AND n.embedding IS NOT NULL
WITH n, reduce(dot = 0.0, i IN range(0, size(n.embedding)-1) | 
    dot + n.embedding[i] * $embedding[i]) / 
    (sqrt(reduce(norm = 0.0, i IN range(0, size(n.embedding)-1) | 
        norm + n.embedding[i] * n.embedding[i])) * 
     sqrt(reduce(norm = 0.0, i IN range(0, size($embedding)-1) | 
        norm + $embedding[i] * $embedding[i]))) AS score
RETURN n.name AS text,
       score,
       {{
           labels: labels(n),
           metadata: n
       }} AS metadata
ORDER BY score DESC LIMIT 5
"""

# 初始化 VectorStore，使用自定义检索查询
vectorstore = Neo4jVector.from_existing_index(
    embedding=embeddings,
    url=url,
    username=username,
    password=password,
    index_name="entity_embedding_index_0",
    embedding_node_property="embedding",
    retrieval_query=retrieval_query,
)


def search_knowledge_graph(query, k=5):
    """搜索知识图谱中与查询最相似的节点"""
    print(f"\n执行查询: '{query}'")

    try:
        # 使用标准查询
        results = vectorstore.similarity_search_with_score(query, k=k)

        print(f"找到 {len(results)} 个相关节点:")
        for i, (doc, score) in enumerate(results):
            print(f"{i+1}. {doc.page_content} (相似度: {score:.4f})")
            if hasattr(doc, "metadata") and doc.metadata:
                print(f"   元数据: {doc.metadata}")

        return results
    except Exception as e:
        print(f"搜索出错: {e}")
        return []


# 示例查询
search_knowledge_graph("土建工程", k=5)
