import json

from django.contrib import admin, messages
from django.utils import timezone
from django.utils.html import format_html

from system_logs.models import SystemLog

_LEVEL_COLOURS = {
    SystemLog.LEVEL_INFO: ("#e3f2fd", "#1565c0"),
    SystemLog.LEVEL_WARNING: ("#fff3e0", "#a35c00"),
    SystemLog.LEVEL_ERROR: ("#fdecea", "#b71c1c"),
}


def _pretty_json(value):
    if value in (None, "", {}, []):
        return "—"
    return format_html(
        '<pre style="white-space:pre-wrap;max-height:420px;overflow:auto;margin:0;'
        'background:#f7f7f7;padding:10px;border-radius:4px;font-size:12px;">{}</pre>',
        json.dumps(value, indent=2, ensure_ascii=False, default=str),
    )


class UnresolvedProblemsFilter(admin.SimpleListFilter):
    title = "needs attention"
    parameter_name = "attention"

    def lookups(self, request, model_admin):
        return [("yes", "Unresolved warnings & errors")]

    def queryset(self, request, queryset):
        if self.value() == "yes":
            return queryset.filter(
                resolved=False, level__in=[SystemLog.LEVEL_WARNING, SystemLog.LEVEL_ERROR],
            )
        return queryset


@admin.register(SystemLog)
class SystemLogAdmin(admin.ModelAdmin):
    """
    Read-only except "resolved" + notes. Visible to superusers; grant the
    system_logs view/change permissions to a group to open it to a role.
    """
    list_display = (
        "created_at", "level_badge", "module", "event", "short_message",
        "reference", "phone_number", "mpesa_receipt", "resolved",
    )
    list_filter = (UnresolvedProblemsFilter, "level", "module", "resolved", "created_at")
    search_fields = (
        "reference", "checkout_request_id", "phone_number", "mpesa_receipt",
        "event", "message", "related_id",
    )
    date_hierarchy = "created_at"
    list_per_page = 50
    actions = ["mark_resolved"]
    readonly_fields = (
        "created_at", "level", "module", "event", "message", "reference",
        "checkout_request_id", "phone_number", "mpesa_receipt", "related_model", "related_id",
        "http_status", "request_pretty", "response_pretty", "traceback_pretty",
        "user", "alert_sent_at", "resolved_by", "resolved_at",
    )
    fieldsets = (
        (None, {"fields": ("created_at", "level", "module", "event", "message", "user")}),
        ("References", {"fields": (
            "reference", "checkout_request_id", "phone_number", "mpesa_receipt",
            "related_model", "related_id",
        )}),
        ("What was sent and received", {"fields": ("http_status", "request_pretty", "response_pretty")}),
        ("Error", {"fields": ("traceback_pretty",)}),
        ("Follow-up", {"fields": ("alert_sent_at", "resolved", "resolution_notes", "resolved_by", "resolved_at")}),
    )

    @admin.display(description="Level", ordering="level")
    def level_badge(self, obj):
        bg, fg = _LEVEL_COLOURS.get(obj.level, ("#eee", "#333"))
        return format_html(
            '<span style="background:{};color:{};padding:2px 8px;border-radius:3px;font-weight:bold;'
            'font-size:11px;">{}</span>', bg, fg, obj.get_level_display(),
        )

    @admin.display(description="Message")
    def short_message(self, obj):
        return obj.message if len(obj.message) <= 90 else obj.message[:90] + "…"

    @admin.display(description="Request sent")
    def request_pretty(self, obj):
        return _pretty_json(obj.request_data)

    @admin.display(description="Response received")
    def response_pretty(self, obj):
        return _pretty_json(obj.response_data)

    @admin.display(description="Traceback")
    def traceback_pretty(self, obj):
        if not obj.traceback:
            return "—"
        return format_html(
            '<pre style="white-space:pre-wrap;max-height:420px;overflow:auto;margin:0;'
            'background:#fdf3f2;padding:10px;border-radius:4px;font-size:12px;">{}</pre>',
            obj.traceback,
        )

    @admin.action(description="Mark selected as resolved")
    def mark_resolved(self, request, queryset):
        updated = queryset.filter(resolved=False).update(
            resolved=True, resolved_by=request.user, resolved_at=timezone.now(),
        )
        messages.success(request, f"{updated} entr{'y' if updated == 1 else 'ies'} marked resolved.")

    def save_model(self, request, obj, form, change):
        if "resolved" in form.changed_data:
            obj.resolved_by = request.user if obj.resolved else None
            obj.resolved_at = timezone.now() if obj.resolved else None
        super().save_model(request, obj, form, change)

    def has_add_permission(self, request):
        return False

    def has_delete_permission(self, request, obj=None):
        # Entries are removed only by the retention job (prune_system_logs).
        return False
