"""
Workflow Filters.

Django Filter classes for workflow API.
"""
import django_filters
from django.db.models import Q

from .models import (
    ProcessDefinition,
    ProcessInstance,
    Task,
    ProcessHistory,
    InstanceStatus,
    TaskStatus,
    TaskType,
    HistoryEventType,
)


class ProcessDefinitionFilter(django_filters.FilterSet):
    """Filter for ProcessDefinition model."""
    
    slug = django_filters.CharFilter(lookup_expr='iexact')
    name = django_filters.CharFilter(lookup_expr='icontains')
    is_deployed = django_filters.BooleanFilter()
    is_active = django_filters.BooleanFilter()
    version = django_filters.NumberFilter()
    version_min = django_filters.NumberFilter(field_name='version', lookup_expr='gte')
    version_max = django_filters.NumberFilter(field_name='version', lookup_expr='lte')
    created_after = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='gte')
    created_before = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='lte')
    deployed_after = django_filters.DateTimeFilter(field_name='deployed_at', lookup_expr='gte')
    deployed_before = django_filters.DateTimeFilter(field_name='deployed_at', lookup_expr='lte')
    created_by = django_filters.UUIDFilter(field_name='created_by__id')
    
    # Filter for startable definitions (deployed and active)
    startable = django_filters.BooleanFilter(method='filter_startable')
    
    class Meta:
        model = ProcessDefinition
        fields = [
            'slug',
            'name',
            'is_deployed',
            'is_active',
            'version',
        ]

    def filter_startable(self, queryset, name, value):
        if value:
            return queryset.filter(is_deployed=True, is_active=True)
        return queryset


class ProcessInstanceFilter(django_filters.FilterSet):
    """Filter for ProcessInstance model."""
    
    definition = django_filters.UUIDFilter(field_name='definition__id')
    definition_slug = django_filters.CharFilter(field_name='definition__slug', lookup_expr='iexact')
    definition_name = django_filters.CharFilter(field_name='definition__name', lookup_expr='icontains')
    business_key = django_filters.CharFilter(lookup_expr='icontains')
    status = django_filters.ChoiceFilter(choices=InstanceStatus.choices)
    status_in = django_filters.MultipleChoiceFilter(
        field_name='status',
        choices=InstanceStatus.choices,
        conjoined=False
    )
    started_by = django_filters.UUIDFilter(field_name='started_by__id')
    started_after = django_filters.DateTimeFilter(field_name='started_at', lookup_expr='gte')
    started_before = django_filters.DateTimeFilter(field_name='started_at', lookup_expr='lte')
    completed_after = django_filters.DateTimeFilter(field_name='completed_at', lookup_expr='gte')
    completed_before = django_filters.DateTimeFilter(field_name='completed_at', lookup_expr='lte')
    
    # Filter for active instances
    is_active = django_filters.BooleanFilter(method='filter_is_active')
    
    class Meta:
        model = ProcessInstance
        fields = [
            'definition',
            'business_key',
            'status',
            'started_by',
        ]

    def filter_is_active(self, queryset, name, value):
        active_statuses = [InstanceStatus.RUNNING, InstanceStatus.SUSPENDED]
        if value:
            return queryset.filter(status__in=active_statuses)
        return queryset.exclude(status__in=active_statuses)


class TaskFilter(django_filters.FilterSet):
    """Filter for Task model."""
    
    instance = django_filters.UUIDFilter(field_name='instance__id')
    instance_business_key = django_filters.CharFilter(
        field_name='instance__business_key',
        lookup_expr='icontains'
    )
    definition_slug = django_filters.CharFilter(
        field_name='instance__definition__slug',
        lookup_expr='iexact'
    )
    name = django_filters.CharFilter(lookup_expr='icontains')
    task_type = django_filters.ChoiceFilter(choices=TaskType.choices)
    status = django_filters.ChoiceFilter(choices=TaskStatus.choices)
    status_in = django_filters.MultipleChoiceFilter(
        field_name='status',
        choices=TaskStatus.choices,
        conjoined=False
    )
    assignee = django_filters.UUIDFilter(field_name='assignee__id')
    assignee_email = django_filters.CharFilter(field_name='assignee__email', lookup_expr='icontains')
    priority_min = django_filters.NumberFilter(field_name='priority', lookup_expr='gte')
    priority_max = django_filters.NumberFilter(field_name='priority', lookup_expr='lte')
    due_date_before = django_filters.DateTimeFilter(field_name='due_date', lookup_expr='lte')
    due_date_after = django_filters.DateTimeFilter(field_name='due_date', lookup_expr='gte')
    created_after = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='gte')
    created_before = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='lte')
    
    # Filter for active tasks
    is_active = django_filters.BooleanFilter(method='filter_is_active')
    
    # Filter for overdue tasks
    is_overdue = django_filters.BooleanFilter(method='filter_is_overdue')
    
    # Filter for unassigned tasks
    is_unassigned = django_filters.BooleanFilter(method='filter_is_unassigned')
    
    class Meta:
        model = Task
        fields = [
            'instance',
            'task_type',
            'status',
            'assignee',
            'priority_min',
            'priority_max',
        ]

    def filter_is_active(self, queryset, name, value):
        active_statuses = [TaskStatus.CREATED, TaskStatus.ASSIGNED, TaskStatus.CLAIMED]
        if value:
            return queryset.filter(status__in=active_statuses)
        return queryset.exclude(status__in=active_statuses)

    def filter_is_overdue(self, queryset, name, value):
        from django.utils import timezone
        active_statuses = [TaskStatus.CREATED, TaskStatus.ASSIGNED, TaskStatus.CLAIMED]
        if value:
            return queryset.filter(
                status__in=active_statuses,
                due_date__isnull=False,
                due_date__lt=timezone.now()
            )
        return queryset

    def filter_is_unassigned(self, queryset, name, value):
        if value:
            return queryset.filter(assignee__isnull=True)
        return queryset.filter(assignee__isnull=False)


class ProcessHistoryFilter(django_filters.FilterSet):
    """Filter for ProcessHistory model."""
    
    instance = django_filters.UUIDFilter(field_name='instance__id')
    instance_business_key = django_filters.CharFilter(
        field_name='instance__business_key',
        lookup_expr='icontains'
    )
    task = django_filters.UUIDFilter(field_name='task__id')
    user = django_filters.UUIDFilter(field_name='user__id')
    event_type = django_filters.ChoiceFilter(choices=HistoryEventType.choices)
    event_type_in = django_filters.MultipleChoiceFilter(
        field_name='event_type',
        choices=HistoryEventType.choices,
        conjoined=False
    )
    created_after = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='gte')
    created_before = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='lte')
    
    class Meta:
        model = ProcessHistory
        fields = [
            'instance',
            'task',
            'user',
            'event_type',
        ]
