from django.db import transaction
from django.utils.dateparse import parse_date
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status
from rest_framework.filters import SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from account.permissions import (
    HasTabPermission,
    get_user_data_filter,
    user_can_see_all_shop_data,
)
from shop_management.models.data.quotation import Quotation, QuotationItem
from shop_management.serializers.data.quotation import QuotationSerializer
from shop_management.views.data.base import DataRootViewSet
from shop_management.views.data.pagination import CustomPagination


class QuotationViewSet(DataRootViewSet):
    serializer_class = QuotationSerializer
    permission_classes = [IsAuthenticated, HasTabPermission]
    required_tab = "quotations"
    filter_backends = [DjangoFilterBackend, SearchFilter]
    filterset_fields = ["shop", "customer"]
    search_fields = [
        "visitor_name",
        "visitor_contact",
        "customer__name",
        "quotation_items__product__name",
        "quotation_items__product__code",
        "notes",
    ]
    pagination_class = CustomPagination

    def get_queryset(self):
        if user_can_see_all_shop_data(self.request.user, self.required_tab):
            queryset = Quotation.objects.filter(is_deleted=False)
        else:
            queryset = Quotation.objects.filter(
                get_user_data_filter(self.request.user, "shop"),
                is_deleted=False,
            ).distinct()

        selected_shop_id = self.request.headers.get("X-Selected-Shop") or self.request.META.get(
            "HTTP_X_SELECTED_SHOP"
        )
        if selected_shop_id and not user_can_see_all_shop_data(
            self.request.user, self.required_tab
        ):
            queryset = queryset.filter(shop_id=selected_shop_id)

        start_date = self.request.query_params.get("start_date")
        end_date = self.request.query_params.get("end_date")
        if start_date:
            start_date = parse_date(start_date)
            if start_date:
                queryset = queryset.filter(quotation_date__gte=start_date)
        if end_date:
            end_date = parse_date(end_date)
            if end_date:
                queryset = queryset.filter(quotation_date__lte=end_date)

        return queryset.select_related(
            "shop", "customer", "currency"
        ).prefetch_related(
            "quotation_items__product", "quotation_items__unit"
        ).order_by("-id")

    @staticmethod
    def _parse_items(raw_items):
        if not isinstance(raw_items, list):
            return []
        parsed = []
        for item in raw_items:
            product_id = item.get("product")
            quantity = int(item.get("quantity") or 0)
            unit_price = item.get("unit_price")
            if not product_id or quantity <= 0 or unit_price in (None, ""):
                continue
            parsed.append(
                {
                    "product_id": product_id,
                    "quantity": quantity,
                    "unit_id": item.get("unit") or None,
                    "unit_price": unit_price,
                }
            )
        return parsed

    def create(self, request, *args, **kwargs):
        data = request.data.copy() if hasattr(request.data, "copy") else dict(request.data)
        items = self._parse_items(data.pop("quotation_items", []))
        if not items:
            return Response(
                {"quotation_items": "At least one line item is required."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        with transaction.atomic():
            quotation = serializer.save(created_by=request.user)
            for item in items:
                QuotationItem.objects.create(
                    quotation=quotation,
                    product_id=item["product_id"],
                    quantity=item["quantity"],
                    unit_id=item["unit_id"],
                    unit_price=item["unit_price"],
                    created_by=request.user,
                )
        quotation.refresh_from_db()
        return Response(
            QuotationSerializer(quotation).data,
            status=status.HTTP_201_CREATED,
        )

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop("partial", False)
        instance = self.get_object()
        data = request.data.copy() if hasattr(request.data, "copy") else dict(request.data)
        items_raw = data.pop("quotation_items", None)
        items = self._parse_items(items_raw) if items_raw is not None else None

        serializer = self.get_serializer(instance, data=data, partial=partial)
        serializer.is_valid(raise_exception=True)
        with transaction.atomic():
            quotation = serializer.save()
            if items is not None:
                if not items:
                    return Response(
                        {"quotation_items": "At least one line item is required."},
                        status=status.HTTP_400_BAD_REQUEST,
                    )
                quotation.quotation_items.all().delete()
                for item in items:
                    QuotationItem.objects.create(
                        quotation=quotation,
                        product_id=item["product_id"],
                        quantity=item["quantity"],
                        unit_id=item["unit_id"],
                        unit_price=item["unit_price"],
                        created_by=request.user,
                    )
        quotation.refresh_from_db()
        return Response(QuotationSerializer(quotation).data)
