# admin.py
from apps.content.models.category import Category
from apps.content.models.download import Download, PlatformDownload
from django import forms
from django.contrib import admin
from django.core.exceptions import ValidationError
from django.db import models
from django.forms import FileInput
from django.utils.translation import gettext_lazy as _
from django_json_widget.widgets import JSONEditorWidget
from jsonschema import ValidationError, validate
from mptt.forms import TreeNodeChoiceField

from .mixins import SingletonAdminMixin

CHANNEL_SCHEMA = {
    "type": "object",
    "required": ["channel_type"],
    "properties": {
        "channel_type": {
            "enum":
            ["aws_s3", "aliyun_oss", "ftp", "huawei_obs", "local_storage"]
        },
        "bucket": {
            "type": "string"
        },  # 云存储类渠道必填
        "host": {
            "type": "string"
        },  # FTP类必填
        "base_path": {
            "type": "string"
        }  # 本地存储必填
    }
}


def validate_json_structure(value):
    """基础结构校验"""
    # 类型检查
    if not isinstance(value, dict):
        raise ValidationError('必须为键值对格式的JSON对象')

    # 空值校验
    if not value:
        raise ValidationError('配置内容不能为空')


# 模型字段应用
config = models.JSONField(validators=[validate_json_structure],
                          help_text="配置格式参考文档：hexlp.info")


class PlatformDownloadForm(forms.ModelForm):

    class Meta:
        model = PlatformDownload
        fields = '__all__'

    def clean_config(self):
        config = self.cleaned_data['config']
        try:
            validate(config, CHANNEL_SCHEMA)
        except ValidationError as e:
            raise forms.ValidationError(f"JSON 格式错误: {e.message}")
        return config


class PlatformDownloadInline(admin.StackedInline):
    model = PlatformDownload
    extra = 1
    form = PlatformDownloadForm  # 绑定自定义表单
    formfield_overrides = {
        models.JSONField: {
            'widget': JSONEditorWidget(mode='code')  # 仅保留必要参数
        }
    }

    # 字段分组展示
    fieldsets = ((_('基础信息'), {'fields': ('config', )}), )


class DownloadForm(forms.ModelForm):
    category = TreeNodeChoiceField(
        queryset=Category.objects.filter(content_type__model='dowanload'),
        label="栏目",
        help_text="选择树状栏目",
    )

    class Meta:
        model = Download
        fields = '__all__'
        widgets = {
            'file': FileInput(attrs={'accept': '.zip,.rar,.pdf,.doc,.docx'}),
        }


@admin.register(Download)
class DownloadAdmin(SingletonAdminMixin, admin.ModelAdmin):
    inlines = [PlatformDownloadInline]
    form = DownloadForm

    # 列表页配置

    list_filter = ('status', 'category', 'license_type', 'release_date',
                   'software_language')
    search_fields = ['title', 'version', 'meta_description']
    autocomplete_fields = ['category', 'related_tags']
    readonly_fields = ('download_count', 'file_size', 'file_type',
                       'update_time', "create_time")
    # 日期导航

    @property
    def date_hierarchy(self):
        """
        依赖 ContentConfig.get_solo() 方法自身的内置缓存。
        避免在模块加载时访问数据库，同时保证效率。
        """
        from apps.core.models.content_config import ContentConfig
        try:
            # 依赖于 get_solo() 方法内部的缓存实现
            content_config = ContentConfig.get_solo()
            if getattr(content_config, 'date_hierarchy', False):
                return 'release_date'
        except Exception:
            # 优雅处理异常，例如初次迁移时表可能不存在
            pass
        return None

    # 字段分组布局
    fieldsets = ((_('核心信息'), {
        'fields':
        ('title', 'py_title', 'status', 'category', 'content', 'thumb_image')
    }), (_('文件属性'), {
        'fields':
        ('file', ('file_size', 'file_type'), 'md5_hash', 'sha256_hash')
    }), (_('软件属性'), {
        'fields': (
            'software_language',
            'version',
            'license_type',
            'release_date',
        )
    }), (_('平台要求'), {
        'fields': ('support_platforms', ('windows_version', 'macos_version'),
                   'android_version')
    }), (_('下载渠道'), {
        'fields': ('official_website', 'mirror_download', 'cloud_download')
    }), (_('SEO设置'), {
        'classes': ('collapse', ),
        'fields':
        ('slug', 'meta_title', 'meta_description', 'meta_keywords',
         'canonical_url', ('og_title', 'og_description'), 'twitter_card_type')
    }), 
    # (_('内容关联'), {
    #     'classes': ('collapse', ),
    #     'fields': ('related_tags', )
    # }), 
    (_('发布控制'), {
        'classes': ('collapse', ),
        'fields': ('update_log', ('allow_comment', "is_top"), 'template',
                   'update_time', "create_time")
    }), (_('统计信息'), {
        'classes': ('collapse', ),
        'fields': ('download_count', "hits")
    }), ('权限控制', {
        'classes': ('collapse', ),
        'fields': ('staff_only', 'allowed_groups')
    }))

    # 自动填充逻辑
    def save_model(self, request, obj, form, change):
        """自动处理文件元数据"""
        if obj.file and not obj.file_size:
            obj.file_size = obj.file.size
            obj.file_type = obj.file.name.split('.')[-1].upper()
        super().save_model(request, obj, form, change)

    # 自定义动作
    actions = ['reset_download_count', 'make_published', 'archive_selected']

    @admin.action(description="重置下载计数器")
    def reset_download_count(self, request, queryset):
        queryset.update(download_count=0)

    @admin.action(description=_('发布选中条目'))
    def make_published(self, request, queryset):
        updated = queryset.update(status=99)
        self.message_user(request, f"成功发布 {updated} 个条目")

    @admin.action(description=_('归档选中条目'))
    def archive_selected(self, request, queryset):
        updated = queryset.update(status=6)
        self.message_user(request, f"已归档 {updated} 个条目")


# admin.site._registry[DownloadChannelType] = type(
#     'FakeAdmin', (admin.ModelAdmin, ),
#     {'has_module_permission': lambda *args: False})
