'''
根据标签和类型来查找对应的符合条件的人、企业、职位
'''
from flask import current_app
from configs.connections import connect_graph

def similar_seeker(label):
    try:
        query = """        
            WITH $Label AS target_labels
            UNWIND target_labels AS target_label
            MATCH (jl:seekerLabel)
            WITH target_label, jl, apoc.text.distance(target_label, jl.name) AS distance
            WITH target_label, jl, 1.0 / (1.0 + distance) AS similarity
            WHERE similarity > 0.5
            WITH target_label, jl, similarity
            MATCH (j:seeker)-[:connection]->(jl)
            WITH j, similarity
            ORDER BY similarity DESC
            WITH DISTINCT j, similarity
            RETURN j.uniqueId AS ids_list
            ORDER BY similarity DESC
            """
        result = connect_graph.run(query, Label=label)
        if result:
            return [record['ids_list'] for record in result]  # 提取所有 uniqueId
        else:
            return []
    except Exception as e:
        current_app.logger.error(f'similar_seeker error: {e}')
        return str(e)


def draw_graph():
    try:
        # 先判断图谱中是否存在投影图，不存在直接drop会报错
        create_query = """CALL gds.graph.exists('jobGraph') YIELD exists
                              RETURN CASE exists WHEN true THEN 1 ELSE 0 END as graphExists"""
        result = connect_graph.run(create_query).evaluate()
        if result == 0:
            create_query = """
                // 创建图投影
                CALL gds.graph.project(
                    'jobGraph',
                    ['job', 'jobLabel'],
                    {
                        r: {
                            type: 'connection',
                            orientation: 'UNDIRECTED'
                        }
                    }
                )
                """
            connect_graph.run(create_query)
    except Exception as e:
        current_app.logger.error(f'draw_graph error: {e}')
        return str(e)


# 职位详情推荐类似的职位
def similar_job(uniqueid,start,end):
    try:
        if uniqueid:
            query = f""" 
            // 计算 Jaccard 相似度
            CALL gds.nodeSimilarity.stream('jobGraph', {{
                similarityCutoff: 0.0,
                topK: 10
            }})
            YIELD node1, node2, similarity
            WITH gds.util.asNode(node1) AS node1, gds.util.asNode(node2) AS node2, similarity
            WHERE node1.uniqueId = $Id AND node2.uniqueId <> $Id
            WITH node2.uniqueId AS job_id, node2.name AS job_name, similarity
            ORDER BY similarity DESC
            // 返回最相似的 job 节点
            //with count(job_id) as total,collect(job_id) as job_ids
            with collect(job_id) as job_ids
            return job_ids[{start}..{end}] as jobIds
            """
            result = connect_graph.run(query, Id=uniqueid).evaluate()
            if result:
                need_list = default_job()
                return result + need_list[:10 - len(result)]
            else:
                return default_job()
        else:
            return default_job()
    except Exception as e:
        current_app.logger.error(f'similar_job error: {e}')
        return default_job()


# 职位详情推荐类似的职位
def home_job(uniqueid,start,end):
    try:
        if uniqueid:
            query = f""" 
            // 1. 使用索引查找 seeker 节点
             MATCH (s:seeker {{uniqueId: $Id}})-[:connection]->(sl:seekerLabel)
            
            // 2. 获取 jobLabel 节点并提前过滤
            WITH s, sl
            MATCH (jl:jobLabel)
            WHERE jl.name STARTS WITH sl.name OR sl.name STARTS WITH jl.name  // 进一步过滤
            
            // 3. 计算jobLabel 和 seekerLabel 之间的 Levenshtein 距离
            WITH s, sl, jl, apoc.text.levenshteinDistance(jl.name, sl.name) AS distance
            
            // 4. 找到距离最小的 jobLabel
            ORDER BY distance ASC
            WITH s, sl, collect({{jl: jl, distance: distance}}) AS jobLabels
            WITH s, sl, jobLabels[0].jl AS closestJl, jobLabels[0].distance AS min_distance
            
            // 5. 获取 job 节点
            MATCH (j:job)-[:connection]->(closestJl)
            
            // 6. 返回 job 的 id，并限制结果数量
            WITH s, toString(j.uniqueId) AS jobId
            with collect(DISTINCT jobId) AS jobIds
            RETURN jobIds[{start}..{end}] AS jobIds
            """
            result = connect_graph.run(query,Id = uniqueid).evaluate()
            if result:
                need_list = default_job()
                return result + need_list[:10-len(result)]
            else:
                return default_job()
        else:
            return default_job()
    except Exception as e:
        current_app.logger.error(f'home_job error: {e}')
        return default_job()


def default_job():
    try:
        query = """
        MATCH (n:job)-[r:connection]-(m:jobLabel)
        WITH n, COUNT(m) AS num_connections
        ORDER BY num_connections DESC
        LIMIT 10
        RETURN collect(n.uniqueId) AS job_ids
        """
        result = connect_graph.run(query).evaluate()
        return result
    except Exception as e:
        current_app.logger.error(f'default_job error: {e}')
        return []

def draw_person_graph():
    try:
        # 先判断图谱中是否存在投影图，不存在直接drop会报错
        create_query = """CALL gds.graph.exists('personGraph') YIELD exists
                                 RETURN CASE exists WHEN true THEN 1 ELSE 0 END as graphExists"""
        result = connect_graph.run(create_query).evaluate()
        if result == 0:
            create_query = """
                   // 创建图投影
                   CALL gds.graph.project(
                       'personGraph',
                       ['seeker', 'seekerLabel'],
                       {
                           r: {
                               type: 'connection',
                               orientation: 'UNDIRECTED'
                           }
                       }
                   )
                   """
            connect_graph.run(create_query)
    except Exception as e:
        current_app.logger.error(f'draw_graph error: {e}')
        return str(e)


def home_person(uniqueid,start,end):
    try:
        if uniqueid:
            query = f""" 
            // 1. 使用索引查找 job 节点
            MATCH (j:job {{uniqueId: $Id}})-[:connection]->(jl:jobLabel)
            
            // 2. 获取 seekerLabel 节点并提前过滤
            WITH j, jl
            MATCH (sl:seekerLabel)
            WHERE sl.name STARTS WITH jl.name OR jl.name STARTS WITH sl.name  // 进一步过滤
            
            // 3. 计算jobLabel 和 seekerLabel 之间的 Levenshtein 距离
            WITH j, jl, sl, apoc.text.levenshteinDistance(jl.name, sl.name) AS distance
            
            // 4. 找到距离最小的 seekerLabel
            ORDER BY distance ASC
            WITH j, jl, collect({{sl: sl, distance: distance}}) AS seekerLabels
            WITH j, jl, seekerLabels[0].sl AS closestSl, seekerLabels[0].distance AS min_distance
            
            // 5. 获取 seeker 节点
            MATCH (s:seeker)-[:connection]->(closestSl)
            
            // 6. 返回 seeker 的 id，并限制结果数量
            WITH j, toString(s.uniqueId) AS seekerId
            with collect(DISTINCT seekerId) AS seekerIds
            RETURN seekerIds[{start}..{end}] AS seekerIds
            """
            result = connect_graph.run(query,Id = uniqueid).evaluate()
            if result:
                need_list = default_person()
                return result + need_list[:10 - len(result)]
            else:
                return default_person()
        else:
            return default_person()
    except Exception as e:
        current_app.logger.error(f'home_job error: {e}')
        return default_person()

def default_person():
    try:
        query = """
        MATCH (n:seeker)-[r:connection]-(m:seekerLabel)
        WITH n, COUNT(m) AS num_connections
        ORDER BY num_connections DESC
        LIMIT 10
        RETURN collect(n.uniqueId) AS seeker_ids
        """
        result = connect_graph.run(query).evaluate()
        return result
    except Exception as e:
        current_app.logger.error(f'default_person error: {e}')
        return []