from django.db import transaction
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.response import Response

from apps.core.mixins.search_mixin import DynamicSearchMixin
from apps.herd.models import Rancher
from apps.pos_device.mixins.pos_device_mixin import POSDeviceMixin
from apps.warehouse import models as warehouse_models
from apps.warehouse.pos.api.v2 import serializers as warehouse_serializers
from apps.warehouse.services.services import (
    can_buy_from_inventory
)


class InventoryEntryViewSet(viewsets.ModelViewSet, DynamicSearchMixin, POSDeviceMixin):
    queryset = warehouse_models.InventoryEntry.objects.all()
    serializer_class = warehouse_serializers.InventoryEntrySerializer
    permission_classes = [AllowAny]
    search_fields = [
        "distribution__distribution_id",
        "organization__name",
        "weight",
        "balance",
        "lading_number",
        "is_confirmed",
    ]
    date_field = "create_date"

    @action(
        methods=['get'],
        detail=False,
        url_path='my_entries',
        url_name='my_entries',
        name='my_entries'
    )
    def inventory_entries(self, request):
        """ list of pos inventory entries """

        organization = self.get_device_organization()
        device = self.get_pos_device()

        entries = self.queryset.filter(organization=organization)
        queryset = self.filter_query(entries)  # return by search param or all objects

        # paginate & response
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True, context={'device': device})
            return self.get_paginated_response(serializer.data)

    @action(
        methods=['get'],
        detail=False,
        url_path='rancher_inventory_entries',
        url_name='rancher_inventory_entries',
        name='rancher_inventory_entries'
    )
    @transaction.atomic
    def rancher_inventory_entries(self, request):
        """ list of inventory entries (quotas) for rancher """

        organization = self.get_device_organization()
        device = self.get_pos_device()
        rancher = Rancher.objects.filter(national_code=request.GET['national_code'])
        entries = self.queryset.filter(organization=organization)

        # check quota inventory entries for rancher
        available_entries = [
            entry for entry in entries if (can_buy_from_inventory(rancher.first(), entry) & rancher.exists())
        ]

        # paginate & response
        page = self.paginate_queryset(available_entries)  # noqa
        if page is not None:  # noqa
            serializer = self.get_serializer(page, many=True, context={'rancher': rancher.first(), 'device': device})
            # set custom message for paginator
            if not rancher:
                self.paginator.set_message("دامدار با کد ملی مد نظر یافت نشد")  # noqa
            elif not available_entries:
                self.paginator.set_message("دامدار با کد ملی مد نظر سهمیه ایی ندارد")  # noqa
            return self.get_paginated_response(serializer.data)


class InventoryQuotaSaleTransactionViewSet(viewsets.ModelViewSet, DynamicSearchMixin, POSDeviceMixin):
    queryset = warehouse_models.InventoryQuotaSaleTransaction.objects.all().prefetch_related('items')
    serializer_class = warehouse_serializers.InventoryQuotaSaleTransactionSerializer
    permission_classes = [AllowAny]
    search_fields = [
        "rancher__union_name",
        "rancher__union_code",
        "rancher__first_name",
        "rancher__last_name",
        "rancher__national_code",
        "pos_device__device_identity",
        "pos_device__serial",
        "transaction_id",
        "seller_organization__name",
        "quota_distribution__distribution_id",
        "inventory_entry__distribution__distribution_id",
        "transaction_status",
        "delivery_address",
        "product_type",
    ]
    date_field = "create_date"

    def list(self, request, *args, **kwargs):
        """ pos transactions list """

        # get device object
        device = self.get_pos_device()

        queryset = self.queryset.filter(pos_device=device).order_by('-modify_date')
        queryset = self.filter_query(queryset)

        # paginate & response
        page = self.paginate_queryset(queryset)
        if page is not None:  # noqa
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

    @transaction.atomic
    def create(self, request, *args, **kwargs):
        """ create transaction with product items """

        organization = self.get_device_organization()
        device = self.get_pos_device()

        serializer = self.serializer_class(data=request.data, context={
            'organization': organization,
            'pos_device': device,
            'request': self.request

        })
        if serializer.is_valid(raise_exception=True):
            serializer.save()

            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN)


class QuotaPreSaleItemViewSet(viewsets.ModelViewSet, DynamicSearchMixin, POSDeviceMixin):
    queryset = warehouse_models.QuotaPreSaleItem.objects.all().select_related(
        'organization', 'transaction', 'sale_item'
    )
    serializer_class = warehouse_serializers.QuotaPreSaleItemSerializer
