"""
Billing Views - Payment confirmation and management
"""
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import AllowAny
from django.db import transaction
from django.db.models import Q
from django.utils import timezone
from django.http import HttpResponse
from datetime import timedelta
from igny8_core.api.response import success_response, error_response, paginated_response
from igny8_core.api.permissions import IsAdminOrOwner, IsAuthenticatedAndActive, HasTenantAccess
from igny8_core.api.base import AccountModelViewSet
from igny8_core.api.pagination import CustomPageNumberPagination
from igny8_core.auth.models import Account, Subscription
from igny8_core.business.billing.services.credit_service import CreditService
from igny8_core.business.billing.services.invoice_service import InvoiceService
from igny8_core.business.billing.models import (
    CreditTransaction, Invoice, Payment, CreditPackage, 
    AccountPaymentMethod, PaymentMethodConfig
)
from igny8_core.modules.billing.serializers import PaymentMethodConfigSerializer, PaymentConfirmationSerializer
import logging

logger = logging.getLogger(__name__)


class BillingViewSet(viewsets.GenericViewSet):
    """
    ViewSet for billing operations (admin-only).
    """
    permission_classes = [IsAdminOrOwner]
    
    def get_permissions(self):
        """
        Allow action-level permissions to override class-level permissions.
        """
        # Try to get permission_classes from the action
        try:
            # DRF stores action permission_classes in the view method
            return [permission() for permission in self.permission_classes]
        except Exception:
            return super().get_permissions()
    
    @action(detail=False, methods=['post'], url_path='confirm-bank-transfer')
    def confirm_bank_transfer(self, request):
        """
        Confirm a bank transfer payment and activate/renew subscription.
        
        Request body:
        {
            "account_id": 123,
            "external_payment_id": "BT-2025-001",
            "amount": "29.99",
            "payer_name": "John Doe",
            "proof_url": "https://...",
            "period_months": 1
        }
        """
        account_id = request.data.get('account_id')
        subscription_id = request.data.get('subscription_id')
        external_payment_id = request.data.get('external_payment_id')
        amount = request.data.get('amount')
        payer_name = request.data.get('payer_name')
        proof_url = request.data.get('proof_url')
        period_months = int(request.data.get('period_months', 1))
        
        if not all([external_payment_id, amount, payer_name]):
            return error_response(
                error='external_payment_id, amount, and payer_name are required',
                status_code=status.HTTP_400_BAD_REQUEST,
                request=request
            )
        
        if not account_id and not subscription_id:
            return error_response(
                error='Either account_id or subscription_id is required',
                status_code=status.HTTP_400_BAD_REQUEST,
                request=request
            )
        
        try:
            with transaction.atomic():
                # Get account
                if account_id:
                    account = Account.objects.select_related('plan').get(id=account_id)
                    subscription = getattr(account, 'subscription', None)
                else:
                    subscription = Subscription.objects.select_related('account', 'account__plan').get(id=subscription_id)
                    account = subscription.account
                
                if not account or not account.plan:
                    return error_response(
                        error='Account or plan not found',
                        status_code=status.HTTP_404_NOT_FOUND,
                        request=request
                    )
                
                # Calculate period dates based on billing cycle
                now = timezone.now()
                if account.plan.billing_cycle == 'monthly':
                    period_end = now + timedelta(days=30 * period_months)
                elif account.plan.billing_cycle == 'annual':
                    period_end = now + timedelta(days=365 * period_months)
                else:
                    period_end = now + timedelta(days=30 * period_months)
                
                # Create or update subscription
                if not subscription:
                    subscription = Subscription.objects.create(
                        account=account,
                        payment_method='bank_transfer',
                        external_payment_id=external_payment_id,
                        status='active',
                        current_period_start=now,
                        current_period_end=period_end,
                        cancel_at_period_end=False
                    )
                else:
                    subscription.payment_method = 'bank_transfer'
                    subscription.external_payment_id = external_payment_id
                    subscription.status = 'active'
                    subscription.current_period_start = now
                    subscription.current_period_end = period_end
                    subscription.cancel_at_period_end = False
                    subscription.save()
                
                # Update account
                account.payment_method = 'bank_transfer'
                account.status = 'active'
                monthly_credits = account.plan.get_effective_credits_per_month()
                account.credits = monthly_credits
                account.save()
                
                # Log transaction
                CreditTransaction.objects.create(
                    account=account,
                    transaction_type='subscription',
                    amount=monthly_credits,
                    balance_after=monthly_credits,
                    description=f'Bank transfer payment confirmed: {external_payment_id}',
                    metadata={
                        'external_payment_id': external_payment_id,
                        'amount': str(amount),
                        'payer_name': payer_name,
                        'proof_url': proof_url if proof_url else '',
                        'period_months': period_months,
                        'confirmed_by': request.user.email
                    }
                )
                
                logger.info(
                    f'Bank transfer confirmed for account {account.id}: '
                    f'{external_payment_id}, {amount}, {monthly_credits} credits added'
                )
                
                return success_response(
                    data={
                        'account_id': account.id,
                        'subscription_id': subscription.id,
                        'status': 'active',
                        'credits': account.credits,
                        'period_start': subscription.current_period_start.isoformat(),
                        'period_end': subscription.current_period_end.isoformat()
                    },
                    message='Bank transfer confirmed successfully',
                    request=request
                )
                
        except Account.DoesNotExist:
            return error_response(
                error='Account not found',
                status_code=status.HTTP_404_NOT_FOUND,
                request=request
            )
        except Subscription.DoesNotExist:
            return error_response(
                error='Subscription not found',
                status_code=status.HTTP_404_NOT_FOUND,
                request=request
            )
        except Exception as e:
            logger.error(f'Error confirming bank transfer: {str(e)}', exc_info=True)
            return error_response(
                error=f'Failed to confirm payment: {str(e)}',
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                request=request
            )
    
    @action(detail=False, methods=['get'], url_path='payment-methods', permission_classes=[AllowAny])
    def list_payment_methods(self, request):
        """
        Get available payment methods for a specific country.
        Public endpoint - only returns enabled payment methods.
        Does not expose sensitive configuration details.
        
        Query params:
            country: ISO 2-letter country code (default: 'US')
        
        Returns payment methods filtered by country.
        """
        country = request.GET.get('country', 'US').upper()
        
        # Get country-specific methods
        methods = PaymentMethodConfig.objects.filter(
            country_code=country,
            is_enabled=True
        ).order_by('sort_order')
        
        # Serialize using the proper serializer
        serializer = PaymentMethodConfigSerializer(methods, many=True)
        
        # Return in consistent format
        return Response({
            'success': True,
            'results': serializer.data
        }, status=status.HTTP_200_OK)
    
    @action(detail=False, methods=['post'], url_path='payments/confirm', permission_classes=[IsAuthenticatedAndActive])
    def confirm_payment(self, request):
        """
        User confirms manual payment (bank transfer or local wallet).
        Creates Payment record with status='pending_approval' for admin review.
        
        Request body:
        {
            "invoice_id": 123,
            "payment_method": "bank_transfer",
            "manual_reference": "BT-20251208-12345",
            "manual_notes": "Transferred via ABC Bank",
            "amount": "29.00",
            "proof_url": "https://..."  // optional
        }
        """
        serializer = PaymentConfirmationSerializer(data=request.data)
        if not serializer.is_valid():
            return error_response(
                error=serializer.errors,
                status_code=status.HTTP_400_BAD_REQUEST,
                request=request
            )
        
        invoice_id = serializer.validated_data['invoice_id']
        payment_method = serializer.validated_data['payment_method']
        manual_reference = serializer.validated_data['manual_reference']
        manual_notes = serializer.validated_data.get('manual_notes', '')
        amount = serializer.validated_data['amount']
        proof_url = serializer.validated_data.get('proof_url')
        
        try:
            # Get invoice - must belong to user's account
            invoice = Invoice.objects.select_related('account').get(
                id=invoice_id,
                account=request.account
            )
            
            # Check if payment already exists for this invoice
            existing_payment = Payment.objects.filter(
                invoice=invoice,
                status__in=['pending_approval', 'succeeded']
            ).first()
            
            if existing_payment:
                if existing_payment.status == 'succeeded':
                    return error_response(
                        error='This invoice has already been paid and approved.',
                        status_code=status.HTTP_400_BAD_REQUEST,
                        request=request
                    )
                else:
                    return error_response(
                        error=f'A payment confirmation is already pending approval for this invoice (Payment ID: {existing_payment.id}).',
                        status_code=status.HTTP_400_BAD_REQUEST,
                        request=request
                    )
            
            # Validate amount matches invoice
            if amount != invoice.total:
                return error_response(
                    error=f'Amount mismatch. Invoice total is {invoice.total} {invoice.currency}',
                    status_code=status.HTTP_400_BAD_REQUEST,
                    request=request
                )
            
            # Create payment record with pending approval status
            payment = Payment.objects.create(
                account=request.account,
                invoice=invoice,
                amount=amount,
                currency=invoice.currency,
                status='pending_approval',
                payment_method=payment_method,
                manual_reference=manual_reference,
                manual_notes=manual_notes,
                metadata={'proof_url': proof_url, 'submitted_by': request.user.email} if proof_url else {'submitted_by': request.user.email}
            )
            
            logger.info(
                f'Payment confirmation submitted: Payment {payment.id}, '
                f'Invoice {invoice.invoice_number}, Account {request.account.id}, '
                f'Reference: {manual_reference}'
            )
            
            # Send email notification to user
            try:
                from igny8_core.business.billing.services.email_service import BillingEmailService
                BillingEmailService.send_payment_confirmation_email(payment, request.account)
            except Exception as e:
                logger.error(f'Failed to send payment confirmation email: {str(e)}')
            
            return success_response(
                data={
                    'payment_id': payment.id,
                    'invoice_id': invoice.id,
                    'invoice_number': invoice.invoice_number,
                    'status': 'pending_approval',
                    'amount': str(amount),
                    'currency': invoice.currency,
                    'manual_reference': manual_reference
                },
                message='Payment confirmation submitted for review. You will be notified once approved.',
                request=request
            )
            
        except Invoice.DoesNotExist:
            return error_response(
                error='Invoice not found. Please check the invoice ID or contact support.',
                status_code=status.HTTP_404_NOT_FOUND,
                request=request
            )
        except ValueError as ve:
            return error_response(
                error=f'Invalid amount format: {str(ve)}',
                status_code=status.HTTP_400_BAD_REQUEST,
                request=request
            )
        except Exception as e:
            logger.error(f'Error confirming payment: {str(e)}', exc_info=True)
            return error_response(
                error='An unexpected error occurred while processing your payment confirmation. Please try again or contact support.',
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                request=request
            )
    
    @action(detail=True, methods=['post'], url_path='approve', permission_classes=[IsAdminOrOwner])
    def approve_payment(self, request, pk=None):
        """
        Admin approves a manual payment.
        Atomically updates: payment status → invoice paid → subscription active → account active → add credits.
        
        Request body:
        {
            "admin_notes": "Verified payment in bank statement"
        }
        """
        admin_notes = request.data.get('admin_notes', '')
        
        try:
            with transaction.atomic():
                # Get payment with all related objects to prevent N+1 queries
                payment = Payment.objects.select_related(
                    'invoice',
                    'invoice__subscription',
                    'invoice__subscription__plan',
                    'account',
                    'account__subscription',
                    'account__subscription__plan',
                    'account__plan'
                ).get(id=pk)
                
                if payment.status != 'pending_approval':
                    status_msg = {
                        'succeeded': 'This payment has already been approved and processed',
                        'failed': 'This payment was previously rejected and cannot be approved',
                        'refunded': 'This payment was refunded and cannot be re-approved'
                    }.get(payment.status, f'Payment has invalid status: {payment.status}')
                    return error_response(
                        error=status_msg,
                        status_code=status.HTTP_400_BAD_REQUEST,
                        request=request
                    )
                
                invoice = payment.invoice
                account = payment.account
                
                # Validate invoice is still pending
                if invoice.status == 'paid':
                    return error_response(
                        error='Invoice is already marked as paid. Payment cannot be approved again.',
                        status_code=status.HTTP_400_BAD_REQUEST,
                        request=request
                    )
                
                # Validate invoice is not void
                if invoice.status == 'void':
                    return error_response(
                        error='Invoice has been voided. Payment cannot be approved for a void invoice.',
                        status_code=status.HTTP_400_BAD_REQUEST,
                        request=request
                    )
                
                # Validate amount matches
                if payment.amount != invoice.total:
                    return error_response(
                        error=f'Payment amount ({payment.currency} {payment.amount}) does not match invoice total ({invoice.currency} {invoice.total}). Please verify the payment.',
                        status_code=status.HTTP_400_BAD_REQUEST,
                        request=request
                    )
                
                # Get subscription from invoice first, fallback to account.subscription
                subscription = None
                if invoice and hasattr(invoice, 'subscription') and invoice.subscription:
                    subscription = invoice.subscription
                elif account and hasattr(account, 'subscription'):
                    try:
                        subscription = account.subscription
                    except Exception:
                        pass
                
                # 1. Update Payment
                payment.status = 'succeeded'
                payment.approved_by = request.user
                payment.approved_at = timezone.now()
                payment.processed_at = timezone.now()
                payment.admin_notes = admin_notes
                payment.save(update_fields=['status', 'approved_by', 'approved_at', 'processed_at', 'admin_notes'])
                
                # 2. Update Invoice
                invoice.status = 'paid'
                invoice.paid_at = timezone.now()
                invoice.save(update_fields=['status', 'paid_at'])
                
                # 3. Update Subscription
                if subscription:
                    subscription.status = 'active'
                    subscription.external_payment_id = payment.manual_reference
                    subscription.save(update_fields=['status', 'external_payment_id'])
                
                # 4. Update Account
                account.status = 'active'
                account.save(update_fields=['status'])
                
                # 5. Add Credits (if subscription has plan)
                credits_added = 0
                try:
                    if subscription and subscription.plan and subscription.plan.included_credits > 0:
                        credits_added = subscription.plan.included_credits
                        
                        # Use CreditService to add credits
                        CreditService.add_credits(
                            account=account,
                            amount=credits_added,
                            transaction_type='subscription',
                            description=f'{subscription.plan.name} plan credits - Invoice {invoice.invoice_number}',
                            metadata={
                                'subscription_id': subscription.id,
                                'invoice_id': invoice.id,
                                'payment_id': payment.id,
                                'plan_id': subscription.plan.id,
                                'approved_by': request.user.email
                            }
                        )
                    elif account and account.plan and account.plan.included_credits > 0:
                        # Fallback: use account plan if subscription not found
                        credits_added = account.plan.included_credits
                        CreditService.add_credits(
                            account=account,
                            amount=credits_added,
                            transaction_type='subscription',
                            description=f'{account.plan.name} plan credits - Invoice {invoice.invoice_number}',
                            metadata={
                                'invoice_id': invoice.id,
                                'payment_id': payment.id,
                                'plan_id': account.plan.id,
                                'approved_by': request.user.email,
                                'fallback': 'account_plan'
                            }
                        )
                except Exception as credit_error:
                    # Rollback payment approval if credit addition fails
                    logger.error(f'Credit addition failed for payment {payment.id}: {credit_error}', exc_info=True)
                    raise Exception(f'Failed to add credits: {str(credit_error)}') from credit_error
                
                logger.info(
                    f'Payment approved: Payment {payment.id}, Invoice {invoice.invoice_number}, '
                    f'Account {account.id} activated, {credits_added} credits added'
                )
                
                # Send activation email to user
                try:
                    from igny8_core.business.billing.services.email_service import BillingEmailService
                    BillingEmailService.send_payment_approved_email(payment, account, subscription)
                except Exception as e:
                    logger.error(f'Failed to send payment approved email: {str(e)}')
                
                return success_response(
                    data={
                        'payment_id': payment.id,
                        'invoice_id': invoice.id,
                        'invoice_number': invoice.invoice_number,
                        'account_id': account.id,
                        'account_status': account.status,
                        'subscription_status': subscription.status if subscription else None,
                        'credits_added': credits_added,
                        'total_credits': account.credits,
                        'approved_by': request.user.email,
                        'approved_at': payment.approved_at.isoformat()
                    },
                    message='Payment approved successfully. Account activated.',
                    request=request
                )
                
        except Payment.DoesNotExist:
            return error_response(
                error='Payment not found. The payment may have been deleted or the ID is incorrect.',
                status_code=status.HTTP_404_NOT_FOUND,
                request=request
            )
        except Exception as e:
            logger.error(f'Error approving payment {pk}: {str(e)}', exc_info=True)
            
            # Provide specific error messages
            error_msg = str(e)
            if 'credit' in error_msg.lower():
                error_msg = 'Failed to add credits to account. Payment not approved. Please check the plan configuration.'
            elif 'subscription' in error_msg.lower():
                error_msg = 'Failed to activate subscription. Payment not approved. Please verify subscription exists.'
            else:
                error_msg = f'Payment approval failed: {error_msg}'
            
            return error_response(
                error=error_msg,
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                request=request
            )
    
    @action(detail=True, methods=['post'], url_path='reject', permission_classes=[IsAdminOrOwner])
    def reject_payment(self, request, pk=None):
        """
        Admin rejects a manual payment.
        
        Request body:
        {
            "admin_notes": "Transaction reference not found in bank statement"
        }
        """
        admin_notes = request.data.get('admin_notes', 'Payment rejected by admin')
        
        try:
            payment = Payment.objects.get(id=pk)
            
            if payment.status != 'pending_approval':
                return error_response(
                    error=f'Payment is not pending approval (current status: {payment.status})',
                    status_code=status.HTTP_400_BAD_REQUEST,
                    request=request
                )
            
            payment.status = 'failed'
            payment.approved_by = request.user
            payment.approved_at = timezone.now()
            payment.failed_at = timezone.now()
            payment.admin_notes = admin_notes
            payment.failure_reason = admin_notes
            payment.save(update_fields=['status', 'approved_by', 'approved_at', 'failed_at', 'admin_notes', 'failure_reason'])
            
            # Update account status to allow retry
            account = payment.account
            if account.status != 'active':
                account.status = 'pending_payment'
                account.save(update_fields=['status'])
            
            logger.info(f'Payment rejected: Payment {payment.id}, Reason: {admin_notes}')
            
            # Send rejection email to user
            try:
                from igny8_core.business.billing.services.email_service import BillingEmailService
                BillingEmailService.send_payment_rejected_email(payment, account, admin_notes)
            except Exception as e:
                logger.error(f'Failed to send payment rejected email: {str(e)}')
            
            return success_response(
                data={
                    'payment_id': payment.id,
                    'status': 'failed',
                    'rejected_by': request.user.email,
                    'rejected_at': payment.approved_at.isoformat()
                },
                message='Payment rejected.',
                request=request
            )
            
        except Payment.DoesNotExist:
            return error_response(
                error='Payment not found. The payment may have been deleted or the ID is incorrect.',
                status_code=status.HTTP_404_NOT_FOUND,
                request=request
            )
        except Exception as e:
            logger.error(f'Error rejecting payment {pk}: {str(e)}', exc_info=True)
            return error_response(
                error=f'Failed to reject payment. Please try again or contact technical support.',
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                request=request
            )


class InvoiceViewSet(AccountModelViewSet):
    """ViewSet for user-facing invoices"""
    queryset = Invoice.objects.all().select_related('account')
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    pagination_class = CustomPageNumberPagination
    
    def get_queryset(self):
        """Filter invoices by account"""
        queryset = super().get_queryset()
        if hasattr(self.request, 'account') and self.request.account:
            queryset = queryset.filter(account=self.request.account)
        return queryset.order_by('-invoice_date', '-created_at')
    
    def list(self, request):
        """List invoices for current account"""
        queryset = self.get_queryset()
        
        # Filter by status if provided
        status_param = request.query_params.get('status')
        if status_param:
            queryset = queryset.filter(status=status_param)
        
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(queryset, request)
        
        # Serialize invoice data
        results = []
        for invoice in (page if page is not None else []):
            results.append({
                'id': invoice.id,
                'invoice_number': invoice.invoice_number,
                'status': invoice.status,
                'total': str(invoice.total),  # Alias for compatibility
                'total_amount': str(invoice.total),
                'subtotal': str(invoice.subtotal),
                'tax_amount': str(invoice.tax),
                'currency': invoice.currency,
                'invoice_date': invoice.invoice_date.isoformat(),
                'due_date': invoice.due_date.isoformat(),
                'paid_at': invoice.paid_at.isoformat() if invoice.paid_at else None,
                'line_items': invoice.line_items,
                'billing_email': invoice.billing_email,
                'notes': invoice.notes,
                'created_at': invoice.created_at.isoformat(),
            })
        
        return paginated_response(
            {'count': paginator.page.paginator.count, 'next': paginator.get_next_link(), 'previous': paginator.get_previous_link(), 'results': results},
            request=request
        )
    
    def retrieve(self, request, pk=None):
        """Get invoice detail"""
        try:
            invoice = self.get_queryset().get(pk=pk)
            data = {
                'id': invoice.id,
                'invoice_number': invoice.invoice_number,
                'status': invoice.status,
                'total': str(invoice.total),  # Alias for compatibility
                'total_amount': str(invoice.total),
                'subtotal': str(invoice.subtotal),
                'tax_amount': str(invoice.tax),
                'currency': invoice.currency,
                'invoice_date': invoice.invoice_date.isoformat(),
                'due_date': invoice.due_date.isoformat(),
                'paid_at': invoice.paid_at.isoformat() if invoice.paid_at else None,
                'line_items': invoice.line_items,
                'billing_email': invoice.billing_email,
                'notes': invoice.notes,
                'created_at': invoice.created_at.isoformat(),
            }
            return success_response(data=data, request=request)
        except Invoice.DoesNotExist:
            return error_response(error='Invoice not found', status_code=404, request=request)
    
    @action(detail=True, methods=['get'])
    def download_pdf(self, request, pk=None):
        """Download invoice PDF"""
        try:
            invoice = self.get_queryset().get(pk=pk)
            pdf_bytes = InvoiceService.generate_pdf(invoice)
            
            response = HttpResponse(pdf_bytes, content_type='application/pdf')
            response['Content-Disposition'] = f'attachment; filename="invoice-{invoice.invoice_number}.pdf"'
            return response
        except Invoice.DoesNotExist:
            return error_response(error='Invoice not found', status_code=404, request=request)


class PaymentViewSet(AccountModelViewSet):
    """ViewSet for user-facing payments"""
    queryset = Payment.objects.all().select_related('account', 'invoice')
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    pagination_class = CustomPageNumberPagination
    throttle_scope = 'payment_confirmation'
    
    def get_throttles(self):
        """Apply stricter throttling to manual payment submission"""
        from rest_framework.throttling import UserRateThrottle
        if self.action == 'manual':
            # 5 payment submissions per hour per user
            class PaymentSubmissionThrottle(UserRateThrottle):
                rate = '5/hour'
            return [PaymentSubmissionThrottle()]
        return super().get_throttles()
    
    def get_queryset(self):
        """Filter payments by account"""
        queryset = super().get_queryset()
        if hasattr(self.request, 'account') and self.request.account:
            queryset = queryset.filter(account=self.request.account)
        return queryset.order_by('-created_at')
    
    def list(self, request):
        """List payments for current account"""
        queryset = self.get_queryset()
        
        # Filter by status if provided
        status_param = request.query_params.get('status')
        if status_param:
            queryset = queryset.filter(status=status_param)
        
        # Filter by invoice if provided
        invoice_id = request.query_params.get('invoice_id')
        if invoice_id:
            queryset = queryset.filter(invoice_id=invoice_id)
        
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(queryset, request)
        
        # Serialize payment data
        results = []
        for payment in (page if page is not None else []):
            results.append({
                'id': payment.id,
                'invoice_id': payment.invoice_id,
                'invoice_number': payment.invoice.invoice_number if payment.invoice else None,
                'amount': str(payment.amount),
                'currency': payment.currency,
                'status': payment.status,
                'payment_method': payment.payment_method,
                'created_at': payment.created_at.isoformat(),
                'processed_at': payment.processed_at.isoformat() if payment.processed_at else None,
                'manual_reference': payment.manual_reference,
                'manual_notes': payment.manual_notes,
                # admin_notes intentionally excluded - internal only
            })
        
        return paginated_response(
            {'count': paginator.page.paginator.count, 'next': paginator.get_next_link(), 'previous': paginator.get_previous_link(), 'results': results},
            request=request
        )
    
    @action(detail=False, methods=['post'])
    def manual(self, request):
        """Submit manual payment for approval"""
        invoice_id = request.data.get('invoice_id')
        amount = request.data.get('amount')
        payment_method = request.data.get('payment_method', 'bank_transfer')
        reference = request.data.get('reference', '')
        notes = request.data.get('notes', '')
        
        if not amount:
            return error_response(error='Amount is required', status_code=400, request=request)
        
        try:
            account = request.account
            invoice = None
            if invoice_id:
                invoice = Invoice.objects.get(id=invoice_id, account=account)
            
            payment = Payment.objects.create(
                account=account,
                invoice=invoice,
                amount=amount,
                currency='USD',
                payment_method=payment_method,
                status='pending_approval',
                manual_reference=reference,
                manual_notes=notes,
            )
            
            return success_response(
                data={'id': payment.id, 'status': payment.status},
                message='Manual payment submitted for approval',
                status_code=201,
                request=request
            )
        except Invoice.DoesNotExist:
            return error_response(error='Invoice not found', status_code=404, request=request)


class CreditPackageViewSet(viewsets.ReadOnlyModelViewSet):
    """ViewSet for credit packages (read-only for users)"""
    queryset = CreditPackage.objects.filter(is_active=True).order_by('sort_order')
    permission_classes = [IsAuthenticatedAndActive]
    pagination_class = CustomPageNumberPagination
    
    def list(self, request):
        """List available credit packages"""
        queryset = self.get_queryset()
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(queryset, request)
        
        results = []
        for package in (page if page is not None else []):
            results.append({
                'id': package.id,
                'name': package.name,
                'slug': package.slug,
                'credits': package.credits,
                'price': str(package.price),
                'discount_percentage': package.discount_percentage,
                'is_featured': package.is_featured,
                'description': package.description,
                'display_order': package.sort_order,
            })
        
        return paginated_response(
            {'count': paginator.page.paginator.count, 'next': paginator.get_next_link(), 'previous': paginator.get_previous_link(), 'results': results},
            request=request
        )


class AccountPaymentMethodViewSet(AccountModelViewSet):
    """ViewSet for account payment methods"""
    queryset = AccountPaymentMethod.objects.all()
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    pagination_class = CustomPageNumberPagination
    
    def get_queryset(self):
        """Filter payment methods by account"""
        queryset = super().get_queryset()
        if hasattr(self.request, 'account') and self.request.account:
            queryset = queryset.filter(account=self.request.account)
        return queryset.order_by('-is_default', 'type')
    
    def list(self, request):
        """List payment methods for current account"""
        queryset = self.get_queryset()
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(queryset, request)
        
        results = []
        for method in (page if page is not None else []):
            results.append({
                'id': str(method.id),
                'type': method.type,
                'display_name': method.display_name,
                'is_default': method.is_default,
                'is_enabled': method.is_enabled if hasattr(method, 'is_enabled') else True,
                'instructions': method.instructions,
            })
        
        return paginated_response(
            {'count': paginator.page.paginator.count, 'next': paginator.get_next_link(), 'previous': paginator.get_previous_link(), 'results': results},
            request=request
        )


# ============================================================================
# USAGE SUMMARY (Plan Limits) - User-facing endpoint
# ============================================================================

from rest_framework.decorators import api_view, permission_classes

@api_view(['GET'])
@permission_classes([IsAuthenticatedAndActive, HasTenantAccess])
def get_usage_summary(request):
    """
    Get comprehensive usage summary for current account.
    Includes hard limits (sites, users, keywords, clusters) and monthly limits (ideas, words, images).
    
    GET /api/v1/billing/usage-summary/
    """
    try:
        account = getattr(request, 'account', None)
        if not account:
            return error_response(
                error='Account not found.',
                status_code=status.HTTP_400_BAD_REQUEST,
                request=request
            )
        
        from igny8_core.business.billing.services.limit_service import LimitService
        summary = LimitService.get_usage_summary(account)
        
        return success_response(
            data=summary,
            message='Usage summary retrieved successfully.',
            request=request
        )
    except Exception as e:
        logger.error(f'Error getting usage summary: {str(e)}', exc_info=True)
        return error_response(
            error=f'Failed to retrieve usage summary: {str(e)}',
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            request=request
        )
