"""
Moderation Filters

This module contains Django filter classes for the moderation system,
providing comprehensive filtering capabilities for all moderation models.
"""

from datetime import timedelta

import django_filters
from django.contrib.auth import get_user_model
from django.db.models import Q
from django.utils import timezone

from apps.core.choices.registry import get_choices

from .models import (
    BulkOperation,
    ModerationAction,
    ModerationQueue,
    ModerationReport,
)

User = get_user_model()


class ModerationReportFilter(django_filters.FilterSet):
    """Filter for ModerationReport model."""

    # Status filters
    status = django_filters.ChoiceFilter(
        choices=lambda: [
            (choice.value, choice.label) for choice in get_choices("moderation_report_statuses", "moderation")
        ],
        help_text="Filter by report status",
    )

    # Priority filters
    priority = django_filters.ChoiceFilter(
        choices=lambda: [(choice.value, choice.label) for choice in get_choices("priority_levels", "moderation")],
        help_text="Filter by report priority",
    )

    # Report type filters
    report_type = django_filters.ChoiceFilter(
        choices=lambda: [(choice.value, choice.label) for choice in get_choices("report_types", "moderation")],
        help_text="Filter by report type",
    )

    # User filters
    reported_by = django_filters.ModelChoiceFilter(
        queryset=User.objects.all(), help_text="Filter by user who made the report"
    )

    assigned_moderator = django_filters.ModelChoiceFilter(
        queryset=User.objects.filter(role__in=["MODERATOR", "ADMIN", "SUPERUSER"]),
        help_text="Filter by assigned moderator",
    )

    # Date filters
    created_after = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="gte",
        help_text="Filter reports created after this date",
    )

    created_before = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="lte",
        help_text="Filter reports created before this date",
    )

    resolved_after = django_filters.DateTimeFilter(
        field_name="resolved_at",
        lookup_expr="gte",
        help_text="Filter reports resolved after this date",
    )

    resolved_before = django_filters.DateTimeFilter(
        field_name="resolved_at",
        lookup_expr="lte",
        help_text="Filter reports resolved before this date",
    )

    # Content type filters
    content_type = django_filters.CharFilter(
        field_name="content_type__model",
        help_text="Filter by content type (e.g., 'park', 'ride', 'review')",
    )

    # Special filters
    unassigned = django_filters.BooleanFilter(method="filter_unassigned", help_text="Filter for unassigned reports")

    overdue = django_filters.BooleanFilter(method="filter_overdue", help_text="Filter for overdue reports based on SLA")

    has_resolution = django_filters.BooleanFilter(
        method="filter_has_resolution",
        help_text="Filter reports with/without resolution",
    )

    class Meta:
        model = ModerationReport
        fields = [
            "status",
            "priority",
            "report_type",
            "reported_by",
            "assigned_moderator",
            "content_type",
            "unassigned",
            "overdue",
            "has_resolution",
        ]

    def filter_unassigned(self, queryset, name, value):
        """Filter for unassigned reports."""
        if value:
            return queryset.filter(assigned_moderator__isnull=True)
        return queryset.filter(assigned_moderator__isnull=False)

    def filter_overdue(self, queryset, name, value):
        """Filter for overdue reports based on SLA."""
        if not value:
            return queryset

        now = timezone.now()
        sla_hours = {"URGENT": 2, "HIGH": 8, "MEDIUM": 24, "LOW": 72}

        overdue_ids = []
        for report in queryset.filter(status__in=["PENDING", "UNDER_REVIEW"]):
            hours_since_created = (now - report.created_at).total_seconds() / 3600
            if report.priority in sla_hours:
                threshold = sla_hours[report.priority]
            else:
                raise ValueError(f"Unknown priority level: {report.priority}")
            if hours_since_created > threshold:
                overdue_ids.append(report.id)

        return queryset.filter(id__in=overdue_ids)

    def filter_has_resolution(self, queryset, name, value):
        """Filter reports with/without resolution."""
        if value:
            return queryset.exclude(resolution_action__isnull=True, resolution_action="")
        return queryset.filter(Q(resolution_action__isnull=True) | Q(resolution_action=""))


class ModerationQueueFilter(django_filters.FilterSet):
    """Filter for ModerationQueue model."""

    # Status filters
    status = django_filters.ChoiceFilter(
        choices=lambda: [
            (choice.value, choice.label) for choice in get_choices("moderation_queue_statuses", "moderation")
        ],
        help_text="Filter by queue item status",
    )

    # Priority filters
    priority = django_filters.ChoiceFilter(
        choices=lambda: [(choice.value, choice.label) for choice in get_choices("priority_levels", "moderation")],
        help_text="Filter by queue item priority",
    )

    # Item type filters
    item_type = django_filters.ChoiceFilter(
        choices=lambda: [(choice.value, choice.label) for choice in get_choices("queue_item_types", "moderation")],
        help_text="Filter by queue item type",
    )

    # Assignment filters
    assigned_to = django_filters.ModelChoiceFilter(
        queryset=User.objects.filter(role__in=["MODERATOR", "ADMIN", "SUPERUSER"]),
        help_text="Filter by assigned moderator",
    )

    unassigned = django_filters.BooleanFilter(method="filter_unassigned", help_text="Filter for unassigned queue items")

    # Date filters
    created_after = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="gte",
        help_text="Filter items created after this date",
    )

    created_before = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="lte",
        help_text="Filter items created before this date",
    )

    assigned_after = django_filters.DateTimeFilter(
        field_name="assigned_at",
        lookup_expr="gte",
        help_text="Filter items assigned after this date",
    )

    assigned_before = django_filters.DateTimeFilter(
        field_name="assigned_at",
        lookup_expr="lte",
        help_text="Filter items assigned before this date",
    )

    # Content type filters
    content_type = django_filters.CharFilter(field_name="content_type__model", help_text="Filter by content type")

    # Related report filters
    has_related_report = django_filters.BooleanFilter(
        method="filter_has_related_report",
        help_text="Filter items with/without related reports",
    )

    class Meta:
        model = ModerationQueue
        fields = [
            "status",
            "priority",
            "item_type",
            "assigned_to",
            "unassigned",
            "content_type",
            "has_related_report",
        ]

    def filter_unassigned(self, queryset, name, value):
        """Filter for unassigned queue items."""
        if value:
            return queryset.filter(assigned_to__isnull=True)
        return queryset.filter(assigned_to__isnull=False)

    def filter_has_related_report(self, queryset, name, value):
        """Filter items with/without related reports."""
        if value:
            return queryset.filter(related_report__isnull=False)
        return queryset.filter(related_report__isnull=True)


class ModerationActionFilter(django_filters.FilterSet):
    """Filter for ModerationAction model."""

    # Action type filters
    action_type = django_filters.ChoiceFilter(
        choices=lambda: [
            (choice.value, choice.label) for choice in get_choices("moderation_action_types", "moderation")
        ],
        help_text="Filter by action type",
    )

    # User filters
    moderator = django_filters.ModelChoiceFilter(
        queryset=User.objects.filter(role__in=["MODERATOR", "ADMIN", "SUPERUSER"]),
        help_text="Filter by moderator who took the action",
    )

    target_user = django_filters.ModelChoiceFilter(queryset=User.objects.all(), help_text="Filter by target user")

    # Status filters
    is_active = django_filters.BooleanFilter(help_text="Filter by active status")

    # Date filters
    created_after = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="gte",
        help_text="Filter actions created after this date",
    )

    created_before = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="lte",
        help_text="Filter actions created before this date",
    )

    expires_after = django_filters.DateTimeFilter(
        field_name="expires_at",
        lookup_expr="gte",
        help_text="Filter actions expiring after this date",
    )

    expires_before = django_filters.DateTimeFilter(
        field_name="expires_at",
        lookup_expr="lte",
        help_text="Filter actions expiring before this date",
    )

    # Special filters
    expired = django_filters.BooleanFilter(method="filter_expired", help_text="Filter for expired actions")

    expiring_soon = django_filters.BooleanFilter(
        method="filter_expiring_soon",
        help_text="Filter for actions expiring within 24 hours",
    )

    has_related_report = django_filters.BooleanFilter(
        method="filter_has_related_report",
        help_text="Filter actions with/without related reports",
    )

    class Meta:
        model = ModerationAction
        fields = [
            "action_type",
            "moderator",
            "target_user",
            "is_active",
            "expired",
            "expiring_soon",
            "has_related_report",
        ]

    def filter_expired(self, queryset, name, value):
        """Filter for expired actions."""
        now = timezone.now()
        if value:
            return queryset.filter(expires_at__lte=now)
        return queryset.filter(Q(expires_at__gt=now) | Q(expires_at__isnull=True))

    def filter_expiring_soon(self, queryset, name, value):
        """Filter for actions expiring within 24 hours."""
        if not value:
            return queryset

        now = timezone.now()
        soon = now + timedelta(hours=24)
        return queryset.filter(expires_at__gt=now, expires_at__lte=soon, is_active=True)

    def filter_has_related_report(self, queryset, name, value):
        """Filter actions with/without related reports."""
        if value:
            return queryset.filter(related_report__isnull=False)
        return queryset.filter(related_report__isnull=True)


class BulkOperationFilter(django_filters.FilterSet):
    """Filter for BulkOperation model."""

    # Status filters
    status = django_filters.ChoiceFilter(
        choices=lambda: [
            (choice.value, choice.label) for choice in get_choices("bulk_operation_statuses", "moderation")
        ],
        help_text="Filter by operation status",
    )

    # Operation type filters
    operation_type = django_filters.ChoiceFilter(
        choices=lambda: [(choice.value, choice.label) for choice in get_choices("bulk_operation_types", "moderation")],
        help_text="Filter by operation type",
    )

    # Priority filters
    priority = django_filters.ChoiceFilter(
        choices=lambda: [(choice.value, choice.label) for choice in get_choices("priority_levels", "moderation")],
        help_text="Filter by operation priority",
    )

    # User filters
    created_by = django_filters.ModelChoiceFilter(
        queryset=User.objects.filter(role__in=["ADMIN", "SUPERUSER"]),
        help_text="Filter by user who created the operation",
    )

    # Date filters
    created_after = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="gte",
        help_text="Filter operations created after this date",
    )

    created_before = django_filters.DateTimeFilter(
        field_name="created_at",
        lookup_expr="lte",
        help_text="Filter operations created before this date",
    )

    started_after = django_filters.DateTimeFilter(
        field_name="started_at",
        lookup_expr="gte",
        help_text="Filter operations started after this date",
    )

    started_before = django_filters.DateTimeFilter(
        field_name="started_at",
        lookup_expr="lte",
        help_text="Filter operations started before this date",
    )

    completed_after = django_filters.DateTimeFilter(
        field_name="completed_at",
        lookup_expr="gte",
        help_text="Filter operations completed after this date",
    )

    completed_before = django_filters.DateTimeFilter(
        field_name="completed_at",
        lookup_expr="lte",
        help_text="Filter operations completed before this date",
    )

    # Special filters
    can_cancel = django_filters.BooleanFilter(help_text="Filter by cancellation capability")

    has_failures = django_filters.BooleanFilter(
        method="filter_has_failures",
        help_text="Filter operations with/without failures",
    )

    in_progress = django_filters.BooleanFilter(
        method="filter_in_progress",
        help_text="Filter for operations currently in progress",
    )

    class Meta:
        model = BulkOperation
        fields = [
            "status",
            "operation_type",
            "priority",
            "created_by",
            "can_cancel",
            "has_failures",
            "in_progress",
        ]

    def filter_has_failures(self, queryset, name, value):
        """Filter operations with/without failures."""
        if value:
            return queryset.filter(failed_items__gt=0)
        return queryset.filter(failed_items=0)

    def filter_in_progress(self, queryset, name, value):
        """Filter for operations currently in progress."""
        if value:
            return queryset.filter(status__in=["PENDING", "RUNNING"])
        return queryset.exclude(status__in=["PENDING", "RUNNING"])
