from django.core.exceptions import ValidationError as DjangoValidationError
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from account.permissions import HasTabPermission, HasActionPermission, get_user_data_filter, user_can_see_all_shop_data
from shop_management.models.data.stock_adjustment import StockAdjustment
from shop_management.serializers.data.stock_adjustment import StockAdjustmentSerializer
from shop_management.services.stock_adjustments import post_stock_adjustment, void_stock_adjustment
from shop_management.views.data.base import DataRootViewSet
from shop_management.views.data.pagination import CustomPagination


class StockAdjustmentViewSet(DataRootViewSet):
    serializer_class = StockAdjustmentSerializer
    permission_classes = [IsAuthenticated, HasTabPermission, HasActionPermission]
    action_permission_map = {"create": "inventory.adjust_stock", "post": "inventory.adjust_stock", "void": "inventory.adjust_stock"}
    required_tab = "stock"
    pagination_class = CustomPagination
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ["warehouse", "status", "adjustment_date"]
    search_fields = ["adjustment_number", "reason", "notes", "warehouse__name"]
    ordering_fields = ["adjustment_date", "created_at", "posted_at"]

    def get_queryset(self):
        queryset = StockAdjustment.objects.select_related(
            "warehouse", "warehouse__shop", "posted_by", "voided_by"
        ).prefetch_related("items__product", "items__batch", "items__currency")
        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()

    def perform_destroy(self, instance):
        if instance.status != StockAdjustment.Status.DRAFT:
            raise ValidationError("Only draft adjustments can be deleted.")
        instance.delete()

    @action(detail=True, methods=["post"])
    def post(self, request, pk=None):
        try:
            adjustment = post_stock_adjustment(pk, user=request.user)
        except DjangoValidationError as exc:
            raise ValidationError(exc.message_dict if hasattr(exc, "message_dict") else exc.messages)
        return Response(self.get_serializer(adjustment).data)

    @action(detail=True, methods=["post"])
    def void(self, request, pk=None):
        try:
            adjustment = void_stock_adjustment(
                pk, user=request.user, reason=request.data.get("reason", "")
            )
        except DjangoValidationError as exc:
            raise ValidationError(exc.message_dict if hasattr(exc, "message_dict") else exc.messages)
        return Response(self.get_serializer(adjustment).data, status=status.HTTP_200_OK)
