import re
from urllib.parse import urlparse
from djangoblog.plugin_manage.base_plugin import BasePlugin
from djangoblog.plugin_manage import hooks
from djangoblog.plugin_manage.hook_constants import ARTICLE_CONTENT_HOOK_NAME


class ExternalLinksPlugin(BasePlugin):
    """
    外部链接处理插件
    功能：自动为文章中的外部链接添加安全属性，防止钓鱼攻击和提升用户体验
    """

    # 插件基本信息
    PLUGIN_NAME = '外部链接处理器'
    PLUGIN_DESCRIPTION = '自动为文章中的外部链接添加 target="_blank" 和 rel="noopener noreferrer" 属性。'
    PLUGIN_VERSION = '0.1.0'
    PLUGIN_AUTHOR = 'liangliangyy'

    def register_hooks(self):
        """
        注册钩子函数
        将外部链接处理方法注册到文章内容钩子
        """
        hooks.register(ARTICLE_CONTENT_HOOK_NAME, self.process_external_links)

    def process_external_links(self, content, *args, **kwargs):
        """
        处理文章内容中的外部链接

        参数:
            content: str - 原始的文章HTML内容
            *args, **kwargs: 其他参数

        返回值:
            str - 处理后的文章内容，外部链接已添加安全属性
        """
        # 导入获取当前网站域名的工具函数
        from djangoblog.utils import get_current_site
        # 获取当前网站的域名，用于判断链接是否为外部链接
        site_domain = get_current_site().domain

        # 正则表达式模式：匹配所有的 <a> 标签
        # 分组1: <a ... href="  (包含href属性前的所有内容)
        # 分组2: 链接URL
        # 分组3: ">...</a>  (href属性后的内容和标签闭合部分)
        link_pattern = re.compile(r'(<a\s+(?:[^>]*?\s+)?href=")([^"]*)(".*?/a>)', re.IGNORECASE)

        def replacer(match):
            """
            正则替换函数 - 处理单个链接匹配

            参数:
                match: 正则匹配对象

            返回值:
                str - 处理后的链接HTML代码
            """
            # 提取链接URL
            href = match.group(2)

            # 如果链接已经有 target 属性，则不处理（避免重复添加）
            if 'target=' in match.group(0).lower():
                return match.group(0)

            # 解析链接URL，提取域名信息
            parsed_url = urlparse(href)

            # 判断是否为外部链接：
            # 1. 有域名 (parsed_url.netloc 不为空)
            # 2. 且域名不等于当前网站域名
            if parsed_url.netloc and parsed_url.netloc != site_domain:
                # 为外部链接添加安全属性：
                # - target="_blank": 在新标签页打开
                # - rel="noopener noreferrer": 安全防护，防止钓鱼攻击
                return f'{match.group(1)}{href}" target="_blank" rel="noopener noreferrer"{match.group(3)}'

            # 内部链接或无效链接，返回原样
            return match.group(0)

        # 使用正则表达式替换所有匹配的链接
        return link_pattern.sub(replacer, content)


# 实例化插件，自动注册到系统
plugin = ExternalLinksPlugin()