# -*- coding: utf-8 -*-
"""
关系构建器
负责构建非遗项目与深层实体之间的关系
"""

import json
import logging
from typing import Dict, List, Any, Optional
from pathlib import Path
import yaml


class RelationshipBuilder:
    """关系构建器"""

    def __init__(self, ontology_file: str):
        """
        初始化关系构建器

        Args:
            ontology_file: 本体配置文件路径
        """
        # 加载本体配置
        with open(ontology_file, 'r', encoding='utf-8') as f:
            self.ontology = yaml.safe_load(f)

        self.logger = logging.getLogger(__name__)

        # 关系注册表：用于去重
        self.relationship_registry = set()

        self.logger.info("RelationshipBuilder初始化完成")

    def build_relationship(
        self,
        source_id: str,
        target_id: str,
        rel_type: str,
        properties: Dict[str, Any] = None
    ) -> Optional[Dict[str, Any]]:
        """
        构建单个关系

        Args:
            source_id: 源实体ID
            target_id: 目标实体ID
            rel_type: 关系类型
            properties: 关系属性

        Returns:
            关系字典，如果验证失败返回None
        """
        # 验证关系类型
        if rel_type not in self.ontology['relationship_types']:
            self.logger.warning(f"未知关系类型: {rel_type}")
            return None

        # 验证ID不为空
        if not source_id or not target_id:
            self.logger.error(f"关系ID不能为空: source={source_id}, target={target_id}")
            return None

        # 生成关系唯一键（用于去重）
        rel_key = f"{source_id}-{target_id}-{rel_type}"

        # 检查是否重复
        if rel_key in self.relationship_registry:
            self.logger.debug(f"关系已存在，跳过: {rel_key}")
            return None

        # 添加到注册表
        self.relationship_registry.add(rel_key)

        # 构建关系
        relationship = {
            'source': source_id,
            'target': target_id,
            'type': rel_type,
            'properties': json.dumps(properties or {}, ensure_ascii=False)
        }

        return relationship

    def build_relationships_from_extraction(
        self,
        project_id: str,
        extraction_result: Dict[str, Any],
        entity_id_map: Dict[str, str]
    ) -> List[Dict[str, Any]]:
        """
        从抽取结果构建关系

        Args:
            project_id: 项目ID
            extraction_result: LLM抽取结果
            entity_id_map: 实体文本到ID的映射

        Returns:
            关系列表
        """
        relationships = []

        if not extraction_result or 'relationships' not in extraction_result:
            return relationships

        for rel in extraction_result['relationships']:
            # 获取源实体（应该是项目ID）
            source_entity = rel.get('source_entity', '')

            # 验证源实体是否匹配当前项目
            if source_entity != project_id:
                self.logger.warning(f"关系源实体不匹配: 期望{project_id}, 实际{source_entity}")
                # 如果不匹配，尝试修正
                source_entity = project_id

            # 获取目标实体文本
            target_text = rel.get('target_entity', '')

            # 查找目标实体ID
            target_id = entity_id_map.get(target_text)

            if not target_id:
                self.logger.warning(f"未找到目标实体ID: {target_text}")
                continue

            # 获取关系类型
            rel_type = rel.get('type', '')
            rel_properties = rel.get('properties', {})

            # 构建关系
            relationship = self.build_relationship(
                source_entity,
                target_id,
                rel_type,
                rel_properties
            )

            if relationship:
                relationships.append(relationship)

        return relationships

    def build_batch_relationships(
        self,
        projects_data: List[Dict[str, Any]],
        extraction_results: List[Dict[str, Any]],
        entity_id_map: Dict[str, str]
    ) -> List[Dict[str, Any]]:
        """
        批量构建关系

        Args:
            projects_data: 项目数据列表
            extraction_results: 抽取结果列表
            entity_id_map: 实体文本到ID的映射

        Returns:
            关系列表
        """
        self.logger.info(f"开始批量构建关系，共{len(projects_data)}个项目")

        all_relationships = []

        for idx, (project_data, extraction_result) in enumerate(zip(projects_data, extraction_results)):
            if not extraction_result:
                continue

            project_id = project_data.get('project_id', '')

            if not project_id:
                self.logger.warning(f"项目{idx}缺少project_id")
                continue

            # 构建该项目的关系
            relationships = self.build_relationships_from_extraction(
                project_id,
                extraction_result,
                entity_id_map
            )

            all_relationships.extend(relationships)

            self.logger.info(f"项目 {project_id} 构建了{len(relationships)}个关系")

        self.logger.info(f"批量构建完成，共{len(all_relationships)}个关系")

        return all_relationships

    def validate_relationships(
        self,
        relationships: List[Dict[str, Any]],
        node_ids: set
    ) -> Dict[str, Any]:
        """
        验证关系完整性

        Args:
            relationships: 关系列表
            node_ids: 节点ID集合

        Returns:
            验证报告
        """
        report = {
            'total_relationships': len(relationships),
            'valid_relationships': 0,
            'invalid_relationships': 0,
            'broken_links': [],
            'invalid_types': [],
            'relationships_by_type': {}
        }

        for rel in relationships:
            source_id = rel.get('source', '')
            target_id = rel.get('target', '')
            rel_type = rel.get('type', '')

            # 统计关系类型
            report['relationships_by_type'][rel_type] = \
                report['relationships_by_type'].get(rel_type, 0) + 1

            is_valid = True

            # 验证关系类型
            if rel_type not in self.ontology['relationship_types']:
                report['invalid_types'].append({
                    'source': source_id,
                    'target': target_id,
                    'type': rel_type
                })
                is_valid = False

            # 验证链接完整性
            if source_id not in node_ids:
                report['broken_links'].append({
                    'source': source_id,
                    'target': target_id,
                    'type': rel_type,
                    'issue': 'source_not_found'
                })
                is_valid = False

            if target_id not in node_ids:
                report['broken_links'].append({
                    'source': source_id,
                    'target': target_id,
                    'type': rel_type,
                    'issue': 'target_not_found'
                })
                is_valid = False

            if is_valid:
                report['valid_relationships'] += 1
            else:
                report['invalid_relationships'] += 1

        return report

    def get_statistics(self, relationships: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        获取关系统计信息

        Args:
            relationships: 关系列表

        Returns:
            统计信息
        """
        stats = {
            'total_relationships': len(relationships),
            'relationships_by_type': {}
        }

        for rel in relationships:
            rel_type = rel.get('type', 'Unknown')
            stats['relationships_by_type'][rel_type] = \
                stats['relationships_by_type'].get(rel_type, 0) + 1

        return stats
