import json
import os
from importlib import import_module

from apps.core.utils.djacore import (apply_service_limits,
                                     should_continue_service)
from django.conf import settings


class PluginLoader:
    # 定义服务受限时的最大插件数量
    # MAX_PLUGINS_WHEN_SERVICE_LIMITED = 3

    @classmethod
    def get_active_plugins(cls):
        """获取所有激活的合法插件，根据服务状态限制数量"""
        plugins_dir = os.path.join(settings.BASE_DIR, 'plugins')
        if not os.path.exists(plugins_dir):
            print(f"插件目录不存在，正在创建: {plugins_dir}")
            try:
                # 使用 os.makedirs 创建目录，exist_ok=True 避免目录已存在时的错误
                os.makedirs(plugins_dir, exist_ok=True)
                print(f"插件目录创建成功: {plugins_dir}")
            except OSError as e:
                print(f"创建插件目录失败: {plugins_dir}。错误: {e}")
                return active_plugins  # 创建失败，返回空列表
        active_plugins = []

        for plugin_name in os.listdir(plugins_dir):
            plugin_path = os.path.join(plugins_dir, plugin_name)
            meta_file = os.path.join(plugin_path, 'plugin_meta.json')
            init_file = os.path.join(plugin_path, '__init__.py')

            # 验证插件合法性
            if not all([
                    os.path.isdir(plugin_path),
                    os.path.isfile(meta_file),
                    os.path.isfile(init_file)
            ]):
                continue

            try:
                with open(meta_file, 'r', encoding='utf-8') as f:
                    meta = json.load(f)
                    if meta.get('is_active', False):
                        # 当dependency_status不存在或不为'pending'时加载
                        if meta.get('dependency_status', '') != 'pending':
                            active_plugins.append(f'plugins.{plugin_name}')
            except (json.JSONDecodeError, KeyError):
                continue

        # 检查服务状态并相应限制插件数量
        return cls._apply_service_limits(active_plugins)

    @classmethod
    def _apply_service_limits(cls, active_plugins):
        """根据服务状态应用插件数量限制"""
        # if not should_continue_service():
        #     # 服务受限时，使用切片操作限制列表长度[5,6](@ref)
        #     limited_plugins = active_plugins[-cls.
        #                                      MAX_PLUGINS_WHEN_SERVICE_LIMITED:]
        #     return limited_plugins
        # return active_plugins
        return apply_service_limits(active_plugins)

    @classmethod
    def load_plugin_admin(cls, plugin_name):
        """动态加载插件admin配置"""
        try:
            import_module(f'plugins.{plugin_name}.admin')
        except ImportError:
            pass

    @classmethod
    def get_plugin_limit_status(cls):
        """获取当前插件限制状态信息"""
        plugins_dir = os.path.join(settings.BASE_DIR, 'plugins')
        all_active_plugins = []

        # 获取所有激活插件（不应用限制）
        for plugin_name in os.listdir(plugins_dir):
            plugin_path = os.path.join(plugins_dir, plugin_name)
            meta_file = os.path.join(plugin_path, 'plugin_meta.json')
            init_file = os.path.join(plugin_path, '__init__.py')

            if not all([
                    os.path.isdir(plugin_path),
                    os.path.isfile(meta_file),
                    os.path.isfile(init_file)
            ]):
                continue

            try:
                with open(meta_file, 'r', encoding='utf-8') as f:
                    meta = json.load(f)
                    if meta.get('is_active', False) and meta.get(
                            'dependency_status', '') != 'pending':
                        all_active_plugins.append(plugin_name)
            except (json.JSONDecodeError, KeyError):
                continue

        # 应用限制后的插件列表
        limited_plugins = cls._apply_service_limits(all_active_plugins)

        return {
            'service_available': should_continue_service(),
            'total_active_plugins': len(all_active_plugins),
            'current_loaded_plugins': len(limited_plugins),
            # 'max_allowed_when_limited': cls.MAX_PLUGINS_WHEN_SERVICE_LIMITED,
            'is_limited': len(all_active_plugins) > len(limited_plugins)
        }
