from __future__ import annotations

import json
from typing import Any

from django import forms
from django.contrib import admin
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _

try:
    from unfold.admin import ModelAdmin as UnfoldModelAdmin, TabularInline as UnfoldTabularInline
except ImportError:
    UnfoldModelAdmin = admin.ModelAdmin  # type: ignore[assignment]
    UnfoldTabularInline = admin.TabularInline  # type: ignore[assignment]

from simorgh.apps.notifications.models import (
    COUNTRY_DIAL_CODE_CHOICES,
    Notification,
    PushSubscription,
    SmsDeliveryLog,
    SmsProvider,
    SmsProviderTemplate,
    TenantSmsRateLimit,
    UserQuietHours,
)


# ---------------------------------------------------------------------------
# Notification admin
# ---------------------------------------------------------------------------

@admin.register(Notification)
class NotificationAdmin(UnfoldModelAdmin):
    list_display = (
        "created_at",
        "kind",
        "channel",
        "recipient",
        "tenant",
        "delivered_at",
        "read_at",
    )
    list_filter = ("channel", "kind", "tenant")
    search_fields = ("title", "kind")
    readonly_fields = ("public_id", "created_at", "updated_at", "delivered_at")
    ordering = ("-created_at",)


# ---------------------------------------------------------------------------
# SMS Provider country-code multi-select widget
# ---------------------------------------------------------------------------

class CountryCodeMultiSelectWidget(forms.CheckboxSelectMultiple):
    """Renders country code checkboxes grouped in a scrollable container."""

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        choices = [(code, label) for code, label in COUNTRY_DIAL_CODE_CHOICES]
        kwargs.setdefault("choices", choices)
        super().__init__(*args, **kwargs)

    class Media:
        css = {
            "all": []
        }


class SmsProviderAdminForm(forms.ModelForm):
    """Custom form that renders supported_country_codes as a checkbox list."""

    supported_country_codes_select = forms.MultipleChoiceField(
        choices=COUNTRY_DIAL_CODE_CHOICES,
        widget=CountryCodeMultiSelectWidget(),
        required=False,
        label=_("Supported country codes"),
        help_text=_(
            "Select the countries this provider handles. "
            "Leave empty to handle ALL countries (international fallback)."
        ),
    )

    class Meta:
        model = SmsProvider
        exclude: tuple[str, ...] = ("supported_country_codes",)

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        super().__init__(*args, **kwargs)
        if self.instance and self.instance.pk:
            existing = self.instance.get_supported_country_codes()
            self.fields["supported_country_codes_select"].initial = existing

    def save(self, commit: bool = True) -> SmsProvider:
        instance = super().save(commit=False)
        selected = self.cleaned_data.get("supported_country_codes_select") or []
        instance.supported_country_codes = list(selected)
        if commit:
            instance.save()
        return instance


# ---------------------------------------------------------------------------
# SmsProviderTemplate inline
# ---------------------------------------------------------------------------

class SmsProviderTemplateInline(UnfoldTabularInline):
    model = SmsProviderTemplate
    extra = 1
    fields = ("name", "provider_template_id", "params_schema", "is_default_otp")
    show_change_link = True


# ---------------------------------------------------------------------------
# SmsProvider admin
# ---------------------------------------------------------------------------

@admin.register(SmsProvider)
class SmsProviderAdmin(UnfoldModelAdmin):
    form = SmsProviderAdminForm
    inlines = [SmsProviderTemplateInline]
    list_display = (
        "name",
        "slug",
        "is_active",
        "priority",
        "country_codes_display",
        "created_at",
    )
    list_filter = ("is_active",)
    search_fields = ("name", "slug")
    readonly_fields = ("public_id", "created_at", "updated_at")
    ordering = ("-priority", "name")
    fieldsets = (
        (
            None,
            {
                "fields": (
                    "name",
                    "slug",
                    "description",
                    "is_active",
                    "priority",
                ),
            },
        ),
        (
            _("Credentials"),
            {
                "fields": ("credentials",),
                "description": _(
                    "JSON object with provider-specific secrets. "
                    "Example for SMS.ir: "
                    '{\"api_key\": \"YOUR_KEY\", \"line_number\": \"30004505001175\"}'
                ),
            },
        ),
        (
            _("Extra parameters"),
            {
                "fields": ("extra_params",),
                "description": _(
                    "JSON object with additional provider parameters. "
                    "Example for SMS.ir: "
                    '{\"otp_template_id\": 453080, \"otp_param_name\": \"Code\"}'
                ),
            },
        ),
        (
            _("Country routing"),
            {
                "fields": ("supported_country_codes_select",),
            },
        ),
        (
            _("Metadata"),
            {
                "fields": ("public_id", "created_at", "updated_at"),
                "classes": ("collapse",),
            },
        ),
    )

    @admin.display(description=_("Countries"))
    def country_codes_display(self, obj: SmsProvider) -> str:
        codes = obj.get_supported_country_codes()
        if not codes:
            return "🌐 All countries"
        return ", ".join(codes[:5]) + ("…" if len(codes) > 5 else "")


# ---------------------------------------------------------------------------
# SmsDeliveryLog admin
# ---------------------------------------------------------------------------

@admin.register(SmsDeliveryLog)
class SmsDeliveryLogAdmin(UnfoldModelAdmin):
    list_display = (
        "created_at",
        "mobile",
        "provider",
        "tenant",
        "status",
        "provider_message_id",
        "cost",
    )
    list_filter = ("status", "provider", "tenant")
    search_fields = ("mobile", "provider_message_id", "error_message")
    readonly_fields = (
        "public_id",
        "created_at",
        "updated_at",
        "mobile",
        "provider",
        "tenant",
        "message_text",
        "template_id",
        "status",
        "provider_message_id",
        "cost",
        "error_message",
        "raw_response_pretty",
    )
    ordering = ("-created_at",)
    date_hierarchy = "created_at"

    def has_add_permission(self, request: Any) -> bool:  # type: ignore[override]
        return False

    def has_change_permission(self, request: Any, obj: Any = None) -> bool:  # type: ignore[override]
        return False

    @admin.display(description=_("Raw response"))
    def raw_response_pretty(self, obj: SmsDeliveryLog) -> str:
        try:
            pretty = json.dumps(obj.raw_response, indent=2, ensure_ascii=False)
        except Exception:
            pretty = str(obj.raw_response)
        return format_html("<pre style='max-height:300px;overflow:auto'>{}</pre>", pretty)


# ---------------------------------------------------------------------------
# TenantSmsRateLimit admin
# ---------------------------------------------------------------------------

@admin.register(TenantSmsRateLimit)
class TenantSmsRateLimitAdmin(UnfoldModelAdmin):
    list_display = (
        "tenant",
        "max_per_minute",
        "max_per_hour",
        "max_per_day",
        "is_active",
        "updated_at",
    )
    list_filter = ("is_active",)
    search_fields = ("tenant__name",)
    readonly_fields = ("public_id", "created_at", "updated_at")


@admin.register(UserQuietHours)
class UserQuietHoursAdmin(UnfoldModelAdmin):
    list_display = ("user", "tenant", "start", "end", "is_enabled", "created_at")
    list_filter = ("is_enabled", "tenant")
    search_fields = ("user__username", "user__email")
    readonly_fields = ("public_id", "created_at", "updated_at")
    raw_id_fields = ("user",)


@admin.register(PushSubscription)
class PushSubscriptionAdmin(UnfoldModelAdmin):
    list_display = ("user", "tenant", "device_name", "is_active", "last_used_at", "created_at")
    list_filter = ("is_active", "tenant")
    search_fields = ("user__username", "user__email", "device_name")
    readonly_fields = ("public_id", "created_at", "updated_at")
    raw_id_fields = ("user",)
