# 在自定义模板标签文件中（如templatetags/site_info.py）
import sys
from datetime import datetime, timedelta

import distro
import django
import psutil  # 需额外安装
from apps.comments.models import Comment
from apps.core.models.admin_settings import AdminSettings
from apps.core.utils.djacore import validate_vip_auth
from apps.upgrade.utils import get_latest_version
from django import template
from django.conf import settings
from django.contrib.auth.models import User
from django.core.cache import cache
from django.db.models import Count
from django.db.models.functions import TruncDate
from django.utils import timezone
from django.utils.safestring import mark_safe

register = template.Library()


@register.simple_tag
def get_system_info():
    """获取系统环境信息"""
    # 预加载避免多次调用
    mem = psutil.virtual_memory()
    disk = psutil.disk_usage("/")
    cpu_percent = psutil.cpu_percent()

    def get_color(value):
        """根据负载值返回颜色类"""
        if value >= 80:
            return "text-danger"  # 红色高负载
        elif value >= 60:
            return "text-warning"  # 黄色警告
        else:
            return "text-success"  # 绿色正常

    # 获取数据库信息
    from django.db import connection

    db_info = "未知数据库"
    try:
        with connection.cursor() as cursor:
            if "postgresql" in connection.vendor:
                cursor.execute("SELECT version()")
                db_info = f"PostgreSQL {cursor.fetchone()[0].split()[1]}"
            elif "mysql" in connection.vendor:
                cursor.execute("SELECT VERSION()")
                db_info = f"MySQL {cursor.fetchone()[0].split('-')[0]}"
            elif "sqlite" in connection.vendor:
                import sqlite3

                db_info = f"SQLite {sqlite3.sqlite_version}"
            elif "oracle" in connection.vendor:
                cursor.execute("SELECT * FROM v$version")
                db_info = f"Oracle {cursor.fetchone()[0].split()[-1]}"
            elif "sqlserver" in connection.vendor:
                cursor.execute("SELECT @@VERSION")
                db_info = f"SQL Server {cursor.fetchone()[0].split()[3]}"
    except Exception as e:
        db_info = f"数据库检测失败: {str(e)}"
    # 获取SECRET_KEY状态
    secret_key_info = get_secret_key_status()

    return {
        "系统": f"{distro.id()} {distro.version()}",
        "python版本": sys.version.split()[0],
        "django版本": django.get_version(),
        "数据库": db_info,
        "CPU": (
            f"{psutil.cpu_count(logical=False)}核"
            f'<span class="ms-3 {get_color(cpu_percent)}">{cpu_percent}%</span>'
        ),
        "内存": (
            f"{round(mem.total / (1024**3),1)}GB"
            f'<span class="ms-3 {get_color(mem.percent)}">{mem.percent}%</span>'
        ),
        "存储使用": (
            f"{round(disk.total / (1024**3), 1)}GB"
            f'<span class="ms-3 {get_color(disk.percent)}">{disk.percent}%</span>'
        ),
        "SECRET_KEY状态": secret_key_info,
    }


def get_secret_key_status():
    """获取SECRET_KEY状态信息（简化的公开信息）"""
    try:
        from apps.core.utils.secret_manager import secret_manager

        info = secret_manager.get_secret_info()
        days = info.get("key_age_days", 0)
        status = info.get("status", "unknown")
        using_default = info.get("using_default", False)

        # 状态判断
        if using_default:
            status_text = "默认密钥"
            status_color = "warning"
            icon = "⚠️"
            badge_class = "badge bg-warning"
            show_reset = True
            reset_class = "btn-danger"
        elif status == "expired":
            status_text = f"{days}天（已过期）"
            status_color = "danger"
            icon = "❌"
            badge_class = "badge bg-danger"
            show_reset = True
            reset_class = "btn-danger"
        elif status == "warning":
            status_text = f"{days}天（即将过期）"
            status_color = "warning"
            icon = "⚠️"
            badge_class = "badge bg-warning"
            show_reset = True
            reset_class = "btn-warning"
        elif status == "healthy":
            status_text = f"{days}天（正常）"
            status_color = "success"
            # icon = "✅"
            icon = "✅"
            # badge_class = "badge bg-success"
            badge_class = ""
            show_reset = False  # 状态正常时不显示重置按钮
            reset_class = "btn-outline-secondary"
        else:
            status_text = "状态未知"
            status_color = "secondary"
            icon = "❓"
            badge_class = "badge bg-secondary"
            show_reset = True
            reset_class = "btn-secondary"

        # 生成HTML
        html = f'<span class="{badge_class} me-2">{icon} {status_text}</span>'

        if show_reset:
            html += f"""
            <button type="button" 
                    class="btn btn-sm {reset_class} p-0" 
                    data-bs-toggle="modal" 
                    data-bs-target="#secretKeyModal"
                    title="重置SECRET_KEY">
                <i class="bi bi-arrow-clockwise"></i> 重置
            </button>
            """

        return mark_safe(html)

    except ImportError:
        return mark_safe('<span class="badge bg-secondary">状态未知</span>')
    except Exception as e:
        return mark_safe(f'<span class="badge bg-secondary">错误</span>')


@register.simple_tag
def get_server_load():
    return {}


@register.simple_tag
def get_auth_status():
    """
    获取当前授权状态的API接口
    """
    is_valid, auth_info, message = validate_vip_auth()

    return {
        "is_valid": is_valid,
        "message": message,
        "auth_info": auth_info if is_valid else None,
        "checked_at": datetime.now().isoformat(),
    }


@register.simple_tag
def get_content_stats(exclude_models=[]):
    """获取内容统计数据:ml-citation{ref="7" data="citationList"}"""

    admin_settings = AdminSettings.get_solo()
    data = {
        "用户": User.objects.count(),
        # '': Article.objects.count(),
        "评论": Comment.objects.count(),
        # '标签': Tag.objects.count()
    }
    # 自动获取content应用下的所有模型
    show_models = admin_settings.get_stat_models()

    for model in show_models:
        if model.__name__ in exclude_models:  # 新增排除判断:
            continue
        try:
            verbose_name = model._meta.verbose_name
            if model.__name__ == "Tag":
                from apps.content.models import Tag

                data[verbose_name] = Tag.get_total_count()
            else:
                data[verbose_name] = model.objects.count()
        except:
            pass
    return data
    # return {}


@register.simple_tag
def get_cms_version():
    """获取CMS版本信息"""
    try:
        from config.config import SystemConfig

        current_version_str = SystemConfig.VERSION.lstrip("Vv")  # 确保去除前缀
        try:
            # 获取并处理版本号
            raw_latest, data = get_latest_version()

            latest_version_str = raw_latest.lstrip("Vv")

            if latest_version_str == "0.0.0":
                notice = f"版本检测失败"

            # 版本号有效性验证
            def is_valid_version(v):
                base_ok = all(c.isdigit() or c in (".", "_", "p") for c in v)
                struct_ok = (v.count(".") >= 2) or (  # 主版本号 1.0.0
                    "_p" in v and v.split("_p")[0].count(".") >= 2
                )  # 补丁版本 1.0.0_p1
                return base_ok and struct_ok

            if not all(map(is_valid_version, [current_version_str, latest_version_str])):
                raise ValueError("版本号格式不符合要求")

            # 版本号解析比较（支持主版本和补丁版本）
            def parse_version(v):
                main_part, patch = v.split("_p") if "_p" in v else (v, "0")
                main_numbers = list(map(int, main_part.split(".")[:3]))  # 取前三位
                return main_numbers + [int(patch)]

            current_ver = parse_version(current_version_str)
            latest_ver = parse_version(latest_version_str)

            # 按顺序比较主版本和补丁号
            can_upgrade = latest_ver > current_ver
            return current_version_str, can_upgrade
        except:
            return current_version_str, False

    except:

        return getattr(settings, "VERSION", "1.0.0"), False


def get_daily_stats(model_class, days=7):
    """获取指定模型近N天每日发布数量"""
    cache_key = f"stats:{model_class._meta.label_lower}:{days}"
    cached = cache.get(cache_key)
    if cached:
        return cached
    end_date = timezone.now()
    start_date = end_date - timedelta(days=days - 1)

    queryset = (
        model_class.objects.filter(update_time__gte=start_date, status=99)
        .annotate(date=TruncDate("update_time"))
        .values("date")
        .annotate(count=Count("id"))
    )

    # 正确写法：直接使用date字段作为键
    date_counts = {item["date"]: item["count"] for item in queryset}

    # 填充缺失日期
    date_range = [start_date.date() + timedelta(days=i) for i in range(days)]

    result = {
        "dates": [d.strftime("%m-%d") for d in date_range],
        "counts": [date_counts.get(d, 0) for d in date_range],
        "verbose_name": model_class._meta.verbose_name,
        "model_name": model_class._meta.model_name,
    }
    cache.set(cache_key, result, timeout=3600)  # 缓存1小时
    return result


@register.inclusion_tag("admin/stats/chart_block.html")
def recent_publish_charts():
    """生成所有模型的统计图表"""
    charts_data = []
    # 获取content应用中的所有模型
    admin_settings = AdminSettings.get_solo()
    update_models, days = admin_settings.get_update_models()
    # data={
    #     '用户': User.objects.count(),
    #     # '': Article.objects.count(),
    #     '评论': Comment.objects.count(),
    #     '标签': Tag.objects.count()
    # }

    for model in update_models:
        try:
            # 验证必须字段存在
            if all(hasattr(model, f) for f in ["status", "update_time"]):
                charts_data.append(get_daily_stats(model, days))
        except LookupError:
            continue
    return {"charts_data": charts_data}


@register.inclusion_tag("admin/stats/pie_chart.html")
def combined_pie_charts():
    """基于分类模型生成状态分布饼图"""
    chart_title = []
    chart_status = []
    chart_cate = []
    # 获取所有符合条件的分组分类
    from apps.content.models.category import Category

    categories = Category.objects.filter(
        content_type__app_label="content",
    ).select_related("content_type")
    formatted_data_list = []
    for category in categories:
        chart_title.append(category.name)
        model_class = category.content_type.model_class()

        # 获取状态统计数据
        status_stats = (
            model_class.objects.filter(category=category)
            .values("status")
            .annotate(count=Count("id"))
            .order_by("status")
        )

        # 转换状态值为中文
        status_mapping = dict(model_class.StatusChoices.choices)
        formatted_data = [
            {"name": str(status_mapping.get(item["status"], "未知状态")), "value": item["count"]}
            for item in status_stats
        ]
        mes = ""
        for item in status_stats:
            mes += f'{str(status_mapping.get(item["status"], "未知状态"))}:{item["count"]}；'

        formatted_data_list.append(formatted_data)
        # 计算分类总内容数
        total = sum(item["value"] for item in formatted_data)
        total_data = {
            "value": total,
            "name": f"{category.name}({category.content_type_chinese_name})",
            "mes": mes,
        }
        chart_cate.append(total_data)
    merged_data = []
    for data_group in formatted_data_list:
        merged_data.extend(data_group)
    result = {}
    for item in merged_data:
        key = item["name"]
        # 同名键值累加
        result[key] = result.get(key, 0) + item["value"]

    chart_status = [{"name": k, "value": v} for k, v in result.items()]
    return {"chart_status": chart_status, "chart_title": chart_title, "chart_cate": chart_cate}


from apps.oplog.models import oplog


@register.simple_tag
def admin_index_oplog_list(shownum=5):
    return oplog.objects.order_by("-create_time")[:shownum]
