"""
引用源分析引擎 - 从AI回答中提取引用的URL和来源信息

功能：
1. 提取文本中的URL链接
2. 提取Markdown格式的引用链接 [text](url)
3. 提取脚注引用标记 [1] 及其对应URL
4. 识别来源标注（如"来源：xxx"、"据xxx报道"等）
5. 提取数据来源标记 [data_source: xxx]
"""

import logging
import re
from dataclasses import dataclass, field

logger = logging.getLogger(__name__)


@dataclass
class ExtractedCitation:
    """提取的引用源信息"""
    source_url: str | None = None
    source_title: str | None = None
    citation_context: str | None = None  # 引用出现的上下文片段


@dataclass
class CitationAnalysisResult:
    """引用源分析结果"""
    data_source: str = "unknown"  # "ai_platform" 或 "search_engine"
    citations: list[ExtractedCitation] = field(default_factory=list)
    clean_response: str = ""  # 去掉 data_source 标记后的纯文本


# URL正则表达式（匹配 http/https 链接）
_URL_PATTERN = re.compile(
    r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+'
    r'[/\w\-._~:/?#\[\]@!$&\'()*+,;=%]*',
    re.IGNORECASE,
)

# Markdown引用链接 [text](url)
_MD_LINK_PATTERN = re.compile(
    r'\[([^\]]+)\]\((https?://[^\s\)]+)\)',
    re.IGNORECASE,
)

# 脚注引用 [1], [2] 等
_FOOTNOTE_REF_PATTERN = re.compile(r'\[(\d+)\]')

# 脚注定义 [1]: url 或 [1]: text url
_FOOTNOTE_DEF_PATTERN = re.compile(
    r'\[(\d+)\]:\s*(?:([^\n]+?))?\s*(https?://\S+)',
    re.MULTILINE,
)

# 来源标注模式
_SOURCE_ANNOTATION_PATTERNS = [
    re.compile(r'来源[：:]\s*([^\n,，。；;]+)', re.IGNORECASE),
    re.compile(r'据([^\n,，。；;]{2,20}?)(?:报道|消息|透露|表示)', re.IGNORECASE),
    re.compile(r'参考[：:]\s*([^\n,，。；;]+)', re.IGNORECASE),
    re.compile(r'引用[：:]\s*([^\n,，。；;]+)', re.IGNORECASE),
    re.compile(r'出处[：:]\s*([^\n,，。；;]+)', re.IGNORECASE),
]

# data_source 标记
_DATA_SOURCE_PATTERN = re.compile(r'^\[data_source:\s*(\w+)\]\s*\n?', re.MULTILINE)


def extract_data_source(text: str) -> tuple[str, str]:
    """
    从文本中提取 data_source 标记，返回 (data_source, clean_text)
    """
    match = _DATA_SOURCE_PATTERN.search(text)
    if match:
        source = match.group(1)
        clean_text = _DATA_SOURCE_PATTERN.sub("", text)
        return source, clean_text
    return "unknown", text


def extract_urls_with_context(text: str) -> list[ExtractedCitation]:
    """提取文本中的裸URL及其上下文"""
    citations = []
    seen_urls = set()

    for match in _URL_PATTERN.finditer(text):
        url = match.group(0)
        # 清理URL末尾的标点
        url = url.rstrip('.,;:!?)，。；：！？）')

        if url in seen_urls:
            continue
        seen_urls.add(url)

        # 提取上下文：URL前后各100字符
        start = max(0, match.start() - 100)
        end = min(len(text), match.end() + 50)
        context = text[start:end].strip()

        citations.append(ExtractedCitation(
            source_url=url,
            source_title=None,
            citation_context=context,
        ))

    return citations


def extract_markdown_links(text: str) -> list[ExtractedCitation]:
    """提取Markdown格式的引用链接 [text](url)"""
    citations = []
    seen_urls = set()

    for match in _MD_LINK_PATTERN.finditer(text):
        title = match.group(1).strip()
        url = match.group(2).strip().rstrip('.,;:!?)，。；：！？）')

        if url in seen_urls:
            continue
        seen_urls.add(url)

        # 提取上下文
        start = max(0, match.start() - 80)
        end = min(len(text), match.end() + 50)
        context = text[start:end].strip()

        citations.append(ExtractedCitation(
            source_url=url,
            source_title=title,
            citation_context=context,
        ))

    return citations


def extract_footnotes(text: str) -> list[ExtractedCitation]:
    """提取脚注引用及其定义"""
    citations = []
    seen_urls = set()

    # 先收集脚注定义
    footnote_defs: dict[str, tuple[str | None, str]] = {}
    for match in _FOOTNOTE_DEF_PATTERN.finditer(text):
        num = match.group(1)
        title = match.group(2)
        url = match.group(3).strip().rstrip('.,;:!?)，。；：！？）')
        if title:
            title = title.strip().rstrip('.,;:，。；：')
        footnote_defs[num] = (title, url)

    # 再匹配脚注引用，提取上下文
    for match in _FOOTNOTE_REF_PATTERN.finditer(text):
        num = match.group(1)
        if num in footnote_defs:
            title, url = footnote_defs[num]
            if url in seen_urls:
                continue
            seen_urls.add(url)

            start = max(0, match.start() - 80)
            end = min(len(text), match.end() + 50)
            context = text[start:end].strip()

            citations.append(ExtractedCitation(
                source_url=url,
                source_title=title,
                citation_context=context,
            ))

    return citations


def extract_source_annotations(text: str) -> list[ExtractedCitation]:
    """提取来源标注（如"来源：xxx"、"据xxx报道"等）"""
    citations = []
    seen_titles = set()

    for pattern in _SOURCE_ANNOTATION_PATTERNS:
        for match in pattern.finditer(text):
            title = match.group(1).strip()
            if len(title) < 2 or title in seen_titles:
                continue
            seen_titles.add(title)

            start = max(0, match.start() - 50)
            end = min(len(text), match.end() + 50)
            context = text[start:end].strip()

            citations.append(ExtractedCitation(
                source_url=None,
                source_title=title,
                citation_context=context,
            ))

    return citations


def analyze_citations(raw_response: str) -> CitationAnalysisResult:
    """
    分析AI回答中的引用源信息

    Args:
        raw_response: 平台适配器返回的原始响应文本

    Returns:
        CitationAnalysisResult: 包含数据来源标记、引用源列表和清理后的文本
    """
    if not raw_response:
        return CitationAnalysisResult()

    # 1. 提取数据来源标记
    data_source, clean_text = extract_data_source(raw_response)

    # 2. 提取各类引用
    all_citations: list[ExtractedCitation] = []
    seen_urls = set()

    # Markdown链接（优先级最高，有标题）
    for c in extract_markdown_links(clean_text):
        if c.source_url not in seen_urls:
            all_citations.append(c)
            if c.source_url:
                seen_urls.add(c.source_url)

    # 脚注引用
    for c in extract_footnotes(clean_text):
        if c.source_url and c.source_url not in seen_urls:
            all_citations.append(c)
            seen_urls.add(c.source_url)

    # 裸URL
    for c in extract_urls_with_context(clean_text):
        if c.source_url not in seen_urls:
            all_citations.append(c)
            seen_urls.add(c.source_url)

    # 来源标注
    for c in extract_source_annotations(clean_text):
        all_citations.append(c)

    # 限制最多20个引用
    all_citations = all_citations[:20]

    logger.info(
        f"引用源分析完成: data_source={data_source}, "
        f"提取到 {len(all_citations)} 个引用源"
    )

    return CitationAnalysisResult(
        data_source=data_source,
        citations=all_citations,
        clean_response=clean_text,
    )
