#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
媒体叙事分析模块 - 人物画像技能
分析不同倾向媒体如何"框架"目标人物

创建时间：2026-04-03
开发者：瞰宇 (Kàn Yǔ)
"""

import json
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass, asdict
from collections import Counter, defaultdict
import re


@dataclass
class MediaFramework:
    """媒体框架"""
    media_name: str
    media_type: str  # left, right, center, international
    dominant_frame: str  # 主导框架
    secondary_frame: Optional[str]  # 次要框架
    sentiment_distribution: Dict[str, float]  # 情感分布
    keywords: List[str]  # 高频关键词
    report_count: int  # 报道数量


@dataclass
class CrossMediaConsensus:
    """跨媒体共识"""
    consensus_labels: List[str]  # 共识标签
    divergence_points: List[str]  # 分歧点
    polarization_score: float  # 极化分数（0-1）


class MediaAnalyzer:
    """
    媒体叙事分析器
    分析不同倾向媒体如何"框架"目标人物
    """
    
    # 媒体分类（示例）
    MEDIA_CLASSIFICATION = {
        "left": [
            "纽约时报", "华盛顿邮报", "卫报", "CNN", "MSNBC",
            "New York Times", "Washington Post", "The Guardian"
        ],
        "right": [
            "福克斯新闻", "华尔街日报(社论)", "布赖特巴特", "每日来电",
            "Fox News", "WSJ Opinion", "Breitbart", "Daily Caller"
        ],
        "center": [
            "路透社", "美联社", "BBC", "华尔街日报(新闻)",
            "Reuters", "AP", "BBC News"
        ],
        "international": [
            "BBC", "卫报", "每日电讯报", "金融时报",
            "BBC", "The Guardian", "Daily Telegraph", "Financial Times"
        ]
    }
    
    # 常见框架关键词（示例）
    FRAME_KEYWORDS = {
        "reform_leader": ["改革", "先锋", "创新", "变革", "改革者"],
        "trouble_maker": ["麻烦", "混乱", "破坏", "煽动", "极化"],
        "pragmatic": ["务实", "平衡", "稳健", "中间", "理性"],
        "populist": ["民粹", "人民", "反精英", "草根", "群众"]
    }
    
    def __init__(self):
        """初始化媒体分析器"""
        self.media_reports = []
        self.frameworks = []
    
    def load_media_reports(self, reports: List[Dict]):
        """
        加载媒体报道
        
        Args:
            reports: 媒体报道列表
        """
        self.media_reports = reports
    
    def classify_media(self, media_name: str) -> str:
        """
        分类媒体倾向
        
        Args:
            media_name: 媒体名称
            
        Returns:
            媒体类型（left/right/center/international）
        """
        media_name_lower = media_name.lower()
        
        for media_type, media_list in self.MEDIA_CLASSIFICATION.items():
            for media in media_list:
                if media.lower() in media_name_lower or media_name_lower in media.lower():
                    return media_type
        
        # 默认返回中间派
        return "center"
    
    def analyze_media_framework(self, media_name: str, reports: List[Dict]) -> MediaFramework:
        """
        分析单个媒体的框架
        
        Args:
            media_name: 媒体名称
            reports: 该媒体的报道列表
            
        Returns:
            MediaFramework对象
        """
        if not reports:
            return MediaFramework(
                media_name=media_name,
                media_type=self.classify_media(media_name),
                dominant_frame="无数据",
                secondary_frame=None,
                sentiment_distribution={},
                keywords=[],
                report_count=0
            )
        
        # 识别主导框架
        dominant_frame, secondary_frame = self._identify_dominant_frame(reports)
        
        # 分析情感分布
        sentiment_dist = self._analyze_sentiment_distribution(reports)
        
        # 提取高频关键词
        keywords = self._extract_keywords(reports)
        
        return MediaFramework(
            media_name=media_name,
            media_type=self.classify_media(media_name),
            dominant_frame=dominant_frame,
            secondary_frame=secondary_frame,
            sentiment_distribution=sentiment_dist,
            keywords=keywords[:10],  # 取前10个
            report_count=len(reports)
        )
    
    def _identify_dominant_frame(
        self, 
        reports: List[Dict]
    ) -> Tuple[str, (str, None)]:
        """
        识别主导框架
        
        Args:
            reports: 报道列表
            
        Returns:
            (主导框架, 次要框架)
        """
        # 统计各框架的出现频率
        frame_counts = Counter()
        
        for report in reports:
            content = report.get("content", "").lower()
            
            for frame, keywords in self.FRAME_KEYWORDS.items():
                count = sum(1 for kw in keywords if kw in content)
                if count > 0:
                    frame_counts[frame] += count
        
        if not frame_counts:
            return "无明确框架", None
        
        # 获取出现频率最高的框架
        sorted_frames = frame_counts.most_common(2)
        dominant = sorted_frames[0][0]
        secondary = sorted_frames[1][0] if len(sorted_frames) > 1 else None
        
        return dominant, secondary
    
    def _analyze_sentiment_distribution(
        self, 
        reports: List[Dict]
    ) -> Dict[str, float]:
        """
        分析情感分布
        
        Args:
            reports: 报道列表
            
        Returns:
            情感分布字典
        """
        sentiment_counts = Counter()
        
        for report in reports:
            sentiment = report.get("sentiment", "neutral")
            sentiment_counts[sentiment] += 1
        
        total = sum(sentiment_counts.values())
        if total == 0:
            return {"positive": 0.0, "neutral": 0.0, "negative": 0.0}
        
        return {
            "positive": sentiment_counts["positive"] / total,
            "neutral": sentiment_counts["neutral"] / total,
            "negative": sentiment_counts["negative"] / total
        }
    
    def _extract_keywords(self, reports: List[Dict], top_n: int = 10) -> List[str]:
        """
        提取高频关键词
        
        Args:
            reports: 报道列表
            top_n: 返回前N个关键词
            
        Returns:
            关键词列表
        """
        # 合并所有报道内容
        all_text = " ".join([r.get("content", "") for r in reports])
        
        # 简单分词（实际应该使用更复杂的NLP方法）
        words = re.findall(r'\b[\w\u4e00-\u9fff]{2,}\b', all_text)
        
        # 统计词频
        word_counts = Counter(words)
        
        # 过滤停用词（示例）
        stop_words = {"的", "了", "在", "是", "和", "有", "说", "the", "and", "of", "to", "in"}
        for stop_word in stop_words:
            word_counts.pop(stop_word, None)
        
        # 返回高频词
        return [word for word, count in word_counts.most_common(top_n)]
    
    def analyze_all_media(self) -> List[MediaFramework]:
        """
        分析所有媒体的框架
        
        Returns:
            MediaFramework对象列表
        """
        # 按媒体分组
        media_grouped = defaultdict(list)
        for report in self.media_reports:
            media_name = report.get("media_name", "未知媒体")
            media_grouped[media_name].append(report)
        
        # 分析每个媒体的框架
        self.frameworks = []
        for media_name, reports in media_grouped.items():
            framework = self.analyze_media_framework(media_name, reports)
            self.frameworks.append(framework)
        
        return self.frameworks
    
    def analyze_cross_media_consensus(self) -> CrossMediaConsensus:
        """
        分析跨媒体共识与分歧
        
        Returns:
            CrossMediaConsensus对象
        """
        if not self.frameworks:
            return CrossMediaConsensus([], [], 0.0)
        
        # 识别所有媒体都提及的框架
        frame_mentions = defaultdict(int)
        for framework in self.frameworks:
            if framework.dominant_frame != "无数据":
                frame_mentions[framework.dominant_frame] += 1
        
        total_media = len(self.frameworks)
        consensus_labels = [
            frame for frame, count in frame_mentions.items()
            if count >= total_media * 0.7  # 至少70%媒体提及
        ]
        
        # 识别分歧点
        unique_frames = set(f.dominant_frame for f in self.frameworks if f.dominant_frame != "无数据")
        divergence_points = list(unique_frames)
        
        # 计算极化分数（简化版：基于框架多样性）
        polarization_score = min(1.0, len(unique_frames) / total_media)
        
        return CrossMediaConsensus(
            consensus_labels=consensus_labels,
            divergence_points=divergence_points,
            polarization_score=polarization_score
        )
    
    def generate_media_report(self) -> Dict:
        """
        生成媒体叙事分析报告
        
        Returns:
            分析报告字典
        """
        frameworks = self.analyze_all_media()
        consensus = self.analyze_cross_media_consensus()
        
        # 按媒体类型分组
        by_type = defaultdict(list)
        for framework in frameworks:
            by_type[framework.media_type].append({
                "媒体名称": framework.media_name,
                "主导框架": framework.dominant_frame,
                "情感分布": framework.sentiment_distribution,
                "高频关键词": framework.keywords[:5],
                "报道数量": framework.report_count
            })
        
        report = {
            "媒体框架分析": {
                "左翼媒体": by_type["left"],
                "右翼媒体": by_type["right"],
                "中间派媒体": by_type["center"],
                "国际媒体": by_type["international"]
            },
            "跨媒体共识": {
                "共识标签": consensus.consensus_labels,
                "分歧点": consensus.divergence_points,
                "极化分数": f"{consensus.polarization_score:.2f}"
            }
        }
        
        return report


def main():
    """测试媒体分析器"""
    analyzer = MediaAnalyzer()
    
    # 示例媒体报道数据
    reports = [
        {
            "media_name": "纽约时报",
            "title": "民粹主义的兴起",
            "content": "极右翼煽动者正在破坏民主制度，制造社会分裂。",
            "date": "2024-01-01",
            "sentiment": "negative"
        },
        {
            "media_name": "福克斯新闻",
            "title": "爱国反叛者",
            "content": "捍卫自由的爱国者，人民的代言人。",
            "date": "2024-01-02",
            "sentiment": "positive"
        },
        {
            "media_name": "路透社",
            "title": "争议政治人物",
            "content": "一位极具争议的政治人物，引发了广泛讨论。",
            "date": "2024-01-03",
            "sentiment": "neutral"
        }
    ]
    
    analyzer.load_media_reports(reports)
    
    # 生成报告
    print("=== 媒体叙事分析报告 ===")
    report = analyzer.generate_media_report()
    print(json.dumps(report, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
