from django.contrib import admin
from django.db.models import Q
from django.template.defaultfilters import linebreaksbr
from django.utils import timezone
from django.utils.html import format_html, format_html_join

from .models import Order, OrderItem


class GPSAvailabilityFilter(admin.SimpleListFilter):
    title = 'GPS availability'
    parameter_name = 'gps'

    def lookups(self, request, model_admin):
        return (
            ('yes', 'With GPS'),
            ('no', 'Manual only'),
        )

    def queryset(self, request, queryset):
        if self.value() == 'yes':
            return queryset.filter(latitude__isnull=False, longitude__isnull=False)
        if self.value() == 'no':
            return queryset.filter(Q(latitude__isnull=True) | Q(longitude__isnull=True))
        return queryset


class OrderItemInline(admin.TabularInline):
    model = OrderItem
    extra = 0


@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'user',
        'status',
        'payment_status',
        'payment_method',
        'payment_provider_label',
        'short_location',
        'has_precise_location',
        'total_price',
        'created_at',
        'paid_at',
    )
    list_select_related = ('user',)
    list_filter = ('status', 'payment_status', 'payment_provider', 'payment_method', GPSAvailabilityFilter)
    search_fields = (
        'user__username',
        'user__email',
        'id',
        'payment_reference',
        'payment_session_id',
        'full_name',
        'phone',
        'address',
        'location_label',
        'delivery_notes',
    )
    readonly_fields = ('created_at', 'payment_reference', 'payment_session_id', 'paid_at', 'delivery_snapshot', 'maps_link')
    date_hierarchy = 'created_at'
    autocomplete_fields = ('user',)
    actions = ('mark_payment_pending', 'mark_payment_paid', 'mark_status_shipped', 'mark_status_delivered')
    fieldsets = (
        ('Order', {'fields': ('user', 'status', 'created_at', 'total_price')}),
        (
            'Payment',
            {
                'fields': (
                    'payment_status',
                    'payment_method',
                    'payment_provider',
                    'payment_currency',
                    'payment_reference',
                    'payment_session_id',
                    'paid_at',
                )
            },
        ),
        ('Delivery snapshot', {'fields': ('full_name', 'phone', 'location_label', 'address', 'delivery_notes', 'delivery_snapshot')}),
        ('GPS', {'fields': ('latitude', 'longitude', 'location_accuracy_m', 'maps_link')}),
    )
    inlines = [OrderItemInline]

    @admin.display(description='Location')
    def short_location(self, obj):
        return obj.location_label or (obj.address.splitlines()[0].strip() if obj.address else '-')

    @admin.display(boolean=True, description='GPS')
    def has_precise_location(self, obj):
        return obj.has_precise_location

    @admin.display(description='Payment provider')
    def payment_provider_label(self, obj):
        return obj.payment_provider_label

    @admin.display(description='Delivery summary')
    def delivery_snapshot(self, obj):
        lines = []
        if obj.full_name:
            lines.append(format_html('<strong>{}</strong>', obj.full_name))
        if obj.phone:
            lines.append(obj.phone)
        if obj.location_label:
            lines.append(obj.location_label)
        if obj.address:
            lines.append(linebreaksbr(obj.address))
        if obj.delivery_notes:
            lines.append(format_html('<em>Notes:</em> {}', obj.delivery_notes))
        if not lines:
            return '-'
        return format_html_join(format_html('<br>'), '{}', ((line,) for line in lines))

    @admin.display(description='Map')
    def maps_link(self, obj):
        if not obj.has_precise_location:
            return '-'
        return format_html(
            '<a href="https://maps.google.com/?q={},{}" target="_blank" rel="noopener">Open map</a>',
            obj.latitude,
            obj.longitude,
        )

    @admin.action(description='Mark selected orders as payment pending')
    def mark_payment_pending(self, request, queryset):
        updated = queryset.exclude(payment_status='Pending').update(payment_status='Pending')
        self.message_user(request, f'{updated} order(s) marked as payment pending.')

    @admin.action(description='Mark selected orders as paid')
    def mark_payment_paid(self, request, queryset):
        now = timezone.now()
        updated = queryset.exclude(payment_status='Paid').update(payment_status='Paid', paid_at=now)
        queryset.filter(status='Pending').update(status='Paid')
        self.message_user(request, f'{updated} order(s) marked as paid.')

    @admin.action(description='Mark selected orders as shipped')
    def mark_status_shipped(self, request, queryset):
        updated = queryset.exclude(status__in=['Shipped', 'Delivered']).update(status='Shipped')
        self.message_user(request, f'{updated} order(s) marked as shipped.')

    @admin.action(description='Mark selected orders as delivered')
    def mark_status_delivered(self, request, queryset):
        updated = queryset.exclude(status='Delivered').update(status='Delivered')
        cod_collected = queryset.filter(payment_method='Cash on Delivery').exclude(payment_status='Paid').update(
            payment_status='Paid',
            paid_at=timezone.now(),
        )
        message = f'{updated} order(s) marked as delivered.'
        if cod_collected:
            message += f' {cod_collected} COD payment(s) were also marked paid.'
        self.message_user(request, message)


@admin.register(OrderItem)
class OrderItemAdmin(admin.ModelAdmin):
    list_display = ('order', 'product', 'quantity', 'price')
    search_fields = ('order__id', 'product__name')
    autocomplete_fields = ('order', 'product')
