import json

from django import forms
from django.contrib import admin
from django.db import models
from django.utils.safestring import mark_safe
from django_json_widget.widgets import JSONEditorWidget

from ..models.cacheconfig import CacheConfig
from .mixins import SingletonAdminMixin


@admin.register(CacheConfig)
class CacheConfigAdmin(SingletonAdminMixin, admin.ModelAdmin):
    formfield_overrides = {
        models.JSONField: {
            'widget':
            JSONEditorWidget(
                mode='code',  # 直接显示代码编辑模式
                options={
                    'modes': ['code'],  # 禁用模式切换
                    'theme': 'github',  # 更简洁的亮色主题
                    'lineNumbers': False,
                    'indentation': 2,
                    'autoFormat': True  # 自动格式化
                },
                height='400px',  # 适当降低高度
            )
        }
    }

    fieldsets = (
        ("", {
            'fields': (),
            'description':
            mark_safe('''<div class="alert alert-warning">
                      <p style="color: red; font-weight: bold;font-size:130%">重要提示：</p>
                      <p>缓存为底层操作，保存后系统会自动重启。重启系统后缓存数据是否消失取决于选择的缓存方式！</p>
                <p>• 内存缓存(locmem)：重启后数据丢失</p>
                <p>• Redis/数据库/文件缓存：数据会保留</p>
                <p>• Memcached：依赖服务配置</p>
                <p>按展示顺序缓存权重：整站缓存>模板缓存>视图缓存>。但模板缓存和视图缓存又是无关的两个缓存，具体细节需要细细体会。</p>
                      </div>''')
        }),
        (
            "模板缓存策略",
            {
                'description':
                mark_safe('''<div class="alert alert-info">
                        <p >模板缓存是不同视图缓存的，主要是在模板当中的使用的缓存。</p>
                        <p >程序查询数据后再用模板渲染，而模板渲染到某个有缓存的部分，就需要考虑这个缓存的时间有没有到期，如果没有到期，模板不接受渲染，按缓存内容继续下去。</p>
                        <p >设置思路：变化越快的页面建议缓存的时间越短。</p>
                        <p >比如文章边栏的最近更新文章，列表展示10条内容，1分钟发1条文章，10分钟的缓存就可以完成90%——100%的页面更新。</p>
                        <p >我们将模板结构大致分为上中下三部分，上下两部分，我们又分为了上中下三部分，主体部分我们分为了左右两部分，每部分又分为了三部分，细节如下，这样就基本满足了模板的需求</p>
                        </div>'''),
                'fields': (
                    ('top_main_timeout'),
                    ('top_top_timeout', 'top_center_timeout',
                     'top_bottom_timeout'),
                    ('body_main_timeout'),
                    ('body_left_main_timeout', 'body_left_top_timeout',
                     'body_left_center_timeout', 'body_left_bottom_timeout'),
                    (
                        'body_right_main_timeout',
                        'body_right_top_timeout',
                        'body_right_center_timeout',
                        'body_right_bottom_timeout',
                    ),
                    ('foot_main_timeout'),
                    ('foot_top_timeout', 'foot_center_timeout',
                     'foot_bottom_timeout'),
                ),
                # 'classes': ('collapse', )
            }),
        ("核心配置", {
            'description':
            mark_safe('''<div class="alert alert-info">
                        <p >使用标准JSON格式配置，支持多缓存后端设置。多注意单引号、逗号、注释等，这里很容易报错的地方。</p>
                        <p >部分缓存系统需要其他程序的配合。</p>
                        <p >默认为空，我们为您准备了locmem托底，请放心使用。</p>
                        <p style="color: red; font-weight: bold;font-size:130%;text-align: center;"><strong>重要提示：</strong></p>
                        <p style="text-align: center;">当你编辑过这里之后如果想清空这里请输入“{}”，以此来保证有json空值进入，否则依旧保存的旧值</p>
                        
                        </div>'''),
            'fields': ('caches_setting', ),
            'classes': ('collapse', )
        }),
        ("全站缓存配置", {
            'description':
            mark_safe('''<div class="alert alert-info">
                        <p >这里不是启动缓存，无论你启动还是不启动，其他缓存都可以正常运行。这里是指前整站前端所有页面全部进行缓存</p>
                        <p >这是一种非常霸道的缓存。</p>
                        <p >我们只负责帮你把程序准备好，具体的参数以上面核心配置-缓存配置json中的配置为准。如果在不设置缓存配置的情况下开启，默认为300秒，如需修改须将默认配置填入缓存配置当中然后修改timeout</p>
                        </div>'''),
            'fields': ('global_cache_enabled', ),
            'classes': ('collapse', )
        }),
        ("视图缓存策略", {
            'description':
            mark_safe('''<div class="alert alert-info">
                        <p >视图缓存可以按前端展示页面的类别去区分：比如栏目首页算频道页缓存，文章详情页算内容缓存。</p>
                        <p >设置思路：变化越快的页面建议缓存的时间越短。</p>
                        <p >比如栏目页，每页展示20条内容，1分钟发1条文章，20分钟的缓存就可以完成95%——100%的页面更新。</p>
                        </div>'''),
            'fields': (
                'index_timeout',
                'channel_timeout',
                'tag_timeout',
                'list_timeout',
                'item_timeout',
            ),
            'classes': ('collapse', )
        }),
    )

    def save_model(self, request, obj, form, change):
        #通过obj访问字段值
        raw_value = form.cleaned_data.get('caches_setting', {})
        # 空值过滤逻辑
        if isinstance(raw_value, str):
            if raw_value.strip() in ('', 'null', 'undefined'):
                obj.caches_setting = {
                    "default": {
                        "BACKEND":
                        "django.core.cache.backends.locmem.LocMemCache",
                        "LOCATION": "unique-snowflake",  # 需保持唯一性以区分多进程内存缓存‌
                        "TIMEOUT": 300,  # 默认缓存超时时间（秒）
                        "OPTIONS": {
                            "MAX_ENTRIES": 1000,  # 最大缓存条目数
                            "CULL_FREQUENCY": 3  # 缓存满时删除比例（1/3）
                        }
                    }
                }
            else:
                try:  # 手动解析字符串型输入
                    obj.caches_setting = json.loads(raw_value)
                except json.JSONDecodeError:
                    raise forms.ValidationError("非法的JSON格式")
        elif not isinstance(raw_value, dict):
            obj.caches_setting = {
                "default": {
                    "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
                    "LOCATION": "unique-snowflake",  # 需保持唯一性以区分多进程内存缓存‌
                    "TIMEOUT": 300,  # 默认缓存超时时间（秒）
                    "OPTIONS": {
                        "MAX_ENTRIES": 1000,  # 最大缓存条目数
                        "CULL_FREQUENCY": 3  # 缓存满时删除比例（1/3）
                    }
                }
            }
        super().save_model(request, obj, form, change)
        # # 写入静态文件
        # static_config_path = settings.BASE_DIR / 'config/caches.json'
        # try:
        #     with open(static_config_path, 'w', encoding='utf-8') as f:
        #         json.dump(obj.caches_setting, f, indent=2)
        # except Exception as e:
        #     print(f"缓存配置写入失败: {str(e)}")
