from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from .models import (
    Control,
    ImpactChoice,
    Incident,
    LikelihoodChoice,
    Notification,
    NotificationPreference,
    NotificationRule,
    Risk,
    ResidualRisk,
    User,
)

# ---------------------------------------------------------------------------
# Global Admin Settings
# ---------------------------------------------------------------------------
admin.site.site_header = _("Administration")
admin.site.site_title = _("Admin")
admin.site.index_title = _("Administration")


# ---- Inlines ----
class NotificationPreferenceInline(admin.StackedInline):
    """Preferences inline for notifications on User model"""
    model = NotificationPreference
    can_delete = False
    extra = 0
    fieldsets = (
        (_("Risks"), {"fields": ("risk_created", "risk_updated", "risk_deleted")}),
        (_("Controls"), {"fields": ("control_created", "control_updated", "control_deleted")}),
        (_("Residual risks"), {"fields": ("residual_created", "residual_updated", "residual_deleted")}),
        (_("Reviews"), {"fields": ("review_required", "review_completed")}),
        (_("Incidents"), {"fields": ("incident_created", "incident_updated", "incident_deleted")}),
        (_("Users"), {"fields": ("user_created", "user_deleted")}),
    )


class ResidualRiskInline(admin.StackedInline):
    """Inline editor for ResidualRisk (one-to-one with Risk)"""
    model = ResidualRisk
    extra = 0
    can_delete = False
    readonly_fields = ("score", "level", "review_required")
    fields = ("likelihood", "impact", "score", "level", "review_required")


class ControlRisksInline(admin.TabularInline):
    """M2M relation between Risk and Control"""
    model = Control.risks.through
    fk_name = "risk"
    extra = 1
    autocomplete_fields = ("control",)


class NotificationInline(admin.TabularInline):
    """Inline display of notifications on User model"""
    model = Notification
    fields = ("created_at", "message", "read", "sent")
    readonly_fields = ("created_at", "message")
    extra = 0
    ordering = ("-created_at",)


# ---- Shared Mixins ----
class ChangedByMixin:
    """Automatically track user who created/changed/deleted"""
    def save_model(self, request, obj, form, change):
        obj._changed_by = request.user
        super().save_model(request, obj, form, change)

    def delete_model(self, request, obj):
        obj._changed_by = request.user
        super().delete_model(request, obj)


class RedirectOnSaveMixin:
    """Redirect to detail view instead of staying in admin"""
    redirect_url_name = None

    def response_add(self, request, obj, post_url_continue=None):
        return HttpResponseRedirect(reverse(self.redirect_url_name, args=[obj.pk]))

    def response_change(self, request, obj):
        return HttpResponseRedirect(reverse(self.redirect_url_name, args=[obj.pk]))


# ---------------------------------------------------------------------------
# Risk
# ---------------------------------------------------------------------------
@admin.register(Risk)
class RiskAdmin(ChangedByMixin, RedirectOnSaveMixin, admin.ModelAdmin):
    redirect_url_name = "risks:show_risk"
    list_display = ("title", "owner_name", "score", "level", "likelihood", "impact", "follow_up", "status")
    list_filter = ("status", "level", "likelihood", "impact", "owner")
    search_fields = ("title", "asset", "process", "category")
    inlines = [ResidualRiskInline, ControlRisksInline]

    def owner_name(self, obj):
        if not obj.owner:
            return "-"
        return obj.owner.get_full_name() or obj.owner.username


# ---------------------------------------------------------------------------
# Residual Risk
# ---------------------------------------------------------------------------
@admin.register(ResidualRisk)
class ResidualRiskAdmin(ChangedByMixin, RedirectOnSaveMixin, admin.ModelAdmin):
    redirect_url_name = "risks:show_risk"
    list_display = ("risk", "score", "level", "likelihood", "impact", "review_required")
    list_filter = ("level", "likelihood", "impact", "review_required")


# ---------------------------------------------------------------------------
# Control
# ---------------------------------------------------------------------------
@admin.register(Control)
class ControlAdmin(ChangedByMixin, RedirectOnSaveMixin, admin.ModelAdmin):
    redirect_url_name = "risks:show_control"
    list_display = ("title", "status", "due_date", "responsible")
    list_filter = ("status", "due_date")
    autocomplete_fields = ("risks", "responsible")
    search_fields = ("title", "description")


# ---------------------------------------------------------------------------
# Incident
# ---------------------------------------------------------------------------
@admin.register(Incident)
class IncidentAdmin(ChangedByMixin, RedirectOnSaveMixin, admin.ModelAdmin):
    redirect_url_name = "risks:show_incident"
    list_display = ("title", "date_reported", "reported_by", "status")
    list_filter = ("status", "date_reported", "reported_by")
    search_fields = ("title", "description")
    autocomplete_fields = ("related_risks",)
    filter_horizontal = ("related_risks",)

    def get_changeform_initial_data(self, request):
        initial = super().get_changeform_initial_data(request)
        risk_id = request.GET.get("related_risks")
        if risk_id:
            initial["related_risks"] = [risk_id]
        return initial


# ---------------------------------------------------------------------------
# Notification
# ---------------------------------------------------------------------------
@admin.register(Notification)
class NotificationAdmin(admin.ModelAdmin):
    date_hierarchy = "created_at"
    list_display = ("id", "created_at", "user_display", "short_message", "read", "sent")
    list_display_links = ("id", "short_message")
    list_filter = ("read", "sent", "created_at")
    search_fields = ("message", "user__username", "user__first_name", "user__last_name", "user__email")
    list_select_related = ("user",)
    list_editable = ("read", "sent")
    ordering = ("-created_at",)
    autocomplete_fields = ("user",)
    actions = ["mark_as_read", "mark_as_unread", "mark_as_sent", "mark_as_unsent"]

    @admin.display(description=_("User"))
    def user_display(self, obj):
        return obj.user.get_full_name() if obj.user else "—"

    @admin.display(description=_("Message"))
    def short_message(self, obj):
        msg = obj.message or ""
        return (msg[:80] + "…") if len(msg) > 80 else msg

    # Bulk actions
    @admin.action(description=_("Mark selected as read"))
    def mark_as_read(self, request, queryset):
        n = queryset.update(read=True)
        self.message_user(request, _("%(n)d notifications marked as read.") % {"n": n})

    @admin.action(description=_("Mark selected as unread"))
    def mark_as_unread(self, request, queryset):
        n = queryset.update(read=False)
        self.message_user(request, _("%(n)d notifications marked as unread.") % {"n": n})

    @admin.action(description=_("Mark selected as sent"))
    def mark_as_sent(self, request, queryset):
        n = queryset.update(sent=True)
        self.message_user(request, _("%(n)d notifications marked as sent.") % {"n": n})

    @admin.action(description=_("Mark selected as unsent"))
    def mark_as_unsent(self, request, queryset):
        n = queryset.update(sent=False)
        self.message_user(request, _("%(n)d notifications marked as unsent.") % {"n": n})


# ---- Notification Rule ----
@admin.register(NotificationRule)
class NotificationRuleAdmin(admin.ModelAdmin):
    list_display = ("kind", "enabled_in_app", "enabled_email", "to_owner", "to_staff", "short_extras")
    list_editable = ("enabled_in_app", "enabled_email", "to_owner", "to_staff")
    list_filter = ("enabled_in_app", "enabled_email", "to_owner", "to_staff")
    search_fields = ("kind", "extra_recipients")
    ordering = ("kind",)

    @admin.display(description=_("Extra recipients"))
    def short_extras(self, obj):
        txt = (obj.extra_recipients or "").replace("\n", ", ")
        return (txt[:50] + "…") if len(txt) > 50 else txt


# ---------------------------------------------------------------------------
# User (extension)
# ---------------------------------------------------------------------------
@admin.register(User)
class UserAdmin(BaseUserAdmin):
    fieldsets = BaseUserAdmin.fieldsets + (
        (_("SSO Information"), {"fields": ("is_sso_user",)}),
    )
    list_display = (
        "username", "email", "is_staff", "is_superuser", "is_sso_user",
        "owned_risks_count", "responsible_controls_count"
    )
    inlines = [NotificationInline, NotificationPreferenceInline]

    def owned_risks_count(self, obj):
        return obj.risks_owned.count()
    owned_risks_count.short_description = _("Risks Owned")

    def responsible_controls_count(self, obj):
        return obj.controls_responsible.count()
    responsible_controls_count.short_description = _("Controls Responsible")


# ---------------------------------------------------------------------------
# LikelihoodChoice
# ---------------------------------------------------------------------------
@admin.register(LikelihoodChoice)
class LikelihoodChoiceAdmin(admin.ModelAdmin):
    list_display = ("value", "name", "description")

# ---------------------------------------------------------------------------
# ImpactChoice
# ---------------------------------------------------------------------------
@admin.register(ImpactChoice)
class ImpactChoiceAdmin(admin.ModelAdmin):
    list_display = ("value", "name", "description")