import uuid as uuid_lib
from django.db import models as db_models
from rest_framework import status, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from django.utils import timezone
from django.core.cache import cache
from django.conf import settings as django_settings
from datetime import timedelta
from .models import PromotionSlot, ProductPromotion, SponsoredAd
from .serializers import (
    PromotionSlotSerializer, ProductPromotionSerializer, PromotedProductSerializer,
    SponsoredAdSerializer,
)
from products.models import Product
from products.serializers import ProductSerializer
from payments.models import Payment, SystemSettings
from payments.paystack import paystack


class IsVendor(permissions.BasePermission):
    """Permission class for vendor-only access"""
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.user_type == 'vendor' and
            hasattr(request.user, 'vendor_profile')
        )


class IsAdmin(permissions.BasePermission):
    """Permission class for admin-only access"""
    def has_permission(self, request, view):
        return (
            request.user.is_authenticated and
            request.user.user_type == 'admin'
        )


# ============== PUBLIC VIEWS ==============

class PromotionSlotsListView(APIView):
    """List available promotion slots (for vendors to view)"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        slots = PromotionSlot.objects.filter(is_active=True)
        serializer = PromotionSlotSerializer(slots, many=True)
        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


class TrendingProductsView(APIView):
    """Get trending/promoted products, falls back to top products by views"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        try:
            cached = cache.get('trending_products')
            if cached is not None:
                return Response(cached, status=status.HTTP_200_OK)
        except Exception:
            pass

        now = timezone.now()

        promotions = ProductPromotion.objects.filter(
            slot__slot_type='trending',
            is_active=True,
            starts_at__lte=now,
            ends_at__gt=now,
            product__status='active'
        ).select_related('product', 'product__vendor').order_by('-created_at')[:20]

        products = [promo.product for promo in promotions]

        # Fallback: if no promoted trending products, show top products by views
        if not products:
            products = list(
                Product.objects.filter(status='active')
                .select_related('vendor')
                .order_by('-views', '-created_at')[:20]
            )

        serializer = ProductSerializer(products, many=True, context={'request': request})

        response_data = {
            'success': True,
            'data': serializer.data
        }
        try:
            cache.set('trending_products', response_data, 120)  # 2 min
        except Exception:
            pass
        return Response(response_data, status=status.HTTP_200_OK)


class FlashDealsView(APIView):
    """Get flash deal products"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        try:
            cached = cache.get('flash_deals')
            if cached is not None:
                return Response(cached, status=status.HTTP_200_OK)
        except Exception:
            pass

        now = timezone.now()

        promotions = ProductPromotion.objects.filter(
            slot__slot_type='flash_deal',
            is_active=True,
            starts_at__lte=now,
            ends_at__gt=now,
            product__status='active'
        ).select_related('product', 'product__vendor').order_by('-created_at')[:20]

        data = []
        for promo in promotions:
            product_data = ProductSerializer(promo.product, context={'request': request}).data
            product_data['promotion_ends_at'] = promo.ends_at.isoformat()
            data.append(product_data)

        response_data = {
            'success': True,
            'data': data
        }
        try:
            cache.set('flash_deals', response_data, 60)  # 1 min (time-sensitive)
        except Exception:
            pass
        return Response(response_data, status=status.HTTP_200_OK)


class FeaturedProductsView(APIView):
    """Get featured products"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        now = timezone.now()

        # Get active featured promotions
        promotions = ProductPromotion.objects.filter(
            slot__slot_type='featured',
            is_active=True,
            starts_at__lte=now,
            ends_at__gt=now,
            product__status='active'
        ).select_related('product', 'product__vendor').order_by('-created_at')[:20]

        products = [promo.product for promo in promotions]
        serializer = ProductSerializer(products, many=True, context={'request': request})

        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


# ============== VENDOR VIEWS ==============

class VendorPromotionsView(APIView):
    """List vendor's promotions"""
    permission_classes = [IsVendor]

    def get(self, request):
        vendor = request.user.vendor_profile
        promotions = ProductPromotion.objects.filter(
            vendor=vendor
        ).select_related('product', 'slot').order_by('-created_at')

        serializer = ProductPromotionSerializer(promotions, many=True)
        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


class PurchasePromotionView(APIView):
    """Purchase a promotion for a product"""
    permission_classes = [IsVendor]

    def post(self, request):
        product_id = request.data.get('product_id')
        slot_id = request.data.get('slot_id')

        if not product_id or not slot_id:
            return Response({
                'success': False,
                'message': 'Product ID and Slot ID are required'
            }, status=status.HTTP_400_BAD_REQUEST)

        vendor = request.user.vendor_profile

        # Verify product ownership
        try:
            product = Product.objects.get(id=product_id, vendor=vendor, status='active')
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found or not owned by you'
            }, status=status.HTTP_404_NOT_FOUND)

        # Get promotion slot
        try:
            slot = PromotionSlot.objects.get(id=slot_id, is_active=True)
        except PromotionSlot.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Promotion slot not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Check availability
        if not slot.is_available:
            return Response({
                'success': False,
                'message': 'This promotion slot is currently full'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Check if product already has this promotion type active
        existing = ProductPromotion.objects.filter(
            product=product,
            slot__slot_type=slot.slot_type,
            is_active=True,
            ends_at__gt=timezone.now()
        ).exists()

        if existing:
            return Response({
                'success': False,
                'message': f'This product already has an active {slot.get_slot_type_display()} promotion'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Create promotion (payment would normally be processed here)
        now = timezone.now()
        promotion = ProductPromotion.objects.create(
            product=product,
            slot=slot,
            vendor=vendor,
            starts_at=now,
            ends_at=now + timedelta(hours=slot.duration_hours),
            is_active=True
        )

        return Response({
            'success': True,
            'message': 'Promotion activated successfully',
            'data': ProductPromotionSerializer(promotion).data
        }, status=status.HTTP_201_CREATED)


# ============== ADMIN VIEWS ==============

class AdminPromotionSlotsView(APIView):
    """Admin management of promotion slots"""
    permission_classes = [IsAdmin]

    def get(self, request):
        slots = PromotionSlot.objects.all()
        serializer = PromotionSlotSerializer(slots, many=True)
        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)

    def post(self, request):
        serializer = PromotionSlotSerializer(data=request.data)
        if serializer.is_valid():
            slot = serializer.save(created_by=request.user)
            return Response({
                'success': True,
                'message': 'Promotion slot created',
                'data': PromotionSlotSerializer(slot).data
            }, status=status.HTTP_201_CREATED)
        return Response({
            'success': False,
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)


class AdminPromotionSlotDetailView(APIView):
    """Admin detail view for promotion slot"""
    permission_classes = [IsAdmin]

    def patch(self, request, slot_id):
        try:
            slot = PromotionSlot.objects.get(id=slot_id)
        except PromotionSlot.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Slot not found'
            }, status=status.HTTP_404_NOT_FOUND)

        serializer = PromotionSlotSerializer(slot, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response({
                'success': True,
                'message': 'Slot updated',
                'data': serializer.data
            }, status=status.HTTP_200_OK)
        return Response({
            'success': False,
            'errors': serializer.errors
        }, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, slot_id):
        try:
            slot = PromotionSlot.objects.get(id=slot_id)
        except PromotionSlot.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Slot not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Soft delete - deactivate instead of deleting
        slot.is_active = False
        slot.save()

        return Response({
            'success': True,
            'message': 'Slot deactivated'
        }, status=status.HTTP_200_OK)


# ============== SPONSORED ADS VIEWS ==============

def get_sponsored_ad_price():
    """Get sponsored ad price per day from settings"""
    price_str = SystemSettings.get_value('sponsored_ad_price_per_day', '10000')
    return int(float(price_str))


class ActiveSponsoredAdsView(APIView):
    """Get active sponsored ads for public pages"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        from django.db.models import Q

        now = timezone.now()
        limit = int(request.query_params.get('limit', 10))
        item_type = request.query_params.get('item_type', '')

        base_filter = Q(is_active=True, starts_at__lte=now, ends_at__gt=now)

        if item_type:
            base_filter &= Q(item_type=item_type)

        # Filter to only include ads where the related item is active
        active_filter = (
            Q(item_type='product', product__status='active') |
            Q(item_type='service', service__status='active') |
            Q(item_type='event', event__status='active') |
            Q(item_type='menu', menu__status='active') |
            Q(item_type='video', video__is_active=True)
        )

        ads = SponsoredAd.objects.filter(
            base_filter & active_filter
        ).select_related(
            'product', 'service', 'event', 'menu', 'video', 'vendor'
        ).order_by('?')[:limit]

        serializer = SponsoredAdSerializer(ads, many=True, context={'request': request})

        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


class SponsoredAdPriceView(APIView):
    """Get sponsored ad price per day"""
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        price_kobo = get_sponsored_ad_price()
        price_kes = price_kobo / 100

        return Response({
            'success': True,
            'data': {
                'price_per_day': price_kes,
                'currency': 'KES',
            }
        }, status=status.HTTP_200_OK)


class SponsoredAdImpressionView(APIView):
    """Record an impression for a sponsored ad"""
    permission_classes = [permissions.AllowAny]

    def post(self, request, ad_id):
        try:
            ad = SponsoredAd.objects.get(id=ad_id)
        except SponsoredAd.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Ad not found'
            }, status=status.HTTP_404_NOT_FOUND)

        SponsoredAd.objects.filter(id=ad_id).update(
            impressions=db_models.F('impressions') + 1
        )

        return Response({
            'success': True,
        }, status=status.HTTP_200_OK)


class SponsoredAdClickView(APIView):
    """Record a click for a sponsored ad"""
    permission_classes = [permissions.AllowAny]

    def post(self, request, ad_id):
        try:
            ad = SponsoredAd.objects.get(id=ad_id)
        except SponsoredAd.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Ad not found'
            }, status=status.HTTP_404_NOT_FOUND)

        SponsoredAd.objects.filter(id=ad_id).update(
            clicks=db_models.F('clicks') + 1
        )

        return Response({
            'success': True,
        }, status=status.HTTP_200_OK)


class VendorSponsoredAdsView(APIView):
    """List vendor's sponsored ads with stats"""
    permission_classes = [IsVendor]

    def get(self, request):
        vendor = request.user.vendor_profile
        ads = SponsoredAd.objects.filter(
            vendor=vendor
        ).select_related('product', 'service', 'event', 'menu', 'video').order_by('-created_at')

        serializer = SponsoredAdSerializer(ads, many=True, context={'request': request})
        return Response({
            'success': True,
            'data': serializer.data
        }, status=status.HTTP_200_OK)


class PurchaseSponsoredAdView(APIView):
    """Initialize payment for a sponsored ad"""
    permission_classes = [IsVendor]

    def _get_item(self, item_type, item_id, vendor):
        """Validate and return the item to be sponsored"""
        from services.models import Service
        from events.models import Event
        from menus.models import Menu
        from videos.models import VideoListing

        if item_type == 'product':
            try:
                return Product.objects.get(id=item_id, vendor=vendor, status='active')
            except Product.DoesNotExist:
                return None
        elif item_type == 'service':
            try:
                return Service.objects.get(id=item_id, vendor=vendor, status='active')
            except Service.DoesNotExist:
                return None
        elif item_type == 'event':
            try:
                return Event.objects.get(id=item_id, vendor=vendor, status='active')
            except Event.DoesNotExist:
                return None
        elif item_type == 'menu':
            try:
                return Menu.objects.get(id=item_id, vendor=vendor, status='active')
            except Menu.DoesNotExist:
                return None
        elif item_type == 'video':
            try:
                return VideoListing.objects.get(id=item_id, vendor=vendor.user, is_active=True)
            except VideoListing.DoesNotExist:
                return None
        return None

    def post(self, request):
        # Support both new (item_type/item_id) and legacy (product_id) params
        item_type = request.data.get('item_type', 'product')
        item_id = request.data.get('item_id') or request.data.get('product_id')
        days = request.data.get('days')

        if item_type not in ('product', 'service', 'event', 'menu', 'video'):
            return Response({
                'success': False,
                'message': 'item_type must be product, service, event, menu, or video'
            }, status=status.HTTP_400_BAD_REQUEST)

        if not item_id or not days:
            return Response({
                'success': False,
                'message': 'item_id and days are required'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            days = int(days)
            if days < 1:
                raise ValueError()
        except (ValueError, TypeError):
            return Response({
                'success': False,
                'message': 'days must be a positive integer'
            }, status=status.HTTP_400_BAD_REQUEST)

        vendor = request.user.vendor_profile

        # Validate item exists and belongs to vendor
        item = self._get_item(item_type, item_id, vendor)
        if not item:
            return Response({
                'success': False,
                'message': f'{item_type.capitalize()} not found or not owned by you'
            }, status=status.HTTP_404_NOT_FOUND)

        # Check max slots
        max_slots_str = SystemSettings.get_value('max_sponsored_slots_per_day', '50')
        max_slots = int(float(max_slots_str))
        now = timezone.now()
        active_count = SponsoredAd.objects.filter(
            is_active=True, starts_at__lte=now, ends_at__gt=now
        ).count()
        if active_count >= max_slots:
            return Response({
                'success': False,
                'message': 'All sponsored ad slots are currently full. Please try again later.'
            }, status=status.HTTP_400_BAD_REQUEST)

        price_kobo_per_day = get_sponsored_ad_price()
        total_kobo = price_kobo_per_day * days
        total_kes = total_kobo / 100

        reference = f"AD-{request.user.id}-{uuid_lib.uuid4().hex[:8].upper()}"
        callback_url = request.data.get(
            'callback_url',
            f"{django_settings.FRONTEND_URL}/vendor/ads?payment=callback"
        )

        ad_metadata = {
            'user_id': request.user.id,
            'payment_type': 'sponsored_ad',
            'item_type': item_type,
            'item_id': item.id,
            'product_id': item.id if item_type == 'product' else None,
            'days': days,
        }

        payment = Payment.objects.create(
            user=request.user,
            payment_type='sponsored_ad',
            amount=total_kes,
            currency='KES',
            reference=reference,
            status='pending',
            # Store metadata locally as fallback in case Paystack doesn't return it
            paystack_response={'_initial_metadata': ad_metadata},
        )

        result = paystack.initialize_transaction(
            email=request.user.email or f"{request.user.phone_number}@nyanzamarket.com",
            amount=total_kobo,
            reference=reference,
            callback_url=callback_url,
            metadata=ad_metadata,
        )

        if result.get('status'):
            payment.paystack_reference = result['data'].get('reference')
            payment.save()

            return Response({
                'success': True,
                'message': 'Payment initialized',
                'data': {
                    'authorization_url': result['data']['authorization_url'],
                    'access_code': result['data']['access_code'],
                    'reference': reference,
                    'amount': total_kes,
                    'public_key': django_settings.PAYSTACK_PUBLIC_KEY,
                }
            }, status=status.HTTP_200_OK)
        else:
            payment.status = 'failed'
            payment.save()
            return Response({
                'success': False,
                'message': result.get('message', 'Failed to initialize payment')
            }, status=status.HTTP_400_BAD_REQUEST)


# ============== ADMIN SPONSORED ADS VIEWS ==============

class AdminSponsoredAdsListView(APIView):
    """Admin view to list and manage all sponsored ads"""
    permission_classes = [IsAdmin]

    def get(self, request):
        from django.db.models import Q, Sum, Count, F, ExpressionWrapper, FloatField

        status_filter = request.query_params.get('status', '')
        item_type_filter = request.query_params.get('item_type', '')
        search = request.query_params.get('search', '')
        page = int(request.query_params.get('page', 1))
        page_size = int(request.query_params.get('page_size', 20))

        queryset = SponsoredAd.objects.select_related(
            'product', 'service', 'event', 'menu', 'video', 'vendor', 'vendor__user'
        ).order_by('-created_at')

        now = timezone.now()

        if status_filter == 'active':
            queryset = queryset.filter(is_active=True, starts_at__lte=now, ends_at__gt=now)
        elif status_filter == 'expired':
            queryset = queryset.filter(ends_at__lte=now)
        elif status_filter == 'inactive':
            queryset = queryset.filter(is_active=False)

        if item_type_filter:
            queryset = queryset.filter(item_type=item_type_filter)

        if search:
            queryset = queryset.filter(
                Q(product__name__icontains=search) |
                Q(service__name__icontains=search) |
                Q(event__title__icontains=search) |
                Q(menu__name__icontains=search) |
                Q(video__title__icontains=search) |
                Q(vendor__shop_name__icontains=search)
            )

        total = queryset.count()
        start = (page - 1) * page_size
        end = start + page_size
        ads_list = queryset[start:end]

        serializer = SponsoredAdSerializer(ads_list, many=True, context={'request': request})

        # Add vendor_name to each ad
        data = serializer.data
        ads_by_id = {ad.id: ad for ad in ads_list}
        for item in data:
            ad = ads_by_id.get(item['id'])
            if ad:
                item['vendor_name'] = ad.vendor.shop_name
                item['vendor_id'] = ad.vendor.id

        return Response({
            'success': True,
            'data': {
                'results': data,
                'total': total,
                'page': page,
                'page_size': page_size,
                'total_pages': (total + page_size - 1) // page_size,
            }
        }, status=status.HTTP_200_OK)


class AdminSponsoredAdStatsView(APIView):
    """Admin view to get sponsored ad stats"""
    permission_classes = [IsAdmin]

    def get(self, request):
        from django.db.models import Sum, Count, Avg

        now = timezone.now()

        total_ads = SponsoredAd.objects.count()
        active_ads = SponsoredAd.objects.filter(
            is_active=True, starts_at__lte=now, ends_at__gt=now
        ).count()
        total_revenue = SponsoredAd.objects.aggregate(
            total=Sum('total_cost')
        )['total'] or 0
        total_impressions = SponsoredAd.objects.aggregate(
            total=Sum('impressions')
        )['total'] or 0
        total_clicks = SponsoredAd.objects.aggregate(
            total=Sum('clicks')
        )['total'] or 0

        avg_ctr = 0
        if total_impressions > 0:
            avg_ctr = round((total_clicks / total_impressions) * 100, 2)

        # Breakdown by type
        type_breakdown = SponsoredAd.objects.values('item_type').annotate(
            count=Count('id'),
            revenue=Sum('total_cost'),
        )

        return Response({
            'success': True,
            'data': {
                'total_ads': total_ads,
                'active_ads': active_ads,
                'total_revenue': float(total_revenue),
                'total_impressions': total_impressions,
                'total_clicks': total_clicks,
                'avg_ctr': avg_ctr,
                'type_breakdown': list(type_breakdown),
            }
        }, status=status.HTTP_200_OK)


class AdminDeactivateSponsoredAdView(APIView):
    """Admin view to deactivate a sponsored ad"""
    permission_classes = [IsAdmin]

    def post(self, request, ad_id):
        try:
            ad = SponsoredAd.objects.get(id=ad_id)
        except SponsoredAd.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Ad not found'
            }, status=status.HTTP_404_NOT_FOUND)

        ad.is_active = False
        ad.save()

        return Response({
            'success': True,
            'message': f'Ad for "{ad.item_name}" has been deactivated'
        }, status=status.HTTP_200_OK)


class AdminSponsoredAdMaxSlotsView(APIView):
    """Admin view to get/set max sponsored ad slots per day"""
    permission_classes = [IsAdmin]

    def get(self, request):
        max_slots_str = SystemSettings.get_value('max_sponsored_slots_per_day', '50')
        max_slots = int(float(max_slots_str))

        now = timezone.now()
        active_count = SponsoredAd.objects.filter(
            is_active=True, starts_at__lte=now, ends_at__gt=now
        ).count()

        return Response({
            'success': True,
            'data': {
                'max_slots': max_slots,
                'active_count': active_count,
                'available': max_slots - active_count,
            }
        }, status=status.HTTP_200_OK)

    def post(self, request):
        max_slots = request.data.get('max_slots')

        if max_slots is None:
            return Response({
                'success': False,
                'message': 'max_slots is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            max_slots = int(max_slots)
            if max_slots < 1:
                raise ValueError()
        except (ValueError, TypeError):
            return Response({
                'success': False,
                'message': 'max_slots must be a positive integer'
            }, status=status.HTTP_400_BAD_REQUEST)

        SystemSettings.set_value(
            'max_sponsored_slots_per_day',
            str(max_slots),
            'Maximum sponsored ad slots',
            request.user
        )

        return Response({
            'success': True,
            'message': 'Max slots updated successfully',
            'data': {'max_slots': max_slots}
        }, status=status.HTTP_200_OK)


class AdminRetryProcessAdView(APIView):
    """Admin endpoint to manually create a sponsored ad from a successful payment that failed to create one"""
    permission_classes = [IsAdmin]

    def post(self, request, payment_id):
        import logging
        from datetime import timedelta
        from services.models import Service
        from events.models import Event
        from menus.models import Menu

        logger = logging.getLogger(__name__)

        try:
            payment = Payment.objects.get(id=payment_id, payment_type='sponsored_ad')
        except Payment.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Sponsored ad payment not found'
            }, status=status.HTTP_404_NOT_FOUND)

        if payment.status != 'success':
            return Response({
                'success': False,
                'message': f'Payment status is "{payment.status}", not "success". Cannot create ad.'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Check if ad already exists
        if SponsoredAd.objects.filter(payment=payment).exists():
            return Response({
                'success': False,
                'message': 'A sponsored ad already exists for this payment'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Get metadata from paystack_response or initial metadata
        metadata = {}
        if payment.paystack_response:
            metadata = payment.paystack_response.get('metadata', {})
            if not metadata and '_initial_metadata' in payment.paystack_response:
                metadata = payment.paystack_response['_initial_metadata']

        # Allow admin to override via request body
        item_type = request.data.get('item_type') or metadata.get('item_type', 'product')
        item_id = request.data.get('item_id') or metadata.get('item_id') or metadata.get('product_id')
        days = request.data.get('days') or metadata.get('days', 1)

        if not item_id:
            return Response({
                'success': False,
                'message': 'No item_id found in payment metadata. Provide item_type, item_id, and days in request body.',
                'metadata': metadata,
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            item_id = int(item_id)
            days = int(days)
        except (ValueError, TypeError):
            return Response({
                'success': False,
                'message': 'item_id and days must be integers'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Find the item
        try:
            if item_type == 'service':
                item = Service.objects.get(id=item_id)
            elif item_type == 'event':
                item = Event.objects.get(id=item_id)
            elif item_type == 'menu':
                item = Menu.objects.get(id=item_id)
            elif item_type == 'video':
                from videos.models import VideoListing
                item = VideoListing.objects.get(id=item_id)
            else:
                item = Product.objects.get(id=item_id)
        except Exception:
            return Response({
                'success': False,
                'message': f'{item_type.capitalize()} with id={item_id} not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # VideoListing.vendor -> User; others -> VendorProfile
        vendor = item.vendor.vendor_profile if item_type == 'video' else item.vendor

        now = timezone.now()
        ad_kwargs = {
            'vendor': vendor,
            'payment': payment,
            'item_type': item_type,
            'days': days,
            'total_cost': payment.amount,
            'starts_at': now,
            'ends_at': now + timedelta(days=days),
            'is_active': True,
        }
        if item_type == 'service':
            ad_kwargs['service'] = item
        elif item_type == 'event':
            ad_kwargs['event'] = item
        elif item_type == 'menu':
            ad_kwargs['menu'] = item
        elif item_type == 'video':
            ad_kwargs['video'] = item
        else:
            ad_kwargs['product'] = item

        ad = SponsoredAd.objects.create(**ad_kwargs)
        logger.info(f"[SponsoredAd Admin] Manually created ad #{ad.id} for {item_type} '{item}' from payment #{payment.id}")

        return Response({
            'success': True,
            'message': f'Sponsored ad created for "{ad.item_name}" ({days} days)',
            'data': {
                'ad_id': ad.id,
                'item_name': ad.item_name,
                'item_type': item_type,
                'days': days,
                'starts_at': ad.starts_at.isoformat(),
                'ends_at': ad.ends_at.isoformat(),
            }
        }, status=status.HTTP_201_CREATED)


class AdminFailedAdPaymentsView(APIView):
    """List successful sponsored_ad payments that have no corresponding SponsoredAd record"""
    permission_classes = [IsAdmin]

    def get(self, request):
        failed_payments = Payment.objects.filter(
            payment_type='sponsored_ad',
            status='success',
        ).exclude(
            id__in=SponsoredAd.objects.values_list('payment_id', flat=True)
        ).select_related('user').order_by('-created_at')

        results = []
        for p in failed_payments:
            metadata = {}
            if p.paystack_response:
                metadata = p.paystack_response.get('metadata', {})
                if not metadata and '_initial_metadata' in p.paystack_response:
                    metadata = p.paystack_response['_initial_metadata']

            results.append({
                'payment_id': p.id,
                'reference': p.reference,
                'amount': float(p.amount),
                'user_name': p.user.full_name if hasattr(p.user, 'full_name') else str(p.user),
                'created_at': p.created_at.isoformat(),
                'item_type': metadata.get('item_type', 'unknown'),
                'item_id': metadata.get('item_id') or metadata.get('product_id'),
                'days': metadata.get('days'),
                'has_metadata': bool(metadata),
            })

        return Response({
            'success': True,
            'data': results,
            'total': len(results),
        }, status=status.HTTP_200_OK)
