import configparser
import json
import os
from pathlib import Path

# 动态加载user_space配置
from apps.core.utils.get_models import settings_autoload_user_apps
from apps.plugin_manager.utils import PluginLoader

BASE_DIR = Path(__file__).resolve().parent.parent
"""
Django settings for config project.

Generated by 'django-admin startproject' using Django 5.2.

For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = "django-insecure-59z+v2bpz^xs-#tlgiypg9(xd8vz7q5=iay!%va7)$_-%3()s+"

import os
from pathlib import Path

from django.core.exceptions import ImproperlyConfigured

# 尝试导入 SecretKeyManager
try:
    from apps.core.utils.secret_manager import secret_manager

    SECRET_KEY = secret_manager.get_secret_key()
except ImportError:
    # 如果无法导入，使用备选方案
    # BASE_DIR = Path(__file__).resolve().parent.parent

    # # 密钥文件路径
    # SECRET_KEY_FILE = BASE_DIR / '.generated_secret'

    # def get_fallback_secret_key():
    #     # 1. 环境变量
    #     if env_key := os.environ.get('SECRET_KEY'):
    #         return env_key

    #     # 2. 密钥文件
    #     if SECRET_KEY_FILE.exists():
    #         try:
    #             with open(SECRET_KEY_FILE, 'r') as f:
    #                 lines = f.readlines()
    #                 if lines and len(lines[0].strip()) >= 50:
    #                     return lines[0].strip()
    #         except:
    #             pass

    #     # 3. 默认密钥
    #     import hashlib
    #     project_hash = hashlib.sha256(str(BASE_DIR).encode()).hexdigest()[:40]
    #     return f"django-insecure-{project_hash}"

    # SECRET_KEY = get_fallback_secret_key()
    SECRET_KEY = "django-insecure-59z+v2bpz^xs-#tlgiypg9(xd8vz7q5=iay!%va7)$_-%3()s+"

# 验证密钥长度
if len(SECRET_KEY) < 50 and not os.environ.get("DJANGO_ENV") == "development":
    raise ImproperlyConfigured("SECRET_KEY 长度不足50字符")

DEBUG = False
config_path = BASE_DIR / "config/config.json"

try:
    # 关键修改：指定 encoding='utf-8'
    with open(config_path, "r", encoding="utf-8") as f:
        GLOBAL_CONFIG = json.load(f)
except FileNotFoundError:
    print(f"警告：配置文件未找到，路径: {config_path}")
    GLOBAL_CONFIG = {}
except json.JSONDecodeError as e:
    print(f"错误：配置文件不是有效的 JSON 格式。原因: {e}")
    GLOBAL_CONFIG = {}
except UnicodeDecodeError as e:
    print(f"错误：配置文件编码问题。请确认文件是 UTF-8 格式。原因: {e}")
    GLOBAL_CONFIG = {}
try:
    debug_mode = GLOBAL_CONFIG.get("DebugSetting", {}).get("debug_mode", False)
    if debug_mode:
        DEBUG = True
except:
    pass

RESTART_DIR = os.path.join(BASE_DIR, "config/restart.py")
# Application definition
# def autoload_user_apps():
#     """自动扫描并注册用户应用及其模板目录"""
#     BASE_DIR = Path(__file__).resolve().parent.parent
#     USER_APPS_DIR = BASE_DIR / "user_space" / "apps"

#     # 确保目录存在
#     USER_APPS_DIR.mkdir(mode=0o755, parents=True, exist_ok=True)

#     user_apps = []
#     template_dirs = []

#     for app_dir in USER_APPS_DIR.iterdir():
#         if (app_dir.is_dir() and (app_dir / "__init__.py").exists()
#                 and (app_dir / "apps.py").exists()):

#             # 注册应用
#             user_apps.append(f"user_space.apps.{app_dir.name}")

#             # 添加模板目录
#             templates_path = app_dir / "templates"
#             if templates_path.exists():
#                 template_dirs.append(str(templates_path))

#     return user_apps, template_dirs

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    # 'django.contrib.staticfiles',
    "apps.core.apps.MyStaticFilesConfig",
    # 'django.contrib.sites',  # 如需站点框架
    # 'django.contrib.redirects',  # 如需重定向功能
    "mptt",
    "apps.content",
    "apps.core",
    "apps.links",
    "apps.comments",
    "apps.ads",
    "apps.users",
    "apps.plugin_manager",
    "apps.oplog",
    "django_ckeditor_5",
    "apps.upgrade",
    "django.contrib.sitemaps",  # 网站地图
    "rest_framework",  # 启用序列化等DRF功能‌
    "django_json_widget",
    "qr_code",  # 生成二维码
]

# 后来加个开关控制验证码的使用
if True:
    INSTALLED_APPS += [
        "captcha",  #'验证码'
    ]

THEME_NAME = GLOBAL_CONFIG.get("Theme", {}).get("themename", "default")
INSTALLED_APPS += [f"templates.themes.{THEME_NAME}"]
MIDDLEWARE = []
cache_config = GLOBAL_CONFIG.get("CacheConfig", {})
GLOBAL_CACHE_ENABLED = cache_config.get("global_cache_enabled", False)
if GLOBAL_CACHE_ENABLED:
    MIDDLEWARE += [
        "django.middleware.cache.UpdateCacheMiddleware",  # 全站缓存时必须在第一个
    ]
if DEBUG:
    EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
    INTERNAL_IPS = ["127.0.0.1"]
    try:
        internal_ips = GLOBAL_CONFIG.get("DebugSetting", {}).get("internal_ips", "")
        # 将 internal_ips 转为列表
        ip_list = internal_ips.split(",") if "," in internal_ips else [internal_ips]
        for i in ip_list:
            if i and i != "127.0.0.1":
                INTERNAL_IPS.append(i)
    except:
        pass
    INSTALLED_APPS += [
        "debug_toolbar",  # 注册django-debug-toolbar
    ]
    MIDDLEWARE += [
        "debug_toolbar.middleware.DebugToolbarMiddleware",
    ]

    # debug_toolbar 中间键配置
    DEBUG_TOOLBAR_PANELS = [
        "debug_toolbar.panels.versions.VersionsPanel",
        "debug_toolbar.panels.timer.TimerPanel",
        "debug_toolbar.panels.settings.SettingsPanel",
        "debug_toolbar.panels.headers.HeadersPanel",
        "debug_toolbar.panels.request.RequestPanel",
        "debug_toolbar.panels.sql.SQLPanel",
        "debug_toolbar.panels.staticfiles.StaticFilesPanel",
        "debug_toolbar.panels.templates.TemplatesPanel",
        "debug_toolbar.panels.cache.CachePanel",
        "debug_toolbar.panels.signals.SignalsPanel",
        "debug_toolbar.panels.logging.LoggingPanel",
        "debug_toolbar.panels.redirects.RedirectsPanel",
    ]


MIDDLEWARE += [
    "config.headers.HttpResponseCustomHeader",
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "apps.core.middleware.stealth_auth_middleware.StealthAuthMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "apps.core.middleware.config.SettingsMiddleware",
]

# WDNS = False
# #泛解析
# if WDNS:
#     MIDDLEWARE += [
#         'websetting.sgmiddleware.DomainTypeMiddleware',
#     ]
# #是否关闭用户注册链接
# MIDDLEWARE += [
#     'websetting.sgmiddleware.BlockRegistrationMiddleware',
# ]
GLOBAL_CACHE_ENABLED = cache_config.get("global_cache_enabled", False)
if GLOBAL_CACHE_ENABLED:
    MIDDLEWARE += [
        "django.middleware.cache.FetchFromCacheMiddleware",  # 全站缓存时必须在最后一个
    ]
ROOT_URLCONF = "config.urls"
TEMPLATES = [
    {
        "NAME": "django",
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [
            BASE_DIR / "apps/core/templates",  # admin模板路径
            BASE_DIR / "templates",
            BASE_DIR / "templates/themes",
            BASE_DIR / "templates/themes" / THEME_NAME / "templates",  # 直接指向主题的模板目录
            BASE_DIR / "user_space/templates",
        ],  # 必须包含项目模板目录
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
                "apps.core.context_processors.templates_global",
            ],
        },
    },
]
# 可选：添加隐蔽路径白名单（避免与正常路由冲突）
STEALTH_CONFIG = {
    "SECRET_PATHS": [
        "/internal/system/health/check/",
        "/api/v1/client/config/sync/",
        "/static/config/update.json",
    ]
}
TEMPLATES_THEME_DIR = os.path.join(BASE_DIR, "templates/themes", THEME_NAME)
WSGI_APPLICATION = "config.wsgi.application"

USER_APPS, USER_TEMPLATES = settings_autoload_user_apps()
# 去重（避免重复添加已存在的应用）
existing_apps = set(INSTALLED_APPS)
apps_to_add = [app for app in USER_APPS if app not in existing_apps]

# 添加到 INSTALLED_APPS
INSTALLED_APPS += apps_to_add

# 添加模板目录
TEMPLATES[0]["DIRS"].extend(USER_TEMPLATES)
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases

# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]

# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = GLOBAL_CONFIG.get("SiteSettings", {}).get("language_code", "zh-Hans")
TIME_ZONE = GLOBAL_CONFIG.get("SiteSettings", {}).get("time_zone", "Asia/Shanghai")

USE_I18N = True  # 多语言

USE_TZ = False  # 跨时区

# LANGUAGE_CODE = 'en-us'

# TIME_ZONE = 'UTC'

# USE_I18N = True

# USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/
# 确保静态文件基础配置正确
STATIC_URL = "/static/"  # URL 前缀‌
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),  # 自定义静态文件目录
    os.path.join(BASE_DIR, "templates/themes"),
]
STATIC_ROOT = os.path.join(BASE_DIR, "collected_static")  # 生产环境收集目录

# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# ? 这里控制不控制还在考虑中
ALLOWED_HOSTS = ["*"]  # 开发环境允许本地访问
# 生产环境应配置真实域名，例如：
# raise Exception("配置文件已正确加载！")

# django_ckeditor_5设置
# 上传目录控制
MEDIA_URL = "/media/"

# 放在django项目根目录，同时也需要创建media文件夹
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
from apps.core.configs.ckeditor import CKEDITOR_5_CONFIGS

# 获取缓存配置参数

SITE_CONFIG_CACHE_VERSION = 1

INDEX_TIMEOUT = cache_config.get("index_timeout", 0)
CHANNEL_TIMEOUT = cache_config.get("ichannel_timeout", 0)
LIST_TIMEOUT = cache_config.get("list_timeout", 0)
ITEM_TIMEOUT = cache_config.get("item_timeout", 0)
TAG_TIMEOUT = cache_config.get("tag_timeout", 0)

try:
    CACHES = GLOBAL_CONFIG.get("CacheConfig", {}).get("caches_setting", {})
    if CACHES == {}:
        CACHES = {
            "default": {
                "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
                "LOCATION": "unique-snowflake",  # 需保持唯一性以区分多进程内存缓存‌
                "TIMEOUT": 300,  # 默认缓存超时时间（秒）
                "OPTIONS": {
                    "MAX_ENTRIES": 1000,  # 最大缓存条目数
                    "CULL_FREQUENCY": 3,  # 缓存满时删除比例（1/3）
                },
            }
        }

except Exception as e:
    CACHES = {
        "default": {
            "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
            "LOCATION": "unique-snowflake",  # 需保持唯一性以区分多进程内存缓存‌
            "TIMEOUT": 300,  # 默认缓存超时时间（秒）
            "OPTIONS": {
                "MAX_ENTRIES": 1000,  # 最大缓存条目数
                "CULL_FREQUENCY": 3,  # 缓存满时删除比例（1/3）
            },
        }
    }

# CACHES = {
#     "default": {
#         "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
#         "LOCATION": "unique-snowflake",  # 需保持唯一性以区分多进程内存缓存‌
#         "TIMEOUT": 300,  # 默认缓存超时时间（秒）
#         "OPTIONS": {
#             "MAX_ENTRIES": 1000,  # 最大缓存条目数
#             "CULL_FREQUENCY": 3  # 缓存满时删除比例（1/3）
#         }
#     }
# }
# {

#     # 智能路由缓存（业务实际使用的缓存）
#     'smart_cache': {
#         'BACKEND': 'apps.core.cache.router.SmartCache',
#         'OPTIONS':
#         {  # 参数需置于OPTIONS字段 ‌:ml-citation{ref="3,6" data="citationList"}
#             'LAYERS': ['locmem', 'redis', 'database'],
#             'TIMEOUT': 300,
#             'JITTER': (60, 120)
#         }
#     },
# }

# 限制评论层级深度
COMMENT_MAX_DEPTH = 5  # 最大评论层级
COMMENT_PAGINATE_BY = 20  # 每页评论数

# 优化查询
COMMENT_PREFETCH = (
    "children",
    "user",
    "content_type",
)

# django-json-widget可选：配置全局JSON编辑器主题
JSON_EDITOR_SETTINGS = {
    "theme": "django",
    "disable_collapse": True,
}

# django-ratelimit全局限流设置
from apps.core.configs.ratelimit import DJANGO_RATELIMIT_CONFIG

# 将字典中的配置更新到当前模块的全局变量中，使Django能够识别
globals().update(DJANGO_RATELIMIT_CONFIG)
# 默认JSONR渲染器配
REST_FRAMEWORK = {
    "DEFAULT_RENDERER_CLASSES": [
        "apps.core.utils.renderers.UnicodeJSONRenderer",  # 自定义渲染器
        "rest_framework.renderers.BrowsableAPIRenderer",
    ]
}
# django host
# 好像这种django_hosts使用方法取消了
# host_config = GLOBAL_CONFIG.get('global_dns', None)
# try:
#     if host_config.get('status') == 'enabled' and host_config.get(
#             'dns_type') == 'global_site':
#         INSTALLED_APPS += ['django_hosts']
#         ROOT_HOSTCONF = 'apps.core.utils.hosts'  # 指定hosts配置文件
#         DEFAULT_HOST = 'www'  # 默认子域名
# except:
#     pass
# 用户资料扩展
# AUTH_USER_MODEL = 'accounts.CustomUser'  # 关键配置

BACKUP_ROOT = os.path.join(MEDIA_ROOT, "backups")
DATA_UPLOAD_MAX_NUMBER_FIELDS = 1000  # 根据字段数量调整‌
# 202504230021
# 自动发现用户空间静态文件
STATICFILES_DIRS += [
    os.path.join(BASE_DIR, "user_space/static"),
]

# 模板查找路径（确保用户空间模板优先）
TEMPLATES[0]["DIRS"].insert(0, os.path.join(BASE_DIR, "user_space/templates"))
# celery异步
CELERY_BROKER_URL = "django-db"  # 需安装 django-celery-results
# 加载验证路径
pathlist = ["user_space", "media", ".sys_backups", "user_space/static", "user_space/templates"]
for i in pathlist:
    os.makedirs(os.path.join(BASE_DIR, i), exist_ok=True)
# 验证码设置
CAPTCHA_IMAGE_SIZE = (120, 45)  # 验证码图片尺寸
CAPTCHA_LENGTH = 6  # 验证码字符数
# "email_enabled": true,
# "email_host": "smtp.exmail.qq.com",
# "email_user": "web@whsg1.com",
# "email_password": "hJQbTkh8GXN2vT9Z",
# "email_port": 25,
# "use_tls": false,
# "default_sender": "\u4e0a\u683c\u8f6f\u4ef6 <web@whsg1.com>"
# 邮箱配置
email_config = GLOBAL_CONFIG.get("EmailSetting", {})
try:
    if email_config.get("email_enabled", False) == "true":
        EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
        EMAIL_HOST = email_config.get("email_host", None)  # SMTP 服务器地址
        EMAIL_PORT = email_config.get("email_port", 25)
        EMAIL_USE_TLS = True if email_config.get("use_tls", False) == "true" else False
        EMAIL_HOST_USER = email_config.get("email_user", None)  # 发件邮箱
        EMAIL_HOST_PASSWORD = email_config.get("email_password", None)  # 邮箱密码或授权码
        EMAIL_DEFAULT_SENDER = email_config.get("email_password", None)
except:
    print("邮箱配置加载失败")
# 后台路径更改
ADMIN_DIR = "admin/"
try:
    admin_config = GLOBAL_CONFIG.get("AdminSettings", {})
    ADMIN_DIR = admin_config.get("admin_base_path", "admin/")
except:
    pass
if ADMIN_DIR != "admin/":
    # settings.py
    LOGIN_URL = f"{ADMIN_DIR}login/"
    LOGIN_REDIRECT_URL = ADMIN_DIR
# 根据当前项目名（或环境变量）加载对应配置
# 可通过环境变量动态设置（如 os.getenv('DJANGO_PROJECT')）
# 但考虑实际使用当中可能使用起来不是那么方便，所以暂时都设置为一个数据库
PROJECT_NAME = "production"

SQL_CONF_DIR = os.path.join(BASE_DIR, "config/connection_strings.ini")
sql_cf = configparser.ConfigParser()
sql_cf.read(SQL_CONF_DIR, encoding="utf-8")
# 数据库引擎映射表
ENGINE_MAP = {
    "mysql": "django.db.backends.mysql",
    "postgresql": "django.db.backends.postgresql",
    "sqlite3": "django.db.backends.sqlite3",
    "oracle": "django.db.backends.oracle",
}


def load_database_config():
    db_type = sql_cf.get("production", "sql").lower()
    if db_type not in ENGINE_MAP:
        raise ValueError(f"Unsupported database type: {db_type}")

    db_config = {
        "ENGINE": ENGINE_MAP[db_type],
        "NAME": sql_cf.get("production", "name"),
        "USER": sql_cf.get("production", "user", fallback=""),
        "PASSWORD": sql_cf.get("production", "password", fallback=""),
        "HOST": sql_cf.get("production", "host", fallback=""),
        "PORT": int(sql_cf.get("production", "port", fallback="3306")),
        "CONN_MAX_AGE": int(sql_cf.get("production", "conn_max_age", fallback="300")),
        "OPTIONS": {},
    }

    # 合并额外参数（注意类型转换）
    params_section = f"{db_type}_params"
    # 处理mysql特有参数
    if db_type == "mysql" and sql_cf.has_section("mysql_params"):
        for k, v in sql_cf.items("mysql_params"):
            # 特殊处理布尔值和数值类型
            if v.lower() in ("true", "false"):
                db_config["OPTIONS"][k] = sql_cf.getboolean("mysql_params", k)
            elif v.isdigit():
                db_config["OPTIONS"][k] = sql_cf.getint("mysql_params", k)
            else:
                db_config["OPTIONS"][k] = v
    elif sql_cf.has_section(params_section):
        for k, v in sql_cf.items(params_section):
            if k.endswith("_timeout"):  # 处理超时参数
                db_config["OPTIONS"][k] = int(v)
            else:
                db_config["OPTIONS"][k] = v

    return {"default": db_config}


# DATABASES = {
#     'default': {
#         'ENGINE': sql_cf.get(PROJECT_NAME, 'engine'),
#         'NAME': sql_cf.get(PROJECT_NAME, 'name'),
#         'USER': sql_cf.get(PROJECT_NAME, 'user'),
#         'PASSWORD': sql_cf.get(PROJECT_NAME, 'password'),
#         'HOST': sql_cf.get(PROJECT_NAME, 'host'),
#         'PORT': sql_cf.get(PROJECT_NAME, 'port'),
#         'CONN_MAX_AGE': 300,  # 连接存活时间(秒)
#         'OPTIONS': {
#             'threaded': True,  # 启用线程安全模式
#         }
#     }
# }

DATABASES = load_database_config()


PLUGINS_DIR = BASE_DIR / "plugins"

INSTALLED_APPS += PluginLoader.get_active_plugins()
LOGIN_URL = "users:login"
# 允许来自这些源的跨域请求（使用完整的URL，包括协议）
# CSRF_TRUSTED_ORIGINS = [
#     "http://101.34.40.100:8099", 'http://49.235.139.41', 'http://djacore.com',
#     'https://djacore.com'
# ]
# # 获取真实host域名
# USE_X_FORWARDED_HOST = True
# # # 确保 Django 的会话和 CSRF cookie 设置正确
# SESSION_COOKIE_DOMAIN = '.djacore.com'  # 注意前面的点
# CSRF_COOKIE_DOMAIN = '.djacore.com'  # 注意前面的点
