"""
Django settings for djangoblog project.
项目配置文件：包含项目核心设置、数据库、中间件、静态资源等所有全局配置
Generated by 'django-admin startproject' using Django 1.10.2.
"""
import os
import sys
from pathlib import Path

# 导入Django国际化翻译工具
from django.utils.translation import gettext_lazy as _


def env_to_bool(env, default):
    """
    环境变量转换工具函数：将环境变量的字符串值转为布尔值
    - 若环境变量未设置，返回默认值
    - 若环境变量存在，仅当值为'True'时返回True，其他情况返回False
    """
    str_val = os.environ.get(env)
    return default if str_val is None else str_val == 'True'


# -------------------------- 基础路径配置 --------------------------
# 项目根目录：当前配置文件所在目录的父级目录（即项目根目录）
BASE_DIR = Path(__file__).resolve().parent.parent


# -------------------------- 安全与调试配置 --------------------------
# 快速开发配置（生产环境需修改）
# SECURITY WARNING: 生产环境必须将SECRET_KEY通过环境变量配置，禁止硬编码
SECRET_KEY = os.environ.get(
    'DJANGO_SECRET_KEY') or 'n9ceqv38)#&mwuat@(mjb_p%em$e8$qyr#fw9ot!=ba6lijx-6'

# 调试模式：开发环境开启（True），生产环境必须关闭（False）
# 通过环境变量控制，默认开启调试
DEBUG = env_to_bool('DJANGO_DEBUG', True)

# 测试模式标识：当执行python manage.py test时，TESTING为True
TESTING = len(sys.argv) > 1 and sys.argv[1] == 'test'

# 允许访问的主机列表：生产环境需指定具体域名，禁止使用'*'（存在安全风险）
ALLOWED_HOSTS = ['*', '127.0.0.1', 'example.com']

# Django 4.0+新增：信任的CSRF源列表，防止跨站请求伪造，生产环境需配置真实域名
CSRF_TRUSTED_ORIGINS = ['http://example.com']


# -------------------------- 应用配置 --------------------------
INSTALLED_APPS = [
    # Django内置应用（精简版Admin，仅包含核心功能）
    'django.contrib.admin.apps.SimpleAdminConfig',
    'django.contrib.auth',          # 用户认证系统
    'django.contrib.contenttypes',  # 内容类型框架（关联模型与数据表）
    'django.contrib.sessions',      # 会话管理
    'django.contrib.messages',      # 消息提示系统
    'django.contrib.staticfiles',   # 静态资源管理
    'django.contrib.sites',         # 多站点支持（用于sitemap等功能）
    'django.contrib.sitemaps',      # 站点地图生成

    # 第三方应用
    'mdeditor',     # Markdown编辑器（用于文章编写）
    'haystack',     # 全文搜索框架
    'compressor',   # 静态资源压缩（CSS/JS合并压缩）

    # 自定义应用
    'blog',         # 博客核心功能（文章、分类等）
    'accounts',     # 用户账户管理（自定义用户模型等）
    'comments',     # 评论功能
    'oauth',        # 第三方登录（如GitHub、微信等）
    'servermanager',# 服务器管理（如系统监控等）
    'owntracks',    # 位置追踪（可选功能）
    'djangoblog'    # 项目主应用（全局配置、工具函数等）
]


# -------------------------- 中间件配置 --------------------------
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',  # 安全相关中间件（防XSS、点击劫持等）
    'django.contrib.sessions.middleware.SessionMiddleware',  # 会话管理
    'django.middleware.locale.LocaleMiddleware',      # 国际化中间件（多语言支持）
    'django.middleware.gzip.GZipMiddleware',          # GZip压缩（减少响应体积）
    # 'django.middleware.cache.UpdateCacheMiddleware', # 缓存更新（注释：当前未启用）
    'django.middleware.common.CommonMiddleware',      # 通用中间件（处理URL、反向解析等）
    # 'django.middleware.cache.FetchFromCacheMiddleware', # 缓存读取（注释：当前未启用）
    'django.middleware.csrf.CsrfViewMiddleware',      # CSRF保护中间件
    'django.contrib.auth.middleware.AuthenticationMiddleware',  # 用户认证中间件
    'django.contrib.messages.middleware.MessageMiddleware',     # 消息提示中间件
    'django.middleware.clickjacking.XFrameOptionsMiddleware',  # 防点击劫持
    'django.middleware.http.ConditionalGetMiddleware',         # 处理HTTP条件请求（如304缓存）
    'blog.middleware.OnlineMiddleware'                 # 自定义中间件（跟踪用户在线状态）
]


# -------------------------- URL与模板配置 --------------------------
# 项目主URL配置文件路径
ROOT_URLCONF = 'djangoblog.urls'

# 模板配置
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',  # Django模板引擎
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  # 全局模板目录（项目根目录下的templates）
        'APP_DIRS': True,  # 允许从各应用的templates目录加载模板
        'OPTIONS': {
            # 模板上下文处理器：向所有模板注入全局变量
            'context_processors': [
                'django.template.context_processors.debug',  # 调试模式变量
                'django.template.context_processors.request', # 请求对象（request）
                'django.contrib.auth.context_processors.auth', # 用户认证变量（user）
                'django.contrib.messages.context_processors.messages', # 消息提示变量
                'blog.context_processors.seo_processor' # 自定义SEO处理器（注入SEO相关变量）
            ],
        },
    },
]

# WSGI应用入口（用于部署，如Gunicorn、uWSGI）
WSGI_APPLICATION = 'djangoblog.wsgi.application'


# -------------------------- 数据库配置 --------------------------
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 数据库引擎（MySQL）
        'NAME': os.environ.get('DJANGO_MYSQL_DATABASE') or 'djangoblog',  # 数据库名
        'USER': os.environ.get('DJANGO_MYSQL_USER') or 'root',  # 数据库用户名
        'PASSWORD': os.environ.get('DJANGO_MYSQL_PASSWORD') or 'LY181828',  # 数据库密码
        'HOST': os.environ.get('DJANGO_MYSQL_HOST') or '127.0.0.1',  # 数据库主机
        'PORT': int(os.environ.get('DJANGO_MYSQL_PORT') or 3306),  # 数据库端口
        'OPTIONS': {'charset': 'utf8mb4'},  # 数据库字符集（支持emoji表情）
    }}


# -------------------------- 密码验证配置 --------------------------
AUTH_PASSWORD_VALIDATORS = [
    # 验证密码与用户名/邮箱是否相似
    {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
    # 验证密码最小长度（默认8位）
    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
    # 验证密码是否为常见弱密码（如123456）
    {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
    # 验证密码是否全为数字
    {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
]


# -------------------------- 国际化与时间配置 --------------------------
# 支持的语言列表（英文、简体中文、繁体中文）
LANGUAGES = (
    ('en', _('English')),
    ('zh-hans', _('Simplified Chinese')),
    ('zh-hant', _('Traditional Chinese')),
)

# 语言文件目录（存放翻译文件的路径）
LOCALE_PATHS = (os.path.join(BASE_DIR, 'locale'),)

# 默认语言（简体中文）
LANGUAGE_CODE = 'zh-hans'

# 时区（上海时区，与UTC时差+8）
TIME_ZONE = 'Asia/Shanghai'

# 启用国际化
USE_I18N = True

# 启用本地化（日期、时间格式等）
USE_L10N = True

# 禁用UTC时间（使用本地时间存储数据库时间）
USE_TZ = False


# -------------------------- 全文搜索配置（Haystack） --------------------------
HAYSTACK_CONNECTIONS = {
    'default': {
        # 搜索引擎：自定义中文Whoosh引擎（支持中文分词）
        'ENGINE': 'djangoblog.whoosh_cn_backend.WhooshEngine',
        # 搜索索引存储路径（项目配置文件目录下的whoosh_index）
        'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'),
    },
}

# 实时更新搜索索引：当文章新增/修改/删除时，自动更新搜索索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'


# -------------------------- 用户认证配置 --------------------------
# 自定义认证后端：允许用户用用户名或邮箱登录
AUTHENTICATION_BACKENDS = ['accounts.user_login_backend.EmailOrUsernameModelBackend']

# 自定义用户模型：替换Django内置的User模型（关联accounts应用的BlogUser）
AUTH_USER_MODEL = 'accounts.BlogUser'

# 登录页面URL：未登录用户访问需认证页面时，重定向到该URL
LOGIN_URL = '/login/'


# -------------------------- 静态资源与媒体文件配置 --------------------------
# 静态资源收集目录（生产环境使用python manage.py collectstatic收集后的路径）
STATIC_ROOT = os.path.join(BASE_DIR, 'collectedstatic')

# 静态资源URL前缀（前端访问静态资源的路径，如http://example.com/static/）
STATIC_URL = '/static/'

# 全局静态资源目录（项目根目录下的static文件夹）
STATICFILES = os.path.join(BASE_DIR, 'static')

# 媒体文件（用户上传文件，如文章图片）存储目录
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')

# 媒体文件URL前缀（前端访问上传文件的路径，如http://example.com/media/）
MEDIA_URL = '/media/'

# 静态资源查找器（指定Django如何查找静态文件）
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',  # 从全局STATICFILES目录查找
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',  # 从各应用的static目录查找
    'compressor.finders.CompressorFinder',  # 从compressor压缩后的目录查找
)


# -------------------------- 静态资源压缩配置（Compressor） --------------------------
# 启用压缩（生产环境建议开启，开发环境可关闭）
COMPRESS_ENABLED = True
# COMPRESS_OFFLINE = True  # 离线压缩（注释：当前未启用，适合生产环境）

# CSS压缩过滤器：1. 转换相对URL为绝对URL；2. 压缩CSS代码
COMPRESS_CSS_FILTERS = [
    'compressor.filters.css_default.CssAbsoluteFilter',
    'compressor.filters.cssmin.CSSMinFilter'
]

# JS压缩过滤器：压缩JS代码
COMPRESS_JS_FILTERS = ['compressor.filters.jsmin.JSMinFilter']


# -------------------------- 缓存配置 --------------------------
# HTTP缓存超时时间（单位：秒，2592000秒=30天）
CACHE_CONTROL_MAX_AGE = 2592000

# 默认缓存：本地内存缓存（适合开发环境，生产环境建议用Redis/Memcached）
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'TIMEOUT': 10800,  # 缓存超时时间（3小时）
        'LOCATION': 'unique-snowflake',  # 缓存实例标识（唯一即可）
    }
}

# 若环境变量配置了Redis地址，则使用Redis作为缓存（生产环境推荐）
if os.environ.get("DJANGO_REDIS_URL"):
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.redis.RedisCache',
            'LOCATION': f'redis://{os.environ.get("DJANGO_REDIS_URL")}',
        }
    }


# -------------------------- 其他业务配置 --------------------------
# 多站点支持的站点ID（默认1，与django.contrib.sites配合使用）
SITE_ID = 1

# 百度链接提交URL：用于向百度搜索引擎提交新链接（SEO优化）
BAIDU_NOTIFY_URL = os.environ.get('DJANGO_BAIDU_NOTIFY_URL') or \
                   'http://data.zz.baidu.com/urls?site=https://www.lylinux.net&token=1uAOGrMsUm5syDGn'

# 时间格式：全局日期时间显示格式
TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
DATE_TIME_FORMAT = '%Y-%m-%d'

# Bootstrap颜色样式列表（用于文章标签、按钮等UI组件）
BOOTSTRAP_COLOR_TYPES = ['default', 'primary', 'success', 'info', 'warning', 'danger']

# 分页配置：每页显示的文章数量
PAGINATE_BY = 10

# X-Frame-Options配置：仅允许同域嵌入iframe（防点击劫持）
X_FRAME_OPTIONS = 'SAMEORIGIN'

# 默认自增字段类型（Django 3.2+新增，避免主键溢出）
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

# 微信管理员密码（两次MD5加密，用于微信后台管理验证）
WXADMIN = os.environ.get('DJANGO_WXADMIN_PASSWORD') or '995F03AC401D6CABABAEF756FC4D43C7'


# -------------------------- Elasticsearch配置（可选） --------------------------
# 若环境变量配置了Elasticsearch地址，则使用Elasticsearch作为搜索引擎（替代Whoosh）
if os.environ.get('DJANGO_ELASTICSEARCH_HOST'):
    ELASTICSEARCH_DSL = {
        'default': {'hosts': os.environ.get('DJANGO_ELASTICSEARCH_HOST')},
    }
    HAYSTACK_CONNECTIONS = {
        'default': {'ENGINE': 'djangoblog.elasticsearch_backend.ElasticSearchEngine'},
    }


# -------------------------- 日志配置 --------------------------
# 日志存储目录（项目根目录下的logs文件夹）
LOG_PATH = os.path.join(BASE_DIR, 'logs')
# 若目录不存在则创建（exist_ok=True避免重复创建报错）
if not os.path.exists(LOG_PATH):
    os.makedirs(LOG_PATH, exist_ok=True)

LOGGING = {
    'version': 1,  # 日志配置版本（固定为1）
    'disable_existing_loggers': False,  # 不禁用已存在的日志器
    'root': {  # 根日志器（所有未指定日志器的日志都会走这里）
        'level': 'INFO',  # 日志级别（INFO及以上会被记录）
        'handlers': ['console', 'log_file'],  # 日志处理器（控制台+文件）
    },
    'formatters': {  # 日志格式
        'verbose': {  # 详细格式（包含时间、级别、模块、行号等）
            'format': '[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d %(module)s] %(message)s',
        }
    },
    'filters': {  # 日志过滤器
        'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'},  # 仅DEBUG=False时生效
        'require_debug_true': {'()': 'django.utils.log.RequireDebugTrue'},   # 仅DEBUG=True时生效
    },
    'handlers': {  # 日志处理器（定义日志如何输出）
        'log_file': {  # 文件处理器（按天分割日志）
            'level': 'INFO',
            'class': 'logging.handlers.TimedRotatingFileHandler',  # 按时间轮转的文件处理器
            'filename': os.path.join(LOG_PATH, 'djangoblog.log'),  # 日志文件路径
            'when': 'D',  # 轮转周期（每天一个文件）
            'formatter': 'verbose',  # 使用详细格式
            'interval': 1,  # 轮转间隔（1天）
            'delay': True,  # 延迟创建文件（直到有日志时才创建）
            'backupCount': 5,  # 保留5个备份日志文件
            'encoding': 'utf-8'  # 日志文件编码
        },
        'console': {  # 控制台处理器（仅开发环境显示）
            'level': 'DEBUG',
            'filters': ['require_debug_true'],  # 仅DEBUG=True时生效
            'class': 'logging.StreamHandler',  # 输出到控制台
            'formatter': 'verbose'
        },
        'null': {'class': 'logging.NullHandler'},  # 空处理器（丢弃日志）
        'mail_admins': {  # 邮件处理器（发生ERROR时通知管理员）
            'level': 'ERROR',
            'filters': ['require_debug_false'],  # 仅生产环境（DEBUG=False）生效
            'class': 'django.utils.log.AdminEmailHandler'  # 发送邮件给ADMINS列表
        }
    },
    'loggers': {  # 自定义日志器（针对特定模块）
        'djangoblog': {  # 项目主模块日志
            'handlers': ['log_file', 'console'],
            'level': 'INFO',
            'propagate': True,  # 是否向上传递日志（到root日志器）
        },
        'django.request': {  # Django请求相关日志（如404、500错误）
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': False,  # 不向上传递（避免重复记录）
        }
    }
}


# -------------------------- 邮件配置 --------------------------
# 邮件后端（SMTP服务）
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# 是否使用TLS加密（与SSL二选一，根据邮件服务商配置）
EMAIL_USE_TLS = env_to_bool('DJANGO_EMAIL_TLS', False)
# 是否使用SSL加密（阿里云邮箱等常用465端口+SSL）
EMAIL_USE_SSL = env_to_bool('DJANGO_EMAIL_SSL', True)
# 邮件服务器地址（如阿里云邮箱为smtp.mxhichina.com）
EMAIL_HOST = os.environ.get('DJANGO_EMAIL_HOST') or 'smtp.mxhichina.com'
# 邮件服务器端口（SSL通常为465，TLS通常为587）
EMAIL_PORT = int(os.environ.get('DJANGO_EMAIL_PORT') or 465)
# 发送邮件的用户名（邮箱地址）
EMAIL_HOST_USER = os.environ.get('DJANGO_EMAIL_USER')
# 发送邮件的密码（邮箱授权码，非登录密码）
EMAIL_HOST_PASSWORD = os.environ.get('DJANGO_EMAIL_PASSWORD')
# 默认发件人（与EMAIL_HOST_USER一致）
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
# 管理员邮件（与ADMINS配合使用）
SERVER_EMAIL = EMAIL_HOST_USER

# 管理员列表：发生ERROR时会收到邮件通知
ADMINS = [('admin', os.environ.get('DJANGO_ADMIN_EMAIL') or 'admin@admin.com')]


# -------------------------- 插件系统配置 --------------------------
# 插件目录（项目根目录下的plugins文件夹）
PLUGINS_DIR = BASE_DIR / 'plugins'

# 激活的插件列表（按需启用，提供额外功能）
ACTIVE_PLUGINS = [
    'article_copyright',  # 文章版权声明
    'reading_time',       # 文章阅读时长估算
    'external_links',     # 外部链接处理（如添加nofollow）
    'view_count',         # 文章阅读量统计
    'seo_optimize'        # SEO优化（如自动生成meta标签）
]