"""
store/admin.py
──────────────
Django admin registration for the store app.

Key admin features
──────────────────
• OrderAdmin: inline order items, read-only payment fields, list actions for
  updating order status in bulk.
• MpesaTransactionAdmin: fully read-only audit log.
• CouponAdmin: inline coupon usage stats.
• DeliveryArea / PickupLocation: simple CRUD with county grouping.
"""

from django.contrib import admin
from django.db.models import F
from django.utils import timezone
from django.utils.html import format_html

from catalog_app.models import Book
from .models import (
    Cart, CartItem,
    Coupon,
    DeliveryArea, PickupLocation,
    MpesaTransaction,
    Order, OrderItem,
    PaybillSettings,
)


# ---------------------------------------------------------------------------
# Inlines
# ---------------------------------------------------------------------------

class OrderItemInline(admin.TabularInline):
    model = OrderItem
    extra = 0
    readonly_fields = ["book", "unit_price", "quantity", "total_price", "book_snapshot"]
    can_delete = False


class MpesaTransactionInline(admin.TabularInline):
    model = MpesaTransaction
    extra = 0
    readonly_fields = [
        "checkout_request_id", "phone_number", "amount",
        "result_code", "result_desc", "mpesa_receipt_number",
        "transaction_date", "created_at",
    ]
    can_delete = False
    show_change_link = True


class CartItemInline(admin.TabularInline):
    model = CartItem
    extra = 0
    readonly_fields = ["book", "quantity", "added_at"]
    can_delete = True


# ---------------------------------------------------------------------------
# Order
# ---------------------------------------------------------------------------

@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
    list_display = [
        "order_reference", "customer_name", "phone_number",
        "final_amount_display", "status_badge", "proof_pending_badge",
        "delivery_type", "payment_confirmed_at", "created_at",
    ]
    list_filter = ["status", "delivery_type", "created_at"]
    search_fields = [
        "order_reference", "customer_name", "customer_email",
        "phone_number", "mpesa_receipt_number",
    ]
    ordering = ["-created_at"]
    readonly_fields = [
        "order_reference", "created_at", "updated_at",
        "checkout_request_id", "merchant_request_id",
        "mpesa_receipt_number", "transaction_id", "payment_confirmed_at",
        "total_amount", "delivery_fee", "discount_amount", "final_amount",
        "session_key",
        "paybill_proof_submitted_at", "proof_image_preview",
    ]
    inlines = [OrderItemInline, MpesaTransactionInline]
    fieldsets = [
        ("Identity", {
            "fields": ["order_reference", "user", "session_key", "status"],
        }),
        ("Customer", {
            "fields": [
                "customer_name", "customer_email", "phone_number", "notes",
            ],
        }),
        ("Amounts (KES)", {
            "fields": [
                "total_amount", "delivery_fee", "discount_amount",
                "final_amount", "coupon",
            ],
        }),
        ("Delivery", {
            "fields": [
                "delivery_type", "delivery_area", "delivery_address",
                "pickup_location",
            ],
        }),
        ("Payment / M-Pesa", {
            "fields": [
                "checkout_request_id", "merchant_request_id",
                "mpesa_receipt_number", "transaction_id",
                "payment_confirmed_at",
            ],
        }),
        ("Payment Proof (Manual Paybill)", {
            "fields": [
                "paybill_confirmation_code",
                "paybill_proof_image",
                "proof_image_preview",
                "paybill_proof_submitted_at",
            ],
        }),
        ("Timestamps", {
            "fields": ["created_at", "updated_at"],
            "classes": ["collapse"],
        }),
    ]
    actions = [
        "mark_processing", "mark_shipped", "mark_delivered", "mark_cancelled",
        "approve_payment", "reject_payment",
    ]

    @admin.display(description="Amount (KES)")
    def final_amount_display(self, obj: Order) -> str:
        return f"KES {obj.final_amount:,.2f}"

    @admin.display(description="Status")
    def status_badge(self, obj: Order) -> str:
        colours = {
            "pending": "#f59e0b",
            "payment_initiated": "#3b82f6",
            "paid": "#10b981",
            "failed": "#ef4444",
            "cancelled": "#6b7280",
            "processing": "#8b5cf6",
            "shipped": "#06b6d4",
            "delivered": "#059669",
        }
        colour = colours.get(obj.status, "#9ca3af")
        return format_html(
            '<span style="background:{};color:#fff;padding:2px 8px;'
            'border-radius:4px;font-size:11px">{}</span>',
            colour, obj.get_status_display(),
        )

    @admin.action(description="Mark selected orders as Processing")
    def mark_processing(self, request, queryset):
        queryset.update(status=Order.STATUS_PROCESSING)

    @admin.action(description="Mark selected orders as Shipped")
    def mark_shipped(self, request, queryset):
        queryset.update(status=Order.STATUS_SHIPPED)

    @admin.action(description="Mark selected orders as Delivered")
    def mark_delivered(self, request, queryset):
        queryset.update(status=Order.STATUS_DELIVERED)

    @admin.action(description="Cancel selected orders")
    def mark_cancelled(self, request, queryset):
        for order in queryset:
            order.status = Order.STATUS_CANCELLED
            order.save()   # Triggers the signal that releases stock

    @admin.action(description="✓ Approve payment — mark as Paid")
    def approve_payment(self, request, queryset):
        now = timezone.now()
        approved = 0
        for order in queryset.filter(
            status__in=[Order.STATUS_PENDING, Order.STATUS_PAYMENT_INITIATED]
        ):
            order.status = Order.STATUS_PAID
            order.payment_confirmed_at = now
            if not order.mpesa_receipt_number and order.paybill_confirmation_code:
                order.mpesa_receipt_number = order.paybill_confirmation_code
            order.save(update_fields=[
                "status", "payment_confirmed_at", "mpesa_receipt_number", "updated_at",
            ])
            approved += 1
        self.message_user(request, f"{approved} order(s) approved and marked as Paid.")

    @admin.action(description="✗ Reject payment — mark as Failed + release stock")
    def reject_payment(self, request, queryset):
        rejected = 0
        for order in queryset.filter(
            status__in=[Order.STATUS_PENDING, Order.STATUS_PAYMENT_INITIATED]
        ):
            order.status = Order.STATUS_FAILED
            order.save(update_fields=["status", "updated_at"])
            for item in order.items.select_related("book"):
                Book.objects.filter(pk=item.book_id).update(stock=F("stock") + item.quantity)
            rejected += 1
        self.message_user(request, f"{rejected} order(s) rejected and stock released.")

    @admin.display(description="Proof")
    def proof_pending_badge(self, obj: Order) -> str:
        if obj.paybill_confirmation_code and obj.status == Order.STATUS_PAYMENT_INITIATED:
            return format_html(
                '<span style="background:#f59e0b;color:#fff;padding:2px 8px;'
                'border-radius:4px;font-size:11px">⏳ Review proof</span>'
            )
        return ""

    @admin.display(description="Proof Image")
    def proof_image_preview(self, obj: Order) -> str:
        if obj.paybill_proof_image:
            return format_html(
                '<a href="{url}" target="_blank">'
                '<img src="{url}" style="max-height:220px;max-width:320px;'
                'border-radius:6px;border:1px solid #e5e7eb;" /></a>',
                url=obj.paybill_proof_image.url,
            )
        return "No screenshot uploaded."


# ---------------------------------------------------------------------------
# MpesaTransaction  (read-only audit log)
# ---------------------------------------------------------------------------

@admin.register(MpesaTransaction)
class MpesaTransactionAdmin(admin.ModelAdmin):
    list_display = [
        "checkout_request_id_short", "order_link", "phone_number",
        "amount", "result_code", "mpesa_receipt_number", "created_at",
    ]
    list_filter = ["result_code", "created_at"]
    search_fields = [
        "checkout_request_id", "mpesa_receipt_number",
        "phone_number", "order__order_reference",
    ]
    ordering = ["-created_at"]
    readonly_fields = [f.name for f in MpesaTransaction._meta.get_fields()
                       if hasattr(f, "column")]

    def has_add_permission(self, request):
        return False

    def has_change_permission(self, request, obj=None):
        return False

    @admin.display(description="CheckoutRequestID")
    def checkout_request_id_short(self, obj: MpesaTransaction) -> str:
        return obj.checkout_request_id[:20] + "…" if len(obj.checkout_request_id) > 20 else obj.checkout_request_id

    @admin.display(description="Order")
    def order_link(self, obj: MpesaTransaction) -> str:
        return format_html(
            '<a href="/admin/store/order/{}/change/">{}</a>',
            obj.order_id, obj.order.order_reference,
        )


# ---------------------------------------------------------------------------
# DeliveryArea & PickupLocation
# ---------------------------------------------------------------------------

@admin.register(DeliveryArea)
class DeliveryAreaAdmin(admin.ModelAdmin):
    list_display = ["slug", "name", "county", "delivery_fee", "estimated_days", "is_active"]
    list_filter = ["county", "is_active"]
    search_fields = ["slug", "name", "county"]
    list_editable = ["delivery_fee", "estimated_days", "is_active"]
    prepopulated_fields = {"slug": ("name",)}


@admin.register(PickupLocation)
class PickupLocationAdmin(admin.ModelAdmin):
    list_display = ["name", "county", "address", "phone", "is_active"]
    list_filter = ["county", "is_active"]
    search_fields = ["name", "county", "address"]
    list_editable = ["is_active"]


# ---------------------------------------------------------------------------
# Coupon
# ---------------------------------------------------------------------------

@admin.register(Coupon)
class CouponAdmin(admin.ModelAdmin):
    list_display = [
        "code", "discount_type", "discount_value", "uses_count",
        "max_uses", "expires_at", "is_active",
    ]
    list_filter = ["discount_type", "is_active"]
    search_fields = ["code", "description"]
    readonly_fields = ["uses_count"]


# ---------------------------------------------------------------------------
# Cart  (debug view — not typically needed in production admin)
# ---------------------------------------------------------------------------

@admin.register(Cart)
class CartAdmin(admin.ModelAdmin):
    list_display = ["id", "user", "session_key_short", "item_count", "updated_at"]
    inlines = [CartItemInline]
    readonly_fields = ["created_at", "updated_at"]

    @admin.display(description="Session")
    def session_key_short(self, obj: Cart) -> str:
        sk = obj.session_key or ""
        return sk[:16] + "…" if len(sk) > 16 else sk

    @admin.display(description="Items")
    def item_count(self, obj: Cart) -> int:
        return obj.items.count()


# ---------------------------------------------------------------------------
# PaybillSettings  (singleton — only one row ever exists)
# ---------------------------------------------------------------------------

@admin.register(PaybillSettings)
class PaybillSettingsAdmin(admin.ModelAdmin):
    fieldsets = [
        ("M-Pesa Paybill", {
            "fields": ["business_number", "account_number"],
        }),
        ("Notifications", {
            "fields": ["admin_notification_email"],
            "description": (
                "Email address that receives payment-proof alerts. "
                "Leave blank to use the default EMAIL_HOST_USER."
            ),
        }),
        ("Meta", {
            "fields": ["updated_at"],
            "classes": ["collapse"],
        }),
    ]
    readonly_fields = ["updated_at"]

    def has_add_permission(self, request) -> bool:
        return not PaybillSettings.objects.exists()

    def has_delete_permission(self, request, obj=None) -> bool:
        return False
