from apps.core.models.base import BaseModel
from django.contrib import admin, messages
from django.db.models import Count
from django.http import HttpResponseNotAllowed
from django.shortcuts import redirect
from django.urls import path, reverse
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from mptt.admin import DraggableMPTTAdmin

from ..models import Category  # 根据实际应用路径调整导入


@admin.register(Category)
class CategoryAdmin(DraggableMPTTAdmin):

    # 列表页显示字段配置
    list_display = (
        "id",
        "tree_actions",  # 拖拽操作图标
        "indented_title",  # 带缩进层级的标题
        # 'cate_type_with_color',  # 栏目类型（人类可读）
        "slug",
        "subdomain",
        "get_content_type_name",  # 替换原content_type
        "nav_status",
        "review_status",  # 审核状态
        "add_related_object_link",
        "get_status_stats",
    )

    # 可点击进入编辑页的字段
    list_display_links = ("indented_title",)

    # 列表页可直接编辑的字段
    list_editable = ("nav_status", "review_status")

    # 右侧过滤器
    list_filter = ("cate_type", "parent")

    # 搜索功能支持字段
    search_fields = ("name", "slug", "seo_title")

    # 自动填充 slug 规则
    # prepopulated_fields = {'slug': ('name', )}

    # 树形结构缩进像素（默认20）
    mptt_level_indent = 25
    mptt_indent_field = "indented_title"

    # 字段分组布局（编辑页）
    fieldsets = (
        (_("基础信息"), {"fields": ("name", "slug", "content_type", "parent", "review_status")}),
        (
            _("SEO 优化"),
            {
                "fields": ("seo_title", "keywords", "description"),
            },
        ),
        (
            _("更多"),
            {
                "fields": (
                    "subdomain",
                    "image",
                    "open_type",
                    "nav_status",
                    "index_template",
                    "content_template",
                    "notes",
                ),
                "classes": ("collapse",),  # 默认折叠
            },
        ),
        (_("权限控制"), {"classes": ("collapse",), "fields": ("staff_only", "allowed_groups")}),
    )

    @admin.display(description=_("模型类型"))
    def get_content_type_name(self, obj):
        name = ""
        try:
            name = obj.content_type.model_class()._meta.verbose_name
        except:
            name = "未知模型"
        return name

    @admin.display(description=_("状态统计"))
    def get_status_stats(self, obj):
        # 获取关联模型的所有实例
        model_class = obj.content_type.model_class()
        if not model_class:
            return ""

        # 统计各状态数量
        stats = (
            model_class.objects.filter(category=obj)
            .values("status")
            .annotate(count=Count("status"))
            .order_by("status")
        )

        # 通过累加stats中的count计算总数
        total = sum(item["count"] for item in stats)

        # 格式化输出
        if total > 0:
            output = []
            for stat in stats:
                status_name = dict(BaseModel.StatusChoices.choices).get(stat["status"], "未知")
                count = stat["count"]
                if stat["status"] == BaseModel.StatusChoices.STORED and 0 < count < 2000:
                    output.append(
                        f'<span class="text-danger fw-bold">{status_name}: {count}</span>'
                    )
                elif stat["status"] == BaseModel.StatusChoices.STORED and count < 2000:
                    output.append(f'<span class="text-success">{status_name}: {count}</span>')
                else:
                    output.append(f"{status_name}: {count}")

        return mark_safe(f"总数: {total} | " + " | ".join(output)) if total > 0 else ""

    # get_status_stats.short_description = ''
    # 自定义方法 - 带颜色的状态显示
    @admin.display(description=_("栏目类型"))
    def cate_type_with_color(self, obj):
        colors = {
            1: "#000",  # 普通栏目
            2: "#f0d6efd",  # 百科栏目
            3: "#d9534f",  # 下载栏目
            4: "#5cb85c",  # 专题栏目
        }
        icons = {1: "card-text", 2: "wikipedia", 3: "cloud-download", 4: "newspaper"}
        return format_html(
            '<span style="color: {};" class="bi bi-{}">{}</span>',
            colors.get(obj.cate_type, "#000"),
            icons.get(obj.cate_type, "list"),
            obj.get_cate_type_display(),
        )

    def image_preview(self, obj):
        """图片字段的预览"""
        if obj.image:
            return mark_safe(f'<img src="{obj.image.url}" style="max-height: 50px;" />')
        return "-"

    image_preview.short_description = _("图片预览")

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path(
                "rebuild-tree/",
                self.admin_site.admin_view(self.rebuild_tree),
                name="content_category_rebuild_tree",  # 名称修正
            ),
        ]
        return custom_urls + urls

    def rebuild_tree(self, request):
        # 权限校验
        if not request.user.has_perm("content.category.can_rebuild_tree"):
            self.message_user(request, "无权限执行此操作", messages.ERROR)
            return redirect("admin:content_category_changelist")

        # 方法校验
        if request.method != "POST":
            return HttpResponseNotAllowed(["POST"])

        # 业务逻辑
        try:
            Category.objects.rebuild()
            self.message_user(request, "树结构重建成功", messages.SUCCESS)
        except Exception as e:
            self.message_user(request, f"重建失败: {str(e)}", messages.ERROR)

        return redirect("admin:content_category_changelist")

    def add_related_object_link(self, obj):
        html = ""
        item_url = Category.get_absolute_url(obj)
        add_url = reverse("admin:content_category_add")
        html += f'<li class="breadcrumb-item"><a href="{add_url}?parent_id={obj.id}">添加栏目</a></li><li class="breadcrumb-item"><a href="{item_url}" target="_blank">前端浏览</a></li>'

        # 获取关联模型的元信息
        model = obj.content_type.model_class()
        app_label = obj.content_type.app_label

        # 自动生成添加和列表链接
        try:
            add_url = reverse(f"admin:{app_label}_{model._meta.model_name}_add")
            list_url = reverse(f"admin:{app_label}_{model._meta.model_name}_changelist")
            html += f'<li class="breadcrumb-item"><a href="{add_url}?category_id={obj.id}">添加{model._meta.verbose_name}</a></li>'
            html += f'<li class="breadcrumb-item"><a href="{list_url}?category__id__exact={obj.id}">{model._meta.verbose_name_plural}</a></li>'
        except:
            add_url = ""
            list_url = ""
        if obj.notes:
            html += f'<li class="breadcrumb-item"><sapn data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-title="{obj.notes}"><i class="bi bi-sticky-fill text-primary" ></i></sapn></li>'

        nav_html = f"""<nav aria-label="breadcrumb">
                    <ol class="breadcrumb">
                        {html}
                    </ol>
                    </nav>"""
        return format_html(nav_html)

    add_related_object_link.short_description = "操作"
    add_related_object_link.allow_tags = True

    def changelist_view(self, request, extra_context=None):
        extra_context = extra_context or {}

        # 动态传递权限标记
        has_permission = request.user.has_perm("content.category.can_rebuild_tree")
        extra_context["has_rebuild_permission"] = has_permission

        # 生成带 CSRF 的 POST 表单按钮
        if has_permission:
            from django.middleware.csrf import get_token

            rebuild_url = reverse("admin:content_category_rebuild_tree")
            csrf_token = get_token(request)  # 获取当前请求的 CSRF Token
            button_html = f"""
            <form action="{rebuild_url}" method="POST" style="display:inline;">
                <input type="hidden" name="csrfmiddlewaretoken" value="{csrf_token}">
                <button type="submit" class="button">重建树结构</button>
            </form>
        """
            extra_context["rebuild_button"] = mark_safe(button_html)

        return super().changelist_view(request, extra_context=extra_context)

    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        # 捕获 URL 中的 category_id 参数
        parent_id = request.GET.get("parent_id")
        if parent_id:
            # 将参数注入表单字段初始值
            form.base_fields["parent"].initial = Category.objects.get(id=parent_id)
        return form
