"""Subscription Django admin registrations (Unfold)."""

from __future__ import annotations

from typing import ClassVar

from django import forms
from django.contrib import admin
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _

try:
    from unfold.admin import ModelAdmin as UnfoldModelAdmin
    from unfold.admin import TabularInline as UnfoldTabularInline
    from unfold.decorators import display
except ImportError:
    UnfoldModelAdmin = admin.ModelAdmin  # type: ignore[assignment]
    UnfoldTabularInline = admin.TabularInline  # type: ignore[assignment]

    def display(**kwargs):  # type: ignore[return-value]
        def decorator(fn):
            return fn
        return decorator

from simorgh.apps.subscription.models import (
    Addon,
    PlanFeature,
    PlatformPlan,
    TenantAddonFeature,
    TenantSubscription,
)

# Aliases for Phase B
Plan = PlatformPlan
PlanEntitlement = PlanFeature


# ---------------------------------------------------------------------------
# Feature tree widget — hierarchical checkbox selection
# ---------------------------------------------------------------------------

def _build_feature_tree() -> list[dict]:
    """Build Domain → Capability → Feature tree from the catalog."""
    from simorgh.apps.modules.models import Capability, Domain, FeatureCatalog

    tree: list[dict] = []
    domains = Domain.objects.prefetch_related("capabilities__features").order_by("sort_order", "code")

    for domain in domains:
        capabilities: list[dict] = []
        for cap in domain.capabilities.order_by("name"):
            features = list(
                cap.features.filter(is_always_on=False, is_platform_internal=False)
                .order_by("code")
                .values_list("code", "label")
            )
            if features:
                capabilities.append({
                    "name": cap.name,
                    "slug": cap.slug,
                    "features": [{"code": f[0], "label": f[1] or f[0]} for f in features],
                })
        if capabilities:
            tree.append({
                "id": f"domain-{domain.code}",
                "name": domain.name,
                "code": domain.code,
                "capabilities": capabilities,
            })
    return tree


class FeatureTreeWidget(forms.CheckboxSelectMultiple):
    """Renders features as a hierarchical checkbox tree: Domain → Capability → Feature."""

    template_name = "django/forms/widgets/checkbox_select.html"
    option_template_name = "django/forms/widgets/checkbox_option.html"

    def render(self, name, value, attrs=None, renderer=None):
        """Render the tree with cascading JavaScript."""
        if value is None:
            value = []
        tree = _build_feature_tree()

        html_parts = ['<div class="feature-tree" id="feature-tree">']

        for domain in tree:
            domain_id = domain["id"]
            html_parts.append(f'<div class="ft-domain" style="margin-bottom:12px;border:1px solid #e5e7eb;border-radius:6px;overflow:hidden">')
            # Domain header (level 1)
            html_parts.append(
                f'<label class="ft-domain-header" style="display:flex;align-items:center;gap:8px;padding:8px 12px;'
                f'background:#f3f4f6;cursor:pointer;font-weight:600;font-size:14px;border-bottom:1px solid #e5e7eb">'
                f'<input type="checkbox" class="ft-parent" data-target=".ft-domain-{domain["code"]}" '
                f'onchange="featureTreeCascade(this)" style="accent-color:#0ea5e9">'
                f'📁 {domain["name"]}</label>'
            )
            # Capabilities (level 2)
            html_parts.append(f'<div class="ft-domain-{domain["code"]}" style="padding:4px 0">')
            for cap in domain["capabilities"]:
                cap_id = f'{domain["code"]}-{cap["slug"]}'
                html_parts.append(
                    f'<div class="ft-capability" style="margin:2px 0">'
                    f'<label style="display:flex;align-items:center;gap:6px;padding:5px 12px 5px 24px;'
                    f'cursor:pointer;font-weight:500;font-size:13px;background:#f9fafb">'
                    f'<input type="checkbox" class="ft-parent" data-target=".ft-cap-{cap_id}" '
                    f'onchange="featureTreeCascade(this)" style="accent-color:#0ea5e9">'
                    f'📂 {cap["name"]}</label>'
                )
                # Features (level 3)
                html_parts.append(f'<div class="ft-cap-{cap_id}" style="padding:2px 0">')
                for feat in cap["features"]:
                    checked = 'checked' if feat["code"] in value else ''
                    html_parts.append(
                        f'<label style="display:flex;align-items:center;gap:6px;padding:3px 12px 3px 44px;'
                        f'cursor:pointer;font-size:12px;color:#374151">'
                        f'<input type="checkbox" name="{name}" value="{feat["code"]}" {checked} '
                        f'class="ft-leaf" data-parent=".ft-cap-{cap_id}" '
                        f'onchange="featureTreeUpdateParent(this)" style="accent-color:#0ea5e9">'
                        f'📄 {feat["label"]} <span style="color:#9ca3af;font-size:10px">({feat["code"]})</span></label>'
                    )
                html_parts.append('</div></div>')
            html_parts.append('</div></div>')

        html_parts.append('</div>')

        # JavaScript for cascading
        js = """
        <script>
        function featureTreeCascade(el) {
            const target = el.closest('.ft-domain, .ft-capability') || el.parentElement.parentElement;
            const container = target.querySelector(el.dataset.target);
            if (!container) return;
            const checkboxes = container.querySelectorAll('input[type="checkbox"]');
            checkboxes.forEach(cb => {
                cb.checked = el.checked;
                cb.dispatchEvent(new Event('change', {bubbles: true}));
            });
            // Update parent state
            featureTreeUpdateParent(el);
        }
        function featureTreeUpdateParent(el) {
            // Find the leaf's capability container, update its parent checkbox
            const capContainer = el.closest('[class*="ft-cap-"]');
            if (capContainer) {
                const capCheckbox = capContainer.parentElement.querySelector(':scope > label > input.ft-parent');
                if (capCheckbox) {
                    const children = capContainer.querySelectorAll('input[type="checkbox"]');
                    const allChecked = children.length > 0 && Array.from(children).every(c => c.checked);
                    const someChecked = Array.from(children).some(c => c.checked);
                    capCheckbox.checked = allChecked;
                    capCheckbox.indeterminate = someChecked && !allChecked;
                }
                // Now update the domain parent
                const domainContainer = capContainer.closest('[class*="ft-domain-"]');
                if (domainContainer) {
                    const domainCheckbox = domainContainer.parentElement.querySelector(':scope > label > input.ft-parent');
                    if (domainCheckbox) {
                        const domainChildren = domainContainer.querySelectorAll('input[type="checkbox"]');
                        const allChecked = domainChildren.length > 0 && Array.from(domainChildren).every(c => c.checked);
                        const someChecked = Array.from(domainChildren).some(c => c.checked);
                        domainCheckbox.checked = allChecked;
                        domainCheckbox.indeterminate = someChecked && !allChecked;
                    }
                }
            }
        }
        // Initialize parent states on page load
        document.addEventListener('DOMContentLoaded', function() {
            document.querySelectorAll('.ft-parent').forEach(cb => {
                const container = cb.closest('.ft-domain, .ft-capability');
                if (!container) return;
                const targetSelector = cb.dataset.target;
                if (!targetSelector) return;
                const target = container.querySelector(targetSelector);
                if (!target) return;
                const children = target.querySelectorAll('input[type="checkbox"]');
                const allChecked = children.length > 0 && Array.from(children).every(c => c.checked);
                const someChecked = Array.from(children).some(c => c.checked);
                cb.checked = allChecked;
                cb.indeterminate = someChecked && !allChecked;
            });
        });
        </script>
        <style>
        .feature-tree label:hover { background: #e0f2fe !important; }
        .feature-tree input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; }
        @media (prefers-color-scheme: dark) {
            .ft-domain { border-color: #374151 !important; }
            .ft-domain-header { background: #1f2937 !important; }
            .ft-capability label { background: #111827 !important; }
            .ft-leaf { color: #d1d5db !important; }
        }
        </style>
        """
        return mark_safe("".join(html_parts) + js)


class PlanForm(forms.ModelForm):
    """Custom form for PlatformPlan with hierarchical feature selection."""

    feature_selection = forms.MultipleChoiceField(
        label=_("فیچرهای پلن"),
        required=False,
        choices=[],  # populated in __init__
        widget=FeatureTreeWidget,
        help_text=_(
            "انتخاب سلسله‌مراتبی: با انتخاب هر دسته، تمام زیرمجموعه‌ها انتخاب می‌شوند. "
            "Domain ← Capability ← Feature"
        ),
    )

    class Meta:
        model = Plan
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Populate choices from tree for validation
        all_features: list[tuple[str, str]] = []
        for domain in _build_feature_tree():
            for cap in domain["capabilities"]:
                for feat in cap["features"]:
                    all_features.append((feat["code"], f'{feat["label"]} ({feat["code"]})'))
        self.fields["feature_selection"].choices = all_features

        # Pre-select currently linked features
        if self.instance and self.instance.pk:
            existing = PlanEntitlement.objects.filter(plan=self.instance).values_list("feature_key", flat=True)
            self.fields["feature_selection"].initial = list(existing)


# ---------------------------------------------------------------------------
# PlanEntitlement inline — kept as read-only summary after save
# ---------------------------------------------------------------------------

class PlanEntitlementInline(UnfoldTabularInline):
    model = PlanEntitlement
    extra = 0
    fields = ("feature_key", "enabled_by_default")
    readonly_fields = ("feature_key", "enabled_by_default")
    can_delete = True
    ordering = ("feature_key",)
    verbose_name = _("فیچر فعلی")
    verbose_name_plural = _("فیچرهای فعلی (فقط نمایشی)")

    def has_add_permission(self, request, obj=None):  # noqa: ARG002
        return False  # Add via the tree widget instead


@admin.register(Plan)
class PlanAdmin(UnfoldModelAdmin):
    form = PlanForm
    list_display = (
        "code",
        "name",
        "price_monthly",
        "currency",
        "user_limit",
        "storage_badge",
        "is_public",
        "is_active",
        "sort_order",
        "feature_count",
    )
    list_filter = ("is_active", "is_public", "currency")
    search_fields = ("code", "name")
    ordering = ("sort_order", "code")
    inlines: ClassVar[list] = [PlanEntitlementInline]
    readonly_fields = ("public_id", "created_at", "updated_at")
    fieldsets = (
        (None, {"fields": ("code", "name", "description")}),
        (
            _("قیمت‌گذاری"),
            {
                "fields": (
                    "price_monthly",
                    "price_yearly",
                    "currency",
                    "trial_days",
                )
            },
        ),
        (
            _("محدودیت‌ها"),
            {
                "fields": (
                    "user_limit",
                    "storage_gb",
                    "workflow_limit",
                    "api_calls_per_month",
                )
            },
        ),
        (
            _("فیچرهای پلن"),
            {
                "fields": ("feature_selection",),
                "description": _(
                    "فیچرها به صورت سلسله‌مراتبی نمایش داده می‌شوند. "
                    "با انتخاب یک Domain یا Capability، تمام زیرمجموعه‌ها انتخاب می‌شوند."
                ),
            },
        ),
        (_("نمایش"), {"fields": ("is_public", "is_active", "sort_order")}),
        (_("متادیتا"), {"fields": ("public_id", "created_at", "updated_at"), "classes": ("collapse",)}),
    )

    @display(description=_("فضا"))
    def storage_badge(self, obj: Plan) -> str:
        if obj.storage_gb == -1:
            return format_html(
                '<span style="background:#6b7280;color:#fff;padding:2px 8px;border-radius:4px;font-size:11px">∞</span>'
            )
        return f"{obj.storage_gb} GB"

    @display(description=_("تعداد فیچر"))
    def feature_count(self, obj: Plan) -> int:
        return obj.plan_features.count()

    def save_model(self, request, obj, form, change):
        """Save plan and sync PlanFeature entries from the tree widget."""
        super().save_model(request, obj, form, change)
        selected = form.cleaned_data.get("feature_selection", [])
        self._sync_features(obj, selected)

    def _sync_features(self, plan: Plan, selected_codes: list[str]):
        """Sync PlanFeature rows: delete removed, add new, keep existing."""
        existing = {fe.feature_key: fe for fe in PlanEntitlement.objects.filter(plan=plan)}
        selected_set = set(selected_codes)

        # Delete unchecked features
        to_delete = set(existing.keys()) - selected_set
        if to_delete:
            PlanEntitlement.objects.filter(plan=plan, feature_key__in=to_delete).delete()

        # Add new features
        to_add = selected_set - set(existing.keys())
        PlanEntitlement.objects.bulk_create([
            PlanEntitlement(plan=plan, feature_key=code, enabled_by_default=True)
            for code in to_add
        ])


@admin.register(TenantSubscription)
class TenantSubscriptionAdmin(UnfoldModelAdmin):
    list_display = (
        "tenant",
        "plan",
        "status_badge",
        "seat_count",
        "trial_ends_at",
        "current_period_end",
        "created_at",
    )
    list_filter = ("status", "plan")
    search_fields = ("tenant__slug", "tenant__name")
    raw_id_fields = ("tenant", "organization_node", "plan")
    readonly_fields = ("public_id", "created_at", "updated_at")
    fieldsets = (
        (None, {"fields": ("tenant", "plan", "status", "seat_count")}),
        (
            _("دوره"),
            {
                "fields": (
                    "trial_ends_at",
                    "current_period_start",
                    "current_period_end",
                )
            },
        ),
        (
            _("لغو اشتراک"),
            {
                "fields": ("cancelled_at", "cancellation_reason"),
                "classes": ("collapse",),
            },
        ),
        (
            _("متادیتا"),
            {"fields": ("organization_node", "public_id", "created_at", "updated_at"), "classes": ("collapse",)},
        ),
    )

    @display(description=_("وضعیت"))
    def status_badge(self, obj: TenantSubscription) -> str:
        colours = {
            "active": "#22c55e",
            "trial": "#3b82f6",
            "suspended": "#f59e0b",
            "expired": "#ef4444",
            "cancelled": "#6b7280",
        }
        colour = colours.get(obj.status, "#6b7280")
        return format_html(
            '<span style="background:{};color:#fff;padding:2px 8px;border-radius:4px;font-size:11px">{}</span>',
            colour,
            obj.get_status_display(),
        )


@admin.register(TenantAddonFeature)
class TenantAddonFeatureAdmin(UnfoldModelAdmin):
    list_display = (
        "tenant",
        "feature_key",
        "purchased_at",
        "expires_at",
        "price_paid",
        "active_badge",
    )
    list_filter: ClassVar[list] = []
    search_fields = ("tenant__slug", "feature_key")
    raw_id_fields = ("tenant", "organization_node")
    readonly_fields = ("public_id", "created_at", "updated_at")
    ordering = ("tenant__slug", "feature_key")

    @display(description=_("فعال"))
    def active_badge(self, obj: TenantAddonFeature) -> str:
        if obj.is_active:
            return format_html(
                '<span style="background:#22c55e;color:#fff;padding:2px 8px;border-radius:4px;font-size:11px">✓ فعال</span>'
            )
        return format_html(
            '<span style="background:#ef4444;color:#fff;padding:2px 8px;border-radius:4px;font-size:11px">✗ منقضی</span>'
        )


@admin.register(Addon)
class AddonAdmin(UnfoldModelAdmin):
    list_display = ("name", "code", "price_monthly", "is_active", "created_at")
    list_filter = ("is_active",)
    search_fields = ("name", "code")
    readonly_fields = ("public_id", "created_at", "updated_at")
    ordering = ("name",)


@admin.register(PlanFeature)
class PlanFeatureAdmin(UnfoldModelAdmin):
    list_display = ("plan", "feature_key", "enabled_by_default", "created_at")
    list_filter = ("plan",)
    search_fields = ("feature_key", "plan__name")
    readonly_fields = ("public_id", "created_at", "updated_at")
    ordering = ("plan", "feature_key")
