package com.lingyue.graph.service;

import com.lingyue.graph.entity.GraphNode;
import com.lingyue.graph.entity.GraphRelation;
import com.lingyue.graph.neo4j.Neo4jGraphService;
import com.lingyue.graph.repository.GraphNodeRepository;
import com.lingyue.graph.repository.GraphRelationRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 图数据同步服务
 * 
 * 负责将 PostgreSQL 中的图数据同步到 Neo4j
 * 
 * 同步策略：
 * 1. 实时同步：每次 CRUD 操作后立即同步
 * 2. 批量同步：定时任务或手动触发全量同步
 * 3. 按需同步：查询时如果 Neo4j 无数据则同步
 * 
 * @author lingyue
 * @since 2026-01-21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GraphSyncService {
    
    private final GraphNodeRepository nodeRepository;
    private final GraphRelationRepository relationRepository;
    
    // Neo4j 服务可能不存在（未启用时）
    @Autowired(required = false)
    private Neo4jGraphService neo4jGraphService;
    
    /**
     * 检查 Neo4j 是否可用
     */
    public boolean isNeo4jEnabled() {
        return neo4jGraphService != null;
    }
    
    /**
     * 同步单个节点到 Neo4j
     */
    public void syncNode(GraphNode node) {
        if (!isNeo4jEnabled()) {
            return;
        }
        
        try {
            neo4jGraphService.syncNode(node);
        } catch (Exception e) {
            log.error("同步节点到 Neo4j 失败: nodeId={}, error={}", node.getId(), e.getMessage());
        }
    }
    
    /**
     * 同步单个关系到 Neo4j
     */
    public void syncRelation(GraphRelation relation) {
        if (!isNeo4jEnabled()) {
            return;
        }
        
        try {
            neo4jGraphService.syncRelation(relation);
        } catch (Exception e) {
            log.error("同步关系到 Neo4j 失败: relId={}, error={}", relation.getId(), e.getMessage());
        }
    }
    
    /**
     * 同步文档的所有数据到 Neo4j
     */
    @Async
    public void syncDocument(String documentId) {
        if (!isNeo4jEnabled()) {
            log.debug("Neo4j 未启用，跳过同步");
            return;
        }
        
        log.info("开始同步文档到 Neo4j: documentId={}", documentId);
        
        try {
            // 1. 先删除旧数据
            neo4jGraphService.deleteDocumentGraph(documentId);
            
            // 2. 同步节点
            List<GraphNode> nodes = nodeRepository.findByDocumentId(documentId);
            if (!nodes.isEmpty()) {
                neo4jGraphService.syncNodes(nodes);
            }
            
            // 3. 同步关系
            // 获取所有节点ID
            for (GraphNode node : nodes) {
                List<GraphRelation> relations = relationRepository.findByNodeId(node.getId());
                if (!relations.isEmpty()) {
                    neo4jGraphService.syncRelations(relations);
                }
            }
            
            log.info("文档同步到 Neo4j 完成: documentId={}, nodes={}", documentId, nodes.size());
            
        } catch (Exception e) {
            log.error("同步文档到 Neo4j 失败: documentId={}, error={}", documentId, e.getMessage(), e);
        }
    }
    
    /**
     * 同步用户的所有数据到 Neo4j
     */
    @Async
    public void syncUser(String userId) {
        if (!isNeo4jEnabled()) {
            return;
        }
        
        log.info("开始同步用户数据到 Neo4j: userId={}", userId);
        
        try {
            // 获取用户的所有节点
            List<GraphNode> nodes = nodeRepository.findByUserId(userId);
            if (!nodes.isEmpty()) {
                neo4jGraphService.syncNodes(nodes);
            }
            
            // 同步关系
            for (GraphNode node : nodes) {
                List<GraphRelation> relations = relationRepository.findByNodeId(node.getId());
                if (!relations.isEmpty()) {
                    neo4jGraphService.syncRelations(relations);
                }
            }
            
            log.info("用户数据同步到 Neo4j 完成: userId={}, nodes={}", userId, nodes.size());
            
        } catch (Exception e) {
            log.error("同步用户数据到 Neo4j 失败: userId={}, error={}", userId, e.getMessage(), e);
        }
    }
    
    /**
     * 全量同步（谨慎使用）
     */
    public void fullSync() {
        if (!isNeo4jEnabled()) {
            log.warn("Neo4j 未启用，无法执行全量同步");
            return;
        }
        
        log.info("开始全量同步到 Neo4j...");
        
        // 初始化索引
        neo4jGraphService.initializeIndexes();
        
        // TODO: 分批查询所有节点和关系进行同步
        // 这里需要添加分页逻辑以避免内存溢出
        
        log.info("全量同步完成");
    }
    
    /**
     * 删除文档在 Neo4j 中的数据
     */
    public void deleteDocumentFromNeo4j(String documentId) {
        if (!isNeo4jEnabled()) {
            return;
        }
        
        try {
            neo4jGraphService.deleteDocumentGraph(documentId);
        } catch (Exception e) {
            log.error("从 Neo4j 删除文档失败: documentId={}, error={}", documentId, e.getMessage());
        }
    }
}
