from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
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.shop_account import Account
from shop_management.serializers.data.shop_account import AccountSerializer
from shop_management.views.data.base import DataRootViewSet
from shop_management.views.data.pagination import CustomPagination


class AccountViewSet(DataRootViewSet):
    serializer_class = AccountSerializer
    permission_classes = [IsAuthenticated, HasTabPermission]
    required_tab = "accounts"
    filter_backends = [DjangoFilterBackend, SearchFilter]
    filterset_fields = ["shop", "currency", "is_active"]
    search_fields = ["name", "note"]
    pagination_class = CustomPagination

    def get_queryset(self):
        qs = Account.objects.select_related("shop", "currency").order_by(
            "-id"
        )
        if str(self.request.query_params.get("include_system", "")).lower() not in {"1", "true", "yes"}:
            qs = qs.filter(is_system_account=False)
        if user_can_see_all_shop_data(self.request.user, self.required_tab):
            return qs
        return qs.filter(get_user_data_filter(self.request.user, "shop")).distinct()

    def destroy(self, request, *args, **kwargs):
        account = self.get_object()
        if account.is_system_account:
            return Response(
                {"detail": "System accounts cannot be deleted."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Financial records must retain their account reference for reports and
        # audits.  Checking every reverse relation also covers newer document
        # types that may be added after the original transaction model.
        has_related_records = any(
            getattr(account, relation.get_accessor_name()).exists()
            for relation in account._meta.related_objects
            if relation.get_accessor_name()
        )
        if account.opening_balance != 0 or has_related_records:
            return Response(
                {
                    "detail": (
                        "This account has an opening balance or financial history and cannot "
                        "be deleted. Deactivate it instead."
                    )
                },
                status=status.HTTP_400_BAD_REQUEST,
            )
        return super().destroy(request, *args, **kwargs)
