import os
import re

from django.conf import settings
from django.core.cache import caches
from django.http import (FileResponse, HttpResponseForbidden,
                         HttpResponseNotFound)
from django.views import View


class SensitiveFilter:
    _cache_key = "SENSITIVE_REGEX_CACHE"

    def __init__(self, config):
        self.config = config
        self.regex = self._get_cached_regex()
        self.search_regex = self._get_cached_search_regex()

    def _build_regex(self, words):
        if not words:
            return re.compile(r'^(?!x)x')  # 无敏感词时返回不可能匹配模式
        # 按长度降序排列，优先匹配更长关键词
        sorted_words = sorted(words, key=lambda x: -len(x))
        # 转义特殊字符并组合模式
        pattern = '|'.join(map(re.escape, sorted_words))
        return re.compile(fr'(?:{pattern})')

    def _get_cached_regex(self):
        cache = caches['default']
        regex = cache.get(self._cache_key)

        if not regex:
            words = [
                w.strip() for w in self.config.sensitive_words.split('\n')
                if w.strip()
            ]
            regex = self._build_regex(words)
            cache.set(self._cache_key, regex, timeout=86400)  # 缓存24小时
        return regex

    def process_text(self, text):
        """处理文本中的敏感词"""
        if not self.config.filter_switch or not text:
            return text

        # 根据处理方法选择替换策略
        if self.config.handle_method == 0:  # 删除敏感词
            return self.regex.sub('', text)
        elif self.config.handle_method == 1:  # 替换为星号
            return self.regex.sub(lambda m: '*' * len(m.group()), text)
        else:
            raise ValueError("不支持的处理方法")

    def _build_search_regex(self, words):
        """构建用于检测的正则表达式"""
        if not words:
            return re.compile(r'^(?!x)x')  # 空模式
        sorted_words = sorted(words, key=len, reverse=True)  # 优先匹配长词
        pattern = '|'.join(map(re.escape, sorted_words))
        return re.compile(pattern)

    def _get_cached_search_regex(self):
        """获取缓存的正则对象"""
        cache = caches['default']
        regex = cache.get(self._cache_key)

        if not regex:
            words = [
                w.strip() for w in self.config.sensitive_words.split('\n')
                if w.strip()
            ]
            regex = self._build_search_regex(words)
            cache.set(self._cache_key, regex, timeout=86400)
        return regex

    def has_sensitive_words(self, text):
        """检测文本是否包含敏感词"""
        if not text or not self.search_regex:
            return False
        return bool(self.search_regex.search(text))  # 使用search方法检测


class SensitiveWordsDownload(View):

    def get(self, request):
        try:
            # 路径规范化增强
            rel_path = request.GET.get('path', '').replace('\\', '/')  # 统一分隔符

            if not re.match(r'^[\w\/\-\.]+$', rel_path):
                return HttpResponseForbidden("非法路径请求")

            abs_path = os.path.normpath(
                os.path.join(settings.STATIC_ROOT, rel_path))
            if not abs_path.startswith(str(settings.STATIC_ROOT)):
                return HttpResponseForbidden("禁止访问系统文件")

            file_obj = open(abs_path, 'rb')
            response = FileResponse(file_obj)
            response[
                "Content-Disposition"] = f'attachment; filename="{os.path.basename(abs_path)}"'

            return response
        except FileNotFoundError:
            return HttpResponseNotFound("文件不存在")
