from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAuthenticated
from django.db.models import Prefetch

from account.permissions import HasTabPermission, get_user_data_filter, user_can_see_all_shop_data
from shop_management.models.data.inventory import InventoryBatch, StockBalance, StockMovement
from shop_management.models.data.purchase import PurchaseItem
from shop_management.serializers.data.inventory import (
    InventoryBatchSerializer,
    StockBalanceSerializer,
    StockMovementSerializer,
)
from shop_management.views.data.base import DataRootViewSet
from shop_management.views.data.pagination import CustomPagination


class InventoryBatchViewSet(DataRootViewSet):
    serializer_class = InventoryBatchSerializer
    permission_classes = [IsAuthenticated, HasTabPermission]
    required_tab = "stock"
    pagination_class = CustomPagination
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ["product", "is_blocked", "expiry_date"]
    search_fields = ["batch_number", "product__name", "product__code"]
    ordering_fields = ["expiry_date", "batch_number", "created_at"]

    def get_queryset(self):
        queryset = InventoryBatch.objects.select_related("product", "product__shop")
        if user_can_see_all_shop_data(self.request.user, self.required_tab):
            return queryset
        return queryset.filter(
            get_user_data_filter(self.request.user, "product__shop")
        ).distinct()

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)


class StockBalanceViewSet(DataRootViewSet):
    http_method_names = ["get", "head", "options"]
    serializer_class = StockBalanceSerializer
    permission_classes = [IsAuthenticated, HasTabPermission]
    required_tab = "stock"
    pagination_class = CustomPagination
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ["warehouse", "product", "batch", "cost_currency"]
    search_fields = ["product__name", "product__code", "batch__batch_number", "warehouse__name"]
    ordering_fields = ["quantity", "average_cost", "batch__expiry_date", "updated_at"]

    def get_queryset(self):
        queryset = StockBalance.objects.select_related(
            "warehouse", "warehouse__shop", "product", "product__default_unit",
            "batch", "cost_currency"
        ).prefetch_related(
            "product__prices__currency",
            Prefetch(
                "product__purchase_items",
                queryset=PurchaseItem.objects.filter(purchase__document_status="POSTED")
                .select_related("purchase__currency")
                .order_by("-purchase__purchase_date", "-id"),
                to_attr="posted_purchase_items_for_pricing",
            ),
        )
        if not user_can_see_all_shop_data(self.request.user, self.required_tab):
            queryset = queryset.filter(
                get_user_data_filter(self.request.user, "warehouse__shop")
            ).distinct()
        shop_id = self.request.query_params.get("shop")
        if shop_id:
            queryset = queryset.filter(warehouse__shop_id=shop_id)
        return queryset


class StockMovementViewSet(DataRootViewSet):
    http_method_names = ["get", "head", "options"]
    serializer_class = StockMovementSerializer
    permission_classes = [IsAuthenticated, HasTabPermission]
    required_tab = "stock"
    pagination_class = CustomPagination
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ["warehouse", "product", "batch", "movement_type", "currency"]
    search_fields = ["product__name", "batch__batch_number", "reference_type", "reference_id", "remarks"]
    ordering_fields = ["movement_date", "quantity_in", "quantity_out", "unit_cost"]

    def get_queryset(self):
        queryset = StockMovement.objects.select_related(
            "warehouse", "warehouse__shop", "product", "batch", "currency", "created_by"
        )
        if user_can_see_all_shop_data(self.request.user, self.required_tab):
            return queryset
        return queryset.filter(
            get_user_data_filter(self.request.user, "warehouse__shop")
        ).distinct()
