
from decimal import Decimal

from rest_framework import generics, permissions, status, viewsets
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from .models import ConversionRule, SuperCoinWallet, UserVoucherCode, Wallet, WalletLedger
from .serializers import (
    ConversionRuleSerializer,
    SuperCoinTransactionSerializer,
    SuperCoinWalletSerializer,
    UserVoucherCodeSerializer,
    WalletSerializer,
    WalletLedgerSerializer,
)
from .services.conversion_service import monthly_conversion_job
from .services.wallet_service import WalletService
from apps.core.utils import error_response

class WalletDetailView(generics.RetrieveAPIView):
    serializer_class = WalletSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_object(self):
        return Wallet.objects.get(user=self.request.user)


class WalletLedgerPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 100

class WalletLedgerListView(generics.ListAPIView):
    serializer_class = WalletLedgerSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = WalletLedgerPagination

    def get_queryset(self):
        queryset = WalletLedger.objects.filter(user=self.request.user).order_by('-created_at')
        wallet_type = (self.request.query_params.get('wallet_type') or '').upper().strip()
        if wallet_type:
            queryset = queryset.filter(wallet_type=wallet_type)
        return queryset

    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            paginated = self.get_paginated_response(serializer.data).data
            return Response({
                "success": True,
                "data": paginated
            })
        serializer = self.get_serializer(queryset, many=True)
        return Response({
            "success": True,
            "data": {
                "count": len(serializer.data),
                "next": None,
                "previous": None,
                "results": serializer.data
            }
        })


class VoucherSummaryView(generics.RetrieveAPIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, *args, **kwargs):
        wallet, _ = Wallet.objects.get_or_create(user=request.user)
        WalletService._expire_voucher_codes(request.user, wallet)
        total_codes = UserVoucherCode.objects.filter(user=request.user).count()
        active_codes = UserVoucherCode.objects.filter(
            user=request.user,
            status__in=[UserVoucherCode.Status.ACTIVE, UserVoucherCode.Status.PARTIAL],
        ).count()

        return Response(
            {
                "success": True,
                "data": {
                    "voucher_balance": wallet.voucher_balance,
                    "twm_coins_balance": wallet.voucher_balance,
                    "total_codes": total_codes,
                    "active_codes": active_codes,
                },
            }
        )


class VoucherCodeListView(generics.ListAPIView):
    serializer_class = UserVoucherCodeSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = WalletLedgerPagination

    def get_queryset(self):
        queryset = UserVoucherCode.objects.filter(user=self.request.user).order_by('-created_at')
        status_filter = (self.request.query_params.get('status') or '').upper().strip()
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        return queryset

    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            paginated = self.get_paginated_response(serializer.data).data
            return Response({"success": True, "data": paginated})

        serializer = self.get_serializer(queryset, many=True)
        return Response(
            {
                "success": True,
                "data": {
                    "count": len(serializer.data),
                    "next": None,
                    "previous": None,
                    "results": serializer.data,
                },
            }
        )


class SuperCoinBalanceView(generics.RetrieveAPIView):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = SuperCoinWalletSerializer

    def get_object(self):
        wallet, _ = SuperCoinWallet.objects.get_or_create(user=self.request.user)
        return wallet


class SuperCoinUseView(generics.GenericAPIView):
    permission_classes = [permissions.IsAuthenticated]

    def post(self, request, *args, **kwargs):
        amount = Decimal(str(request.data.get('amount', '0')))
        reference_id = request.data.get('reference_id') or f"SC_USE_{request.user.id}_{request.data.get('source', 'manual')}"
        source = request.data.get('source', 'SERVICE_PAYMENT')

        try:
            WalletService.debit_supercoins(
                user=request.user,
                amount=amount,
                source_type=source,
                reference_id=reference_id,
                metadata={'requested_via': 'api'},
            )
            wallet, _ = SuperCoinWallet.objects.get_or_create(user=request.user)
            return Response({'success': True, 'data': {'balance': str(wallet.balance)}})
        except Exception as exc:
            return Response({'success': False, 'error': str(exc)}, status=status.HTTP_400_BAD_REQUEST)


class SuperCoinLedgerListView(generics.ListAPIView):
    serializer_class = SuperCoinTransactionSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = WalletLedgerPagination

    def get_queryset(self):
        # Keep source-of-truth on super coin transactions (not wallet ledger).
        return self.request.user.super_coin_transactions.all().order_by('-created_at')

    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            paginated = self.get_paginated_response(serializer.data).data
            return Response({
                "success": True,
                "data": paginated,
            })

        serializer = self.get_serializer(queryset, many=True)
        return Response(
            {
                "success": True,
                "data": {
                    "count": len(serializer.data),
                    "next": None,
                    "previous": None,
                    "results": serializer.data,
                },
            }
        )


class MonthlyConversionRunView(generics.GenericAPIView):
    permission_classes = [permissions.IsAdminUser]

    def post(self, request, *args, **kwargs):
        result = monthly_conversion_job()
        return Response({'success': True, 'data': result})


class AllWalletsView(generics.RetrieveAPIView):
    """
    GET /api/v1/web/wallet/all-balances/
    Returns all wallet balances for the authenticated user in a single response.
    """
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, *args, **kwargs):
        wallet, _ = Wallet.objects.get_or_create(user=request.user)
        super_wallet, _ = SuperCoinWallet.objects.get_or_create(user=request.user)
        return Response({
            'success': True,
            'data': {
                'main_balance': str(wallet.main_balance),
                'repurchase_balance': str(wallet.repurchase_balance),
                'twm_coins_balance': str(wallet.voucher_balance),
                'super_coins_balance': str(super_wallet.balance),
                'locked_amount': str(wallet.locked_amount),
            },
        })


class ProductPaymentConfigView(generics.RetrieveAPIView):
    """
    GET /api/v1/web/products/<pk>/payment-config/
    Returns product-level wallet permission flags together with current user balances.
    """
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, pk=None, *args, **kwargs):
        from apps.business.products.models import Product
        try:
            product = Product.objects.get(pk=pk, is_active=True)
        except Product.DoesNotExist:
            return Response({'success': False, 'error': 'Product not found.'}, status=status.HTTP_404_NOT_FOUND)

        wallet, _ = Wallet.objects.get_or_create(user=request.user)
        super_wallet, _ = SuperCoinWallet.objects.get_or_create(user=request.user)

        return Response({
            'success': True,
            'data': {
                'product_id': product.id,
                'allow_main_wallet': product.allow_main_wallet,
                'allow_repurchase': product.allow_repurchase,
                'allow_supercoins': product.allow_supercoins,
                'allow_twm': product.allow_twm,
                'twm_max_percentage': product.twm_max_percentage,
                'balances': {
                    'main_balance': str(wallet.main_balance),
                    'repurchase_balance': str(wallet.repurchase_balance),
                    'twm_coins_balance': str(wallet.voucher_balance),
                    'super_coins_balance': str(super_wallet.balance),
                },
            },
        })


class ConversionRuleAdminViewSet(viewsets.ModelViewSet):
    queryset = ConversionRule.objects.select_related('user').all().order_by('-updated_at')
    serializer_class = ConversionRuleSerializer
    permission_classes = [permissions.IsAdminUser]

