from django_filters import rest_framework as filters
from apps.mtm.models import Goal, Material, Route, RouteMat, RoutePack, Process
from django.db.models.expressions import F
from rest_framework.exceptions import ParseError
from django.db.models import Sum, Q, Value, F, ExpressionWrapper, DecimalField
from django.db.models.functions import Coalesce

class MaterialFilter(filters.FilterSet):
    tag = filters.CharFilter(method='filter_tag', label="low_inm:库存不足;todo:可用")
    process_todo = filters.CharFilter(method='filter_process_todo', label="process_todo:待处理")

    class Meta:
        model = Material
        fields = {
            "id": ["exact", "in"],
            "cate": ["exact", "in"],
            "code": ["exact", "in", "isnull"],
            "type": ["exact", "in"],
            "is_hidden": ["exact"],
            "is_assemb": ["exact"],
            "need_route": ["exact"],
            "name": ["exact", 'contains'],
            "process": ["exact", "in", "isnull"],
            "orderitem_material__order": ['exact'],
            "pu_orderitem_material__pu_order": ["exact"],
            "route_material_out__mgroup": ["exact"],
            "count_safe": ["gte", "lte", "exact", "gt", "lt"]
        }
    
    def filter_process_todo(self, queryset, name, value):
        if value:
            queryset = queryset.filter(
                Q(id__in=RouteMat.objects.filter(route__process__id=value).values('material_id')) |
                Q(id__in=Route.objects.filter(process__id=value).values('material_in_id'))
            )
        return queryset

    def filter_tag(self, queryset, name, value):
        if value == 'low_inm':
            queryset = Material.annotate_count(queryset.exclude(count_safe=None).exclude(count_safe__lte=0)).filter(
                count__lte=F('count_safe'))
        return queryset


class GoalFilter(filters.FilterSet):
    class Meta:
        model = Goal
        fields = {
            "mgroup": ["exact", "in"],
            "mgroup__name": ["exact", "in"],
            "goal_cate": ["exact", "in"],
            "goal_cate__code": ["exact", "in"],
            "year": ["exact"]
        }


class RouteFilter(filters.FilterSet):
    nprocess_name = filters.CharFilter(method='filter_nprocess_name', label="nprocess_name")
    material_in_has = filters.CharFilter(method='filter_material_in_has', label="material_in_has ID")
    class Meta:
        model = Route
        fields = { 
            "material": ["exact", "in", "isnull"],
            "material_out": ["exact", "in"],
            "material_in": ["exact", "in"],
            "process": ["exact", "in"],
            "is_autotask": ["exact"],
            "routepack": ["exact", "isnull"],
            "routepack__state": ["exact"],
            "mgroup": ["exact", "in", "isnull"],
            "mgroup__name": ["exact", "contains"],
            "mgroup__belong_dept": ["exact"],
            "mgroup__belong_dept__name": ["exact", "contains"],
            "from_route": ["exact", "isnull"],
        }

    def filter_nprocess_name(self, queryset, name, value):
        return queryset
    

    def filter_material_in_has(self, queryset, name, value):
        nprocess_name = self.data.get('nprocess_name', None)
        if nprocess_name:
            routepack_qs = queryset.filter(material_in__id=value, routepack__isnull=False, routepack__state=RoutePack.RP_S_CONFIRM).values_list('routepack', flat=True)
            qs = queryset.filter(routepack__in=routepack_qs, process__name=nprocess_name)
            return qs
        raise ParseError("nprocess_name is required")