from haystack.query import SearchQuerySet

from blog.models import Article, Category


class BlogApi:
    """
    博客 API 类，封装了与博客相关的数据查询功能，包括全文搜索、分类获取、分类文章获取和最新文章获取。
    """

    def __init__(self):
        """
        初始化 BlogApi 实例。
        创建一个 SearchQuerySet 对象用于全文搜索，并执行一个空查询以准备搜索环境。
        同时设置默认的最大返回记录数。
        """
        self.searchqueryset = SearchQuerySet()  # Haystack 的搜索查询集对象
        self.searchqueryset.auto_query('')      # 执行空查询，初始化搜索状态
        self.__max_takecount__ = 8             # 设置最大返回文章数量为 8 篇

    def search_articles(self, query):
        """
        根据用户输入的关键词查询文章。

        参数:
            query (str): 用户输入的搜索关键词。

        返回:
            QuerySet: 包含匹配文章的查询集（最多返回 __max_takecount__ 篇文章），
                      并已加载文章的完整模型实例（通过 load_all）。

        说明:
            使用 Haystack 的 auto_query 进行全文搜索，并加载所有关联的文章对象。
        """
        sqs = self.searchqueryset.auto_query(query)  # 根据关键词执行全文搜索
        sqs = sqs.load_all()                         # 加载搜索结果对应的真实模型实例（Article 对象）
        return sqs[:self.__max_takecount__]          # 返回最多 __max_takecount__ 条搜索结果

    def get_category_lists(self):
        """
        获取所有文章分类的列表。

        返回:
            QuerySet: 包含数据库中所有 Category 对象的查询集。

        说明:
            此方法返回所有已创建的分类，可用于展示分类导航等。
        """
        return Category.objects.all()

    def get_category_articles(self, categoryname):
        """
        根据分类名称获取该分类下的文章列表。

        参数:
            categoryname (str): 分类的名称。

        返回:
            QuerySet 或 None: 如果存在该分类的文章，则返回最多 __max_takecount__ 篇文章的查询集；
                              如果该分类下没有文章，则返回 None。

        说明:
            通过文章模型的外键关系（category__name）进行过滤，获取指定分类的文章。
        """
        articles = Article.objects.filter(category__name=categoryname)  # 查询指定分类的文章
        if articles:
            return articles[:self.__max_takecount__]  # 存在文章则返回最多 __max_takecount__ 篇
        return None  # 无文章则返回 None

    def get_recent_articles(self):
        """
        获取最新的文章列表（按模型默认排序，通常是按创建时间倒序）。

        返回:
            QuerySet: 包含最新文章的查询集（最多返回 __max_takecount__ 篇文章）。

        说明:
            此方法返回数据库中最新的若干篇文章，可用于展示“最新文章”或“热门文章”。
        """
        return Article.objects.all()[:self.__max_takecount__]