from django.contrib import admin, messages
from django.utils import timezone
from django.db.models import Count, Q
from datetime import timedelta

from .models import Ticket, TicketComment, TicketAttachment, TicketAudit
from .models import SupportService

# ---------- Inlines ----------
class TicketCommentInline(admin.TabularInline):
    model = TicketComment
    extra = 0
    fields = ("author", "message", "is_internal", "created_at")
    readonly_fields = ("created_at",)

class TicketAttachmentInline(admin.TabularInline):
    model = TicketAttachment
    extra = 0
    fields = ("file", "uploaded_by", "created_at")
    readonly_fields = ("created_at",)

# ---------- Custom List Filters ----------
class HasAssigneeFilter(admin.SimpleListFilter):
    title = "Assigned?"
    parameter_name = "has_assignee"

    def lookups(self, request, model_admin):
        return (("yes", "Assigned"), ("no", "Unassigned"),)

    def queryset(self, request, queryset):
        if self.value() == "yes":
            return queryset.filter(assignee__isnull=False)
        if self.value() == "no":
            return queryset.filter(assignee__isnull=True)
        return queryset

class HasOrderIdFilter(admin.SimpleListFilter):
    title = "Has Order ID?"
    parameter_name = "has_order"

    def lookups(self, request, model_admin):
        return (("yes", "With Order ID"), ("no", "Without Order ID"),)

    def queryset(self, request, queryset):
        if self.value() == "yes":
            return queryset.exclude(order_id__isnull=True).exclude(order_id__exact="")
        if self.value() == "no":
            return queryset.filter(Q(order_id__isnull=True) | Q(order_id__exact=""))
        return queryset

class HasFirstResponseFilter(admin.SimpleListFilter):
    title = "First Response?"
    parameter_name = "first_resp"

    def lookups(self, request, model_admin):
        return (("done", "Has first response"), ("pending", "Not responded yet"),)

    def queryset(self, request, queryset):
        if self.value() == "done":
            return queryset.exclude(first_response_at__isnull=True)
        if self.value() == "pending":
            return queryset.filter(first_response_at__isnull=True)
        return queryset

class AgeBucketFilter(admin.SimpleListFilter):
    """
    Buckets by ticket age since created_at.
    """
    title = "Age"
    parameter_name = "age"

    def lookups(self, request, model_admin):
        return (
            ("0_4h", "0–4 hours"),
            ("4_24h", "4–24 hours"),
            ("1_3d", "1–3 days"),
            ("gt_3d", "> 3 days"),
        )

    def queryset(self, request, queryset):
        now = timezone.now()
        if self.value() == "0_4h":
            return queryset.filter(created_at__gte=now - timedelta(hours=4))
        if self.value() == "4_24h":
            return queryset.filter(created_at__lt=now - timedelta(hours=4),
                                   created_at__gte=now - timedelta(hours=24))
        if self.value() == "1_3d":
            return queryset.filter(created_at__lt=now - timedelta(hours=24),
                                   created_at__gte=now - timedelta(days=3))
        if self.value() == "gt_3d":
            return queryset.filter(created_at__lt=now - timedelta(days=3))
        return queryset

class SLAOverdueFilter(admin.SimpleListFilter):
    """
    Flags overdue by priority with simple SLAs:
      - urgent: first response in 30m, resolve in 4h
      - high:   first response in 1h,  resolve in 8h
      - medium: first response in 4h,  resolve in 24h
      - low:    first response in 8h,  resolve in 72h
    """
    title = "SLA breach"
    parameter_name = "sla"

    SLA = {
        "urgent": {"resp_m": 30,   "res_h": 4},
        "high":   {"resp_m": 60,   "res_h": 8},
        "medium": {"resp_m": 240,  "res_h": 24},
        "low":    {"resp_m": 480,  "res_h": 72},
    }

    def lookups(self, request, model_admin):
        return (
            ("resp_overdue", "Response overdue"),
            ("res_overdue", "Resolution overdue"),
        )

    def queryset(self, request, queryset):
        now = timezone.now()
        val = self.value()
        if val not in {"resp_overdue", "res_overdue"}:
            return queryset

        q = Q()
        for prio, t in self.SLA.items():
            resp_deadline = now - timedelta(minutes=t["resp_m"])
            res_deadline = now - timedelta(hours=t["res_h"])

            if val == "resp_overdue":
                # No first_response_at and past response deadline
                q |= Q(priority=prio, first_response_at__isnull=True, created_at__lt=resp_deadline)
            else:
                # Not resolved/closed and created_at past resolution deadline
                q |= Q(priority=prio, resolved_at__isnull=True, status__in=["open","in_progress","waiting_user"],
                       created_at__lt=res_deadline)

        return queryset.filter(q)

# ---------- Admin Actions ----------
def mark_status(modeladmin, request, queryset, status_value, label):
    updated = queryset.update(status=status_value)
    messages.success(request, f"{updated} ticket(s) marked {label}.")

@admin.action(description="Mark as Open")
def action_mark_open(modeladmin, request, queryset):
    mark_status(modeladmin, request, queryset, "open", "Open")

@admin.action(description="Mark as In Progress")
def action_mark_in_progress(modeladmin, request, queryset):
    mark_status(modeladmin, request, queryset, "in_progress", "In Progress")

@admin.action(description="Mark as Waiting on User")
def action_mark_waiting_user(modeladmin, request, queryset):
    mark_status(modeladmin, request, queryset, "waiting_user", "Waiting on User")

@admin.action(description="Mark as Resolved")
def action_mark_resolved(modeladmin, request, queryset):
    now = timezone.now()
    updated = 0
    for t in queryset:
        t.status = "resolved"
        if not t.resolved_at:
            t.resolved_at = now
        t.save(update_fields=["status", "resolved_at"])
        updated += 1
    messages.success(request, f"{updated} ticket(s) marked Resolved.")

@admin.action(description="Mark as Closed")
def action_mark_closed(modeladmin, request, queryset):
    now = timezone.now()
    updated = 0
    for t in queryset:
        t.status = "closed"
        if not t.resolved_at:
            t.resolved_at = now
        t.save(update_fields=["status", "resolved_at"])
        updated += 1
    messages.success(request, f"{updated} ticket(s) marked Closed.")

@admin.action(description="Assign selected to me")
def action_assign_to_me(modeladmin, request, queryset):
    me = request.user
    updated = queryset.update(assignee=me)
    messages.success(request, f"{updated} ticket(s) assigned to you.")

# ---------- Ticket Admin ----------
@admin.register(Ticket)
class TicketAdmin(admin.ModelAdmin):
    list_display = (
        "ticket_id", "subject", "status", "priority",
        "requester", "requester_mobile", "assignee",
        "order_id", "created_at", "updated_at", "age_hours",
        "first_response_at", "resolved_at",
        "comments_count", "attachments_count",
    )
    list_select_related = ("requester", "assignee")
    search_fields = (
        "ticket_id", "subject", "description", "order_id",
        "requester__mobile_number", "requester__first_name", "requester__last_name",
        "requester_mobile", "assignee__first_name", "assignee__last_name",
    )
    list_filter = (
        "status",
        "priority",
        HasAssigneeFilter,
        HasOrderIdFilter,
        HasFirstResponseFilter,
        AgeBucketFilter,
        SLAOverdueFilter,
        "category",
        ("created_at", admin.DateFieldListFilter),
        ("updated_at", admin.DateFieldListFilter),
    )
    date_hierarchy = "created_at"
    readonly_fields = ("ticket_id", "created_at", "updated_at", "first_response_at", "resolved_at")
    inlines = [TicketCommentInline, TicketAttachmentInline]
    autocomplete_fields = ("requester", "assignee")
    ordering = ("-created_at",)

    actions = (
        action_assign_to_me,
        action_mark_open,
        action_mark_in_progress,
        action_mark_waiting_user,
        action_mark_resolved,
        action_mark_closed,
    )

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.annotate(
            _comments_count=Count("comments", distinct=True),
            _attachments_count=Count("attachments", distinct=True),
        )

    def comments_count(self, obj):
        return getattr(obj, "_comments_count", 0)
    comments_count.short_description = "Comments"

    def attachments_count(self, obj):
        return getattr(obj, "_attachments_count", 0)
    attachments_count.short_description = "Files"

    def age_hours(self, obj):
        delta = timezone.now() - obj.created_at
        return f"{int(delta.total_seconds() // 3600)}h"
    age_hours.short_description = "Age"

# Optional: expose audits read-only
@admin.register(TicketAudit)
class TicketAuditAdmin(admin.ModelAdmin):
    list_display = ("ticket", "actor", "field", "old_value", "new_value", "created_at")
    search_fields = ("ticket__ticket_id", "field", "old_value", "new_value", "actor__first_name", "actor__last_name")
    list_filter = (("created_at", admin.DateFieldListFilter),)
    readonly_fields = ("ticket", "actor", "field", "old_value", "new_value", "created_at")
    ordering = ("-created_at",)

@admin.register(SupportService)
class SupportServiceAdmin(admin.ModelAdmin):
    list_display = ("name","code","is_active","sort_order","created_at","updated_at")
    list_editable = ("is_active","sort_order")
    search_fields = ("name","code")
    list_filter = ("is_active",)
