import uuid
import json
import logging
from datetime import timedelta
from django.conf import settings
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny

from .models import Payment, VendorSubscription, SystemSettings, VerificationRequest
from .paystack import paystack
from accounts.models import VendorProfile
from accounts.email_service import send_upgrade_email

logger = logging.getLogger(__name__)


def get_upgrade_price(plan_type='monthly'):
    """Get upgrade price from settings or default.
    Yearly = monthly * 12 * 0.80 (20% off annual total)
    """
    price_str = SystemSettings.get_value('vendor_upgrade_price', str(settings.VENDOR_UPGRADE_PRICE))
    monthly_price = int(float(price_str))
    if plan_type == 'yearly':
        return int(monthly_price * 12 * 0.80)
    return monthly_price


def get_verification_price():
    """Get verification price from settings or default"""
    price_str = SystemSettings.get_value('vendor_verification_price', str(settings.VENDOR_VERIFICATION_PRICE))
    return int(float(price_str))


class InitializeUpgradePaymentView(APIView):
    """Initialize payment for vendor upgrade"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user

        # Check if user is a vendor
        if user.user_type != 'vendor':
            return Response({
                'success': False,
                'message': 'Only vendors can upgrade'
            }, status=status.HTTP_403_FORBIDDEN)

        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor profile not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Get plan type from request
        plan_type = request.data.get('plan_type', 'monthly')
        if plan_type not in ('monthly', 'yearly'):
            plan_type = 'monthly'

        # Check active subscription rules
        is_plan_change = False
        if vendor_profile.is_upgraded:
            try:
                sub = vendor_profile.subscription
                if sub.is_active and not sub.is_expired:
                    # Block same plan or downgrade (yearly can't buy monthly)
                    if sub.plan_type == plan_type:
                        return Response({
                            'success': False,
                            'message': f'You already have an active {plan_type} subscription'
                        }, status=status.HTTP_400_BAD_REQUEST)
                    if sub.plan_type == 'yearly' and plan_type == 'monthly':
                        return Response({
                            'success': False,
                            'message': 'You already have an active yearly subscription'
                        }, status=status.HTTP_400_BAD_REQUEST)
                    # monthly → yearly upgrade allowed
                    is_plan_change = True
            except VendorSubscription.DoesNotExist:
                pass

        # Generate unique reference
        reference = f"UPGRADE-{plan_type}-{user.id}-{uuid.uuid4().hex[:8].upper()}"

        # Get callback URL from request or use default
        callback_url = request.data.get('callback_url', f"{settings.FRONTEND_URL}/upgrade/callback")

        # Get price — 70% of yearly if upgrading from monthly to yearly
        amount_kobo = get_upgrade_price(plan_type)
        if is_plan_change and plan_type == 'yearly':
            amount_kobo = int(amount_kobo * 0.70)
        amount_kes = amount_kobo / 100

        # Create payment record
        payment = Payment.objects.create(
            user=user,
            payment_type='vendor_upgrade',
            amount=amount_kes,
            currency='KES',
            reference=reference,
            status='pending'
        )

        # Initialize Paystack transaction
        result = paystack.initialize_transaction(
            email=user.email or f"{user.phone_number}@nyanzamarket.com",
            amount=amount_kobo,
            reference=reference,
            callback_url=callback_url,
            metadata={
                'user_id': user.id,
                'payment_type': 'vendor_upgrade',
                'plan_type': plan_type,
                'is_plan_change': is_plan_change,
                'shop_name': vendor_profile.shop_name
            }
        )

        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': amount_kes,
                    'public_key': settings.PAYSTACK_PUBLIC_KEY,
                    'is_plan_change': is_plan_change,
                }
            }, 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)


class VerifyPaymentView(APIView):
    """Verify payment after callback"""
    permission_classes = [IsAuthenticated]

    def get(self, request, reference):
        user = request.user

        try:
            payment = Payment.objects.get(reference=reference, user=user)
        except Payment.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Payment not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # If already verified
        if payment.status == 'success':
            return Response({
                'success': True,
                'message': 'Payment already verified',
                'data': {'status': 'success'}
            }, status=status.HTTP_200_OK)

        # Verify with Paystack
        result = paystack.verify_transaction(reference)

        if result.get('status') and result.get('data', {}).get('status') == 'success':
            payment.status = 'success'
            paystack_data = result.get('data', {})
            # Preserve our initial metadata as fallback
            initial_meta = (payment.paystack_response or {}).get('_initial_metadata')
            payment.paystack_response = paystack_data
            if initial_meta and '_initial_metadata' not in paystack_data:
                payment.paystack_response['_initial_metadata'] = initial_meta
            payment.paid_at = timezone.now()
            payment.save()

            # Process based on payment type
            if payment.payment_type == 'vendor_upgrade':
                metadata = result.get('data', {}).get('metadata', {})
                plan_type = metadata.get('plan_type', 'monthly')
                self._process_vendor_upgrade(user, payment, plan_type)
            elif payment.payment_type == 'vendor_verification':
                self._process_vendor_verification(user, payment, result.get('data', {}))
            elif payment.payment_type == 'sponsored_ad':
                self._process_sponsored_ad(payment)

            return Response({
                'success': True,
                'message': 'Payment successful',
                'data': {
                    'status': 'success',
                    'amount': float(payment.amount),
                    'paid_at': payment.paid_at
                }
            }, status=status.HTTP_200_OK)
        else:
            payment.status = 'failed'
            payment.paystack_response = result.get('data')
            payment.save()

            return Response({
                'success': False,
                'message': 'Payment verification failed',
                'data': {'status': 'failed'}
            }, status=status.HTTP_400_BAD_REQUEST)

    def _restore_hidden_items(self, vendor_profile):
        """Re-activate items that were hidden when subscription expired"""
        vendor_profile.products.filter(status='paused').update(status='active')
        vendor_profile.services.filter(status='paused').update(status='active')
        vendor_profile.menus.filter(status='inactive').update(status='active')
        vendor_profile.events.filter(status='draft').update(status='active')

    def _process_vendor_upgrade(self, user, payment, plan_type='monthly'):
        """Process vendor upgrade after successful payment"""
        try:
            vendor_profile = user.vendor_profile
            vendor_profile.is_upgraded = True
            vendor_profile.upgraded_at = timezone.now()
            vendor_profile.save()

            # Restore items hidden during subscription expiry
            self._restore_hidden_items(vendor_profile)

            now = timezone.now()
            if plan_type == 'yearly':
                expires_at = now + timedelta(days=365)
            else:
                expires_at = now + timedelta(days=30)

            # Create or update subscription record
            VendorSubscription.objects.update_or_create(
                vendor=vendor_profile,
                defaults={
                    'payment': payment,
                    'is_active': True,
                    'plan_type': plan_type,
                    'expires_at': expires_at,
                }
            )

            # Send upgrade confirmation email
            send_upgrade_email(user, vendor_profile, float(payment.amount), plan_type, expires_at)

            # Send upgrade notification
            try:
                from notifications.models import Notification
                Notification.notify_upgrade(user)
            except Exception:
                pass
        except VendorProfile.DoesNotExist:
            pass

    def _process_vendor_verification(self, user, payment, paystack_data):
        """Create verification request after successful payment"""
        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return

        # Avoid duplicates
        if VerificationRequest.objects.filter(payment=payment).exists():
            return

        # Get business info from paystack metadata
        metadata = paystack_data.get('metadata', {}) if paystack_data else {}
        business_name = metadata.get('business_name', vendor_profile.shop_name)
        location = metadata.get('location', '')
        business_phone = metadata.get('business_phone', '')
        social_link = metadata.get('social_link', '')

        VerificationRequest.objects.create(
            vendor=vendor_profile,
            payment=payment,
            business_name=business_name,
            location=location,
            business_phone=business_phone,
            social_link=social_link,
            status='pending'
        )

        # Send notification and email
        try:
            from notifications.models import Notification
            Notification.notify_verification_submitted(user)
        except Exception:
            pass
        try:
            from accounts.email_service import send_verification_submitted_email
            send_verification_submitted_email(user, vendor_profile)
        except Exception:
            pass

    def _process_sponsored_ad(self, payment):
        """Process sponsored ad after successful payment"""
        from promotions.models import SponsoredAd
        from products.models import Product
        from services.models import Service
        from events.models import Event
        from menus.models import Menu
        from videos.models import VideoListing

        # Try paystack_response metadata first, fall back to stored initial metadata
        metadata = {}
        if payment.paystack_response:
            metadata = payment.paystack_response.get('metadata', {})
            # Fallback: if Paystack didn't return metadata, check our stored initial metadata
            if not metadata and '_initial_metadata' in payment.paystack_response:
                metadata = payment.paystack_response['_initial_metadata']

        item_type = metadata.get('item_type', 'product')
        item_id = metadata.get('item_id') or metadata.get('product_id')
        days = int(metadata.get('days', 1))

        logger.info(f"[SponsoredAd] Processing payment #{payment.id} ref={payment.reference} | "
                     f"item_type={item_type}, item_id={item_id}, days={days}, metadata={metadata}")

        if not item_id:
            logger.error(f"[SponsoredAd] Payment #{payment.id}: No item_id found in metadata. "
                         f"paystack_response keys: {list(payment.paystack_response.keys()) if payment.paystack_response else 'None'}")
            return

        # Avoid duplicates
        if SponsoredAd.objects.filter(payment=payment).exists():
            logger.info(f"[SponsoredAd] Payment #{payment.id}: Ad already exists, skipping.")
            return

        try:
            item_id = int(item_id)
            now = timezone.now()
            ad_kwargs = {
                'vendor': None,
                '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':
                item = Service.objects.get(id=item_id)
                ad_kwargs['service'] = item
            elif item_type == 'event':
                item = Event.objects.get(id=item_id)
                ad_kwargs['event'] = item
            elif item_type == 'menu':
                item = Menu.objects.get(id=item_id)
                ad_kwargs['menu'] = item
            elif item_type == 'video':
                item = VideoListing.objects.get(id=item_id)
                ad_kwargs['video'] = item
            else:
                item = Product.objects.get(id=item_id)
                ad_kwargs['product'] = item

            # VideoListing.vendor -> User; others -> VendorProfile
            ad_kwargs['vendor'] = item.vendor.vendor_profile if item_type == 'video' else item.vendor
            ad = SponsoredAd.objects.create(**ad_kwargs)
            logger.info(f"[SponsoredAd] Created ad #{ad.id} for {item_type} '{item}' via payment #{payment.id}")

            # Send confirmation email
            try:
                from accounts.email_service import send_sponsored_ad_email
                user = payment.user
                item_name = item.title if item_type in ('event', 'video') else item.name
                vendor_profile = item.vendor.vendor_profile if item_type == 'video' else item.vendor
                send_sponsored_ad_email(
                    user, vendor_profile, item_name, item_type,
                    days, float(payment.amount),
                    ad_kwargs['starts_at'], ad_kwargs['ends_at']
                )
            except Exception as e:
                logger.warning(f"[SponsoredAd] Failed to send email for payment #{payment.id}: {e}")

        except Exception as e:
            logger.error(f"[SponsoredAd] Failed to create ad for payment #{payment.id}: {e}", exc_info=True)


class PaystackWebhookView(APIView):
    """Handle Paystack webhooks"""
    permission_classes = [AllowAny]

    @csrf_exempt
    def post(self, request):
        # Verify signature
        signature = request.headers.get('X-Paystack-Signature', '')
        if not paystack.verify_webhook_signature(request.body, signature):
            return HttpResponse(status=400)

        payload = json.loads(request.body)
        event = payload.get('event')
        data = payload.get('data', {})

        if event == 'charge.success':
            reference = data.get('reference')
            self._handle_successful_payment(reference, data)

        return HttpResponse(status=200)

    def _handle_successful_payment(self, reference, data):
        """Handle successful payment webhook"""
        try:
            payment = Payment.objects.get(reference=reference)

            if payment.status != 'success':
                payment.status = 'success'
                payment.paystack_response = data
                payment.paid_at = timezone.now()
                payment.save()

                # Process based on payment type
                if payment.payment_type == 'vendor_upgrade':
                    user = payment.user
                    metadata = data.get('metadata', {})
                    plan_type = metadata.get('plan_type', 'monthly')
                    try:
                        vendor_profile = user.vendor_profile
                        vendor_profile.is_upgraded = True
                        vendor_profile.upgraded_at = timezone.now()
                        vendor_profile.save()

                        # Restore items hidden during subscription expiry
                        self._restore_hidden_items(vendor_profile)

                        now = timezone.now()
                        if plan_type == 'yearly':
                            expires_at = now + timedelta(days=365)
                        else:
                            expires_at = now + timedelta(days=30)

                        # Create or update subscription
                        sub, created = VendorSubscription.objects.update_or_create(
                            vendor=vendor_profile,
                            defaults={
                                'payment': payment,
                                'is_active': True,
                                'plan_type': plan_type,
                                'expires_at': expires_at,
                            }
                        )

                        # Send email and notification only if subscription was just created
                        if created:
                            send_upgrade_email(user, vendor_profile, float(payment.amount), plan_type, expires_at)
                            try:
                                from notifications.models import Notification
                                Notification.notify_upgrade(user)
                            except Exception:
                                pass
                    except VendorProfile.DoesNotExist:
                        pass
                elif payment.payment_type == 'vendor_verification':
                    self._process_webhook_verification(payment, data)
                elif payment.payment_type == 'sponsored_ad':
                    self._process_webhook_sponsored_ad(payment, data)
        except Payment.DoesNotExist:
            pass

    def _process_webhook_verification(self, payment, data):
        """Process verification request from webhook"""
        user = payment.user
        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return

        # Avoid duplicates
        if VerificationRequest.objects.filter(payment=payment).exists():
            return

        metadata = data.get('metadata', {})
        business_name = metadata.get('business_name', vendor_profile.shop_name)
        location = metadata.get('location', '')
        business_phone = metadata.get('business_phone', '')
        social_link = metadata.get('social_link', '')

        VerificationRequest.objects.create(
            vendor=vendor_profile,
            payment=payment,
            business_name=business_name,
            location=location,
            business_phone=business_phone,
            social_link=social_link,
            status='pending'
        )

        # Send notification and email
        try:
            from notifications.models import Notification
            Notification.notify_verification_submitted(user)
        except Exception:
            pass
        try:
            from accounts.email_service import send_verification_submitted_email
            send_verification_submitted_email(user, vendor_profile)
        except Exception:
            pass

    def _process_webhook_sponsored_ad(self, payment, data):
        """Process sponsored ad from webhook"""
        from promotions.models import SponsoredAd
        from products.models import Product
        from services.models import Service
        from events.models import Event
        from menus.models import Menu
        from videos.models import VideoListing

        metadata = data.get('metadata', {})
        item_type = metadata.get('item_type', 'product')
        item_id = metadata.get('item_id') or metadata.get('product_id')
        days = int(metadata.get('days', 1))

        logger.info(f"[SponsoredAd Webhook] Processing payment #{payment.id} ref={payment.reference} | "
                     f"item_type={item_type}, item_id={item_id}, days={days}, metadata={metadata}")

        if not item_id:
            logger.error(f"[SponsoredAd Webhook] Payment #{payment.id}: No item_id in webhook metadata. "
                         f"data keys: {list(data.keys())}")
            return

        # Avoid duplicates
        if SponsoredAd.objects.filter(payment=payment).exists():
            logger.info(f"[SponsoredAd Webhook] Payment #{payment.id}: Ad already exists, skipping.")
            return

        try:
            item_id = int(item_id)
            now = timezone.now()
            ad_kwargs = {
                'vendor': None,
                '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':
                item = Service.objects.get(id=item_id)
                ad_kwargs['service'] = item
            elif item_type == 'event':
                item = Event.objects.get(id=item_id)
                ad_kwargs['event'] = item
            elif item_type == 'menu':
                item = Menu.objects.get(id=item_id)
                ad_kwargs['menu'] = item
            elif item_type == 'video':
                item = VideoListing.objects.get(id=item_id)
                ad_kwargs['video'] = item
            else:
                item = Product.objects.get(id=item_id)
                ad_kwargs['product'] = item

            # VideoListing.vendor -> User; others -> VendorProfile
            ad_kwargs['vendor'] = item.vendor.vendor_profile if item_type == 'video' else item.vendor
            ad = SponsoredAd.objects.create(**ad_kwargs)
            logger.info(f"[SponsoredAd Webhook] Created ad #{ad.id} for {item_type} '{item}' via payment #{payment.id}")

            # Send confirmation email
            try:
                from accounts.email_service import send_sponsored_ad_email
                user = payment.user
                item_name = item.title if item_type in ('event', 'video') else item.name
                vendor_profile = item.vendor.vendor_profile if item_type == 'video' else item.vendor
                send_sponsored_ad_email(
                    user, vendor_profile, item_name, item_type,
                    days, float(payment.amount),
                    ad_kwargs['starts_at'], ad_kwargs['ends_at']
                )
            except Exception as e:
                logger.warning(f"[SponsoredAd Webhook] Failed to send email for payment #{payment.id}: {e}")

        except Exception as e:
            logger.error(f"[SponsoredAd Webhook] Failed to create ad for payment #{payment.id}: {e}", exc_info=True)


class VerificationPriceView(APIView):
    """Get verification price info (public)"""
    permission_classes = [AllowAny]

    def get(self, request):
        amount_kobo = get_verification_price()
        amount_kes = amount_kobo / 100
        return Response({
            'success': True,
            'data': {
                'amount': amount_kes,
                'price_kes': amount_kes,
                'currency': 'KES',
            }
        }, status=status.HTTP_200_OK)


class VendorVerificationStatusView(APIView):
    """Get vendor's verification request status"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.user_type != 'vendor':
            return Response({
                'success': False,
                'message': 'Only vendors can check verification status'
            }, status=status.HTTP_403_FORBIDDEN)

        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor profile not found'
            }, status=status.HTTP_404_NOT_FOUND)

        if vendor_profile.is_verified_vendor:
            return Response({
                'success': True,
                'data': {'status': 'approved'}
            }, status=status.HTTP_200_OK)

        # Check latest verification request (only those with successful payment)
        latest_request = VerificationRequest.objects.filter(
            vendor=vendor_profile,
            payment__status='success'
        ).order_by('-created_at').first()

        if latest_request:
            return Response({
                'success': True,
                'data': {
                    'status': latest_request.status,
                    'rejection_reason': latest_request.rejection_reason,
                    'created_at': latest_request.created_at,
                }
            }, status=status.HTTP_200_OK)

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


class InitializeVerificationPaymentView(APIView):
    """Initialize payment for vendor verification"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user

        if user.user_type != 'vendor':
            return Response({
                'success': False,
                'message': 'Only vendors can request verification'
            }, status=status.HTTP_403_FORBIDDEN)

        try:
            vendor_profile = user.vendor_profile
            if vendor_profile.is_verified_vendor:
                return Response({
                    'success': False,
                    'message': 'You are already verified'
                }, status=status.HTTP_400_BAD_REQUEST)
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor profile not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Check for pending request (only those with successful payment)
        pending = VerificationRequest.objects.filter(
            vendor=vendor_profile, status='pending', payment__status='success'
        ).exists()
        if pending:
            return Response({
                'success': False,
                'message': 'You already have a pending verification request'
            }, status=status.HTTP_400_BAD_REQUEST)

        business_name = request.data.get('business_name', '').strip()
        location = request.data.get('location', '').strip()
        business_phone = request.data.get('business_phone', '').strip()
        social_link = request.data.get('social_link', '').strip()
        callback_url = request.data.get('callback_url', f"{settings.FRONTEND_URL}/vendor/verify")

        if not all([business_name, location, business_phone, social_link]):
            return Response({
                'success': False,
                'message': 'All fields are required'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Generate reference
        reference = f"VERIFY-{user.id}-{uuid.uuid4().hex[:8].upper()}"

        amount_kobo = get_verification_price()
        amount_kes = amount_kobo / 100

        # Create payment record
        payment = Payment.objects.create(
            user=user,
            payment_type='vendor_verification',
            amount=amount_kes,
            currency='KES',
            reference=reference,
            status='pending'
        )

        # NOTE: VerificationRequest is created AFTER payment succeeds
        # (in VerifyPaymentView or webhook), not here.

        # Initialize Paystack transaction
        result = paystack.initialize_transaction(
            email=user.email or f"{user.phone_number}@wananchimart.com",
            amount=amount_kobo,
            reference=reference,
            callback_url=callback_url,
            metadata={
                'user_id': user.id,
                'payment_type': 'vendor_verification',
                'shop_name': vendor_profile.shop_name,
                'business_name': business_name,
                'location': location,
                'business_phone': business_phone,
                'social_link': social_link,
            }
        )

        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': amount_kes,
                    'public_key': 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)


class UpgradePriceView(APIView):
    """Get upgrade price info"""
    permission_classes = [AllowAny]

    def get(self, request):
        monthly_kobo = get_upgrade_price('monthly')
        yearly_kobo = get_upgrade_price('yearly')
        yearly_upgrade_kobo = int(yearly_kobo * 0.70)
        return Response({
            'success': True,
            'data': {
                'amount': monthly_kobo / 100,
                'monthly': monthly_kobo / 100,
                'yearly': yearly_kobo / 100,
                'yearly_upgrade': yearly_upgrade_kobo / 100,
                'currency': 'KES',
                'features': [
                    'Add up to 100 products',
                    'Up to 5 images per product',
                    'Video uploads',
                    'Discount pricing',
                    'Featured products',
                    'Priority in search results',
                    'Analytics dashboard',
                    'Direct messaging',
                ]
            }
        }, status=status.HTTP_200_OK)


class PaymentHistoryView(APIView):
    """Get user's payment history"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        payments = Payment.objects.filter(user=request.user)
        data = [{
            'id': p.id,
            'type': p.payment_type,
            'amount': float(p.amount),
            'currency': p.currency,
            'status': p.status,
            'reference': p.reference,
            'created_at': p.created_at,
            'paid_at': p.paid_at
        } for p in payments]

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


class SubscriptionStatusView(APIView):
    """Get current vendor subscription status"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.user_type != 'vendor':
            return Response({
                'success': False,
                'message': 'Only vendors can check subscription status'
            }, status=status.HTTP_403_FORBIDDEN)

        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor profile not found'
            }, status=status.HTTP_404_NOT_FOUND)

        try:
            sub = vendor_profile.subscription
            now = timezone.now()

            # Backfill expires_at for legacy subscriptions that don't have it
            if sub.is_active and sub.expires_at is None:
                if sub.plan_type == 'yearly':
                    sub.expires_at = sub.started_at + timedelta(days=365)
                else:
                    sub.expires_at = sub.started_at + timedelta(days=30)
                sub.save(update_fields=['expires_at'])

            days_remaining = 0
            if sub.expires_at:
                delta = sub.expires_at - now
                days_remaining = max(0, delta.days)

            return Response({
                'success': True,
                'data': {
                    'plan_type': sub.plan_type,
                    'is_active': sub.is_active and not sub.is_expired,
                    'started_at': sub.started_at,
                    'expires_at': sub.expires_at,
                    'days_remaining': days_remaining,
                    'is_expired': sub.is_expired,
                    'granted_by_admin': sub.plan_type == 'admin',
                }
            }, status=status.HTTP_200_OK)
        except VendorSubscription.DoesNotExist:
            return Response({
                'success': True,
                'data': {
                    'plan_type': 'free',
                    'is_active': False,
                    'started_at': None,
                    'expires_at': None,
                    'days_remaining': 0,
                    'is_expired': False,
                }
            }, status=status.HTTP_200_OK)


# Admin Views
class AdminSettingsView(APIView):
    """Admin view to manage system settings"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        settings_list = SystemSettings.objects.all()
        data = [{
            'key': s.key,
            'value': s.value,
            'description': s.description,
            'updated_at': s.updated_at
        } for s in settings_list]

        # Include default settings if not in database
        current_keys = [s.key for s in settings_list]
        if 'vendor_upgrade_price' not in current_keys:
            data.append({
                'key': 'vendor_upgrade_price',
                'value': str(settings.VENDOR_UPGRADE_PRICE),
                'description': 'Vendor upgrade price in kobo (smallest unit)',
                'updated_at': None
            })

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

    def post(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        key = request.data.get('key')
        value = request.data.get('value')
        description = request.data.get('description', '')

        if not key or value is None:
            return Response({
                'success': False,
                'message': 'Key and value are required'
            }, status=status.HTTP_400_BAD_REQUEST)

        setting = SystemSettings.set_value(key, value, description, request.user)

        return Response({
            'success': True,
            'message': 'Setting updated successfully',
            'data': {
                'key': setting.key,
                'value': setting.value,
                'description': setting.description,
                'updated_at': setting.updated_at
            }
        }, status=status.HTTP_200_OK)


class AdminUpgradePriceView(APIView):
    """Admin view to get/set upgrade price specifically"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        price_kobo = get_upgrade_price()
        price_kes = price_kobo / 100

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

    def post(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        price_kes = request.data.get('price_kes')

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

        try:
            price_kes = float(price_kes)
            if price_kes <= 0:
                raise ValueError("Price must be positive")
        except (ValueError, TypeError):
            return Response({
                'success': False,
                'message': 'Invalid price value'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Convert to kobo
        price_kobo = int(price_kes * 100)

        SystemSettings.set_value(
            'vendor_upgrade_price',
            price_kobo,
            'Vendor upgrade price in kobo',
            request.user
        )

        return Response({
            'success': True,
            'message': 'Upgrade price updated successfully',
            'data': {
                'price_kobo': price_kobo,
                'price_kes': price_kes,
                'currency': 'KES'
            }
        }, status=status.HTTP_200_OK)


class AdminVerificationPriceView(APIView):
    """Admin view to get/set verification price"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        price_kobo = get_verification_price()
        price_kes = price_kobo / 100

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

    def post(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        price_kes = request.data.get('price_kes')

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

        try:
            price_kes = float(price_kes)
            if price_kes <= 0:
                raise ValueError("Price must be positive")
        except (ValueError, TypeError):
            return Response({
                'success': False,
                'message': 'Invalid price value'
            }, status=status.HTTP_400_BAD_REQUEST)

        price_kobo = int(price_kes * 100)

        SystemSettings.set_value(
            'vendor_verification_price',
            price_kobo,
            'Vendor verification price in kobo',
            request.user
        )

        return Response({
            'success': True,
            'message': 'Verification price updated successfully',
            'data': {
                'price_kobo': price_kobo,
                'price_kes': price_kes,
                'currency': 'KES'
            }
        }, status=status.HTTP_200_OK)


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 AdminSponsoredAdPriceView(APIView):
    """Admin view to get/set sponsored ad price per day"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        price_kobo = get_sponsored_ad_price()
        price_kes = price_kobo / 100

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

    def post(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        price_kes = request.data.get('price_kes')

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

        try:
            price_kes = float(price_kes)
            if price_kes <= 0:
                raise ValueError("Price must be positive")
        except (ValueError, TypeError):
            return Response({
                'success': False,
                'message': 'Invalid price value'
            }, status=status.HTTP_400_BAD_REQUEST)

        price_kobo = int(price_kes * 100)

        SystemSettings.set_value(
            'sponsored_ad_price_per_day',
            price_kobo,
            'Sponsored ad price per day in kobo',
            request.user
        )

        return Response({
            'success': True,
            'message': 'Sponsored ad price updated successfully',
            'data': {
                'price_kobo': price_kobo,
                'price_kes': price_kes,
                'currency': 'KES'
            }
        }, status=status.HTTP_200_OK)


class AdminVerificationRequestsView(APIView):
    """Admin view to list all verification requests"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        status_filter = request.query_params.get('status', '')
        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 = VerificationRequest.objects.filter(
            payment__status='success'
        ).select_related('vendor', 'vendor__user', 'payment')

        if status_filter:
            queryset = queryset.filter(status=status_filter)

        if search:
            from django.db.models import Q
            queryset = queryset.filter(
                Q(business_name__icontains=search) |
                Q(vendor__shop_name__icontains=search) |
                Q(vendor__user__full_name__icontains=search)
            )

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

        data = []
        for req in requests_list:
            data.append({
                'id': req.id,
                'vendor_id': req.vendor.id,
                'shop_name': req.vendor.shop_name,
                'vendor_name': req.vendor.user.full_name,
                'vendor_email': req.vendor.user.email,
                'vendor_phone': req.vendor.user.phone_number,
                'shop_logo': request.build_absolute_uri(req.vendor.shop_logo.url) if req.vendor.shop_logo else None,
                'business_name': req.business_name,
                'location': req.location,
                'business_phone': req.business_phone,
                'social_link': req.social_link,
                'status': req.status,
                'rejection_reason': req.rejection_reason,
                'amount_paid': float(req.payment.amount) if req.payment else 0,
                'created_at': req.created_at,
                'updated_at': req.updated_at,
            })

        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 AdminVerificationActionView(APIView):
    """Admin view to approve or reject a verification request"""
    permission_classes = [IsAuthenticated]

    def post(self, request, pk):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        action = request.data.get('action')  # 'approve' or 'reject'
        rejection_reason = request.data.get('rejection_reason', '')

        if action not in ('approve', 'reject'):
            return Response({
                'success': False,
                'message': 'Action must be "approve" or "reject"'
            }, status=status.HTTP_400_BAD_REQUEST)

        try:
            verification = VerificationRequest.objects.select_related(
                'vendor', 'vendor__user'
            ).get(pk=pk)
        except VerificationRequest.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Verification request not found'
            }, status=status.HTTP_404_NOT_FOUND)

        vendor_profile = verification.vendor
        user = vendor_profile.user

        if action == 'approve':
            verification.status = 'approved'
            verification.save()

            # Mark vendor as verified
            vendor_profile.is_verified_vendor = True
            vendor_profile.save()

            # Send notification and email
            try:
                from notifications.models import Notification
                Notification.notify_verification_approved(user)
            except Exception:
                pass
            try:
                from accounts.email_service import send_verification_approved_email
                send_verification_approved_email(user, vendor_profile)
            except Exception:
                pass

            return Response({
                'success': True,
                'message': f'{vendor_profile.shop_name} has been verified'
            }, status=status.HTTP_200_OK)

        else:  # reject
            verification.status = 'rejected'
            verification.rejection_reason = rejection_reason
            verification.save()

            # Send notification and email
            try:
                from notifications.models import Notification
                Notification.notify_verification_rejected(user, rejection_reason)
            except Exception:
                pass
            try:
                from accounts.email_service import send_verification_rejected_email
                send_verification_rejected_email(user, vendor_profile, rejection_reason)
            except Exception:
                pass

            return Response({
                'success': True,
                'message': f'{vendor_profile.shop_name} verification has been rejected'
            }, status=status.HTTP_200_OK)


# ============================================================================
# M-Pesa Credential Linking Views
# ============================================================================

class VendorMpesaStatusView(APIView):
    """Get vendor's M-Pesa linking status"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.user_type != 'vendor':
            return Response({
                'success': False,
                'message': 'Only vendors can check M-Pesa status'
            }, status=status.HTTP_403_FORBIDDEN)

        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor profile not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Check if vendor is verified
        if not vendor_profile.is_verified_vendor:
            return Response({
                'success': True,
                'data': {
                    'status': 'not_eligible',
                    'message': 'You must be a verified vendor to link M-Pesa'
                }
            }, status=status.HTTP_200_OK)

        # Check for active credentials
        from .models import VendorMpesaCredentials, MpesaLinkingRequest
        try:
            credentials = vendor_profile.mpesa_credentials
            if credentials and credentials.is_active:
                return Response({
                    'success': True,
                    'data': {
                        'status': 'linked',
                        'account_type': credentials.account_type,
                        'business_short_code': credentials.business_short_code,
                        'linked_at': credentials.created_at,
                    }
                }, status=status.HTTP_200_OK)
        except VendorMpesaCredentials.DoesNotExist:
            pass

        # Check for pending request
        latest_request = MpesaLinkingRequest.objects.filter(
            vendor=vendor_profile
        ).order_by('-created_at').first()

        if latest_request:
            return Response({
                'success': True,
                'data': {
                    'status': latest_request.status,
                    'account_type': latest_request.account_type,
                    'business_short_code': latest_request.business_short_code,
                    'rejection_reason': latest_request.rejection_reason,
                    'created_at': latest_request.created_at,
                }
            }, status=status.HTTP_200_OK)

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


class VendorMpesaLinkRequestView(APIView):
    """Submit M-Pesa linking request (verified vendors only)"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user
        if user.user_type != 'vendor':
            return Response({
                'success': False,
                'message': 'Only vendors can link M-Pesa'
            }, status=status.HTTP_403_FORBIDDEN)

        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor profile not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Check if vendor is verified
        if not vendor_profile.is_verified_vendor:
            return Response({
                'success': False,
                'message': 'You must be a verified vendor to link M-Pesa'
            }, status=status.HTTP_403_FORBIDDEN)

        from .models import MpesaLinkingRequest, VendorMpesaCredentials

        # Check for existing active credentials
        try:
            credentials = vendor_profile.mpesa_credentials
            if credentials and credentials.is_active:
                return Response({
                    'success': False,
                    'message': 'You already have active M-Pesa credentials linked'
                }, status=status.HTTP_400_BAD_REQUEST)
        except VendorMpesaCredentials.DoesNotExist:
            pass

        # Check for pending request
        pending = MpesaLinkingRequest.objects.filter(
            vendor=vendor_profile, status='pending'
        ).exists()
        if pending:
            return Response({
                'success': False,
                'message': 'You already have a pending M-Pesa linking request'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Get form data
        account_type = request.data.get('account_type', '').strip()
        business_short_code = request.data.get('business_short_code', '').strip()
        consumer_key = request.data.get('consumer_key', '').strip()
        consumer_secret = request.data.get('consumer_secret', '').strip()
        passkey = request.data.get('passkey', '').strip()

        # Validate
        if account_type not in ('paybill', 'till'):
            return Response({
                'success': False,
                'message': 'Invalid account type. Must be "paybill" or "till"'
            }, status=status.HTTP_400_BAD_REQUEST)

        if not all([business_short_code, consumer_key, consumer_secret, passkey]):
            return Response({
                'success': False,
                'message': 'All credential fields are required'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Create the linking request
        linking_request = MpesaLinkingRequest(
            vendor=vendor_profile,
            account_type=account_type,
            business_short_code=business_short_code,
            status='pending'
        )
        # Set encrypted fields
        linking_request.consumer_key = consumer_key
        linking_request.consumer_secret = consumer_secret
        linking_request.passkey = passkey
        linking_request.save()

        return Response({
            'success': True,
            'message': 'M-Pesa linking request submitted successfully. An admin will review your credentials.',
            'data': {
                'request_id': linking_request.id,
                'status': 'pending'
            }
        }, status=status.HTTP_201_CREATED)


class AdminMpesaLinkingRequestsView(APIView):
    """Admin view to list all M-Pesa linking requests"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        from .models import MpesaLinkingRequest

        status_filter = request.query_params.get('status', '')
        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 = MpesaLinkingRequest.objects.select_related(
            'vendor', 'vendor__user', 'reviewed_by'
        )

        if status_filter:
            queryset = queryset.filter(status=status_filter)

        if search:
            from django.db.models import Q
            queryset = queryset.filter(
                Q(vendor__shop_name__icontains=search) |
                Q(vendor__user__full_name__icontains=search) |
                Q(business_short_code__icontains=search)
            )

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

        data = []
        for req in requests_list:
            data.append({
                'id': req.id,
                'vendor_id': req.vendor.id,
                'shop_name': req.vendor.shop_name,
                'vendor_name': req.vendor.user.full_name,
                'vendor_email': req.vendor.user.email,
                'vendor_phone': req.vendor.user.phone_number,
                'shop_logo': request.build_absolute_uri(req.vendor.shop_logo.url) if req.vendor.shop_logo else None,
                'account_type': req.account_type,
                'business_short_code': req.business_short_code,
                'status': req.status,
                'rejection_reason': req.rejection_reason,
                'reviewed_by': req.reviewed_by.full_name if req.reviewed_by else None,
                'reviewed_at': req.reviewed_at,
                'created_at': req.created_at,
                'updated_at': req.updated_at,
            })

        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 AdminMpesaTestCredentialsView(APIView):
    """Admin view to test M-Pesa credentials before approval"""
    permission_classes = [IsAuthenticated]

    def post(self, request, pk):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        from .models import MpesaLinkingRequest
        from .mpesa import MpesaAPI

        try:
            linking_request = MpesaLinkingRequest.objects.get(pk=pk)
        except MpesaLinkingRequest.DoesNotExist:
            return Response({
                'success': False,
                'message': 'M-Pesa linking request not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Create MpesaAPI instance with the request's credentials
        mpesa = MpesaAPI(
            consumer_key=linking_request.consumer_key,
            consumer_secret=linking_request.consumer_secret,
            passkey=linking_request.passkey,
            shortcode=linking_request.business_short_code,
            account_type=linking_request.account_type
        )

        # Test credentials
        result = mpesa.test_credentials()

        return Response({
            'success': result['success'],
            'message': result['message'],
            'data': {
                'vendor_name': linking_request.vendor.shop_name,
                'account_type': linking_request.account_type,
                'business_short_code': linking_request.business_short_code,
                'test_result': result
            }
        }, status=status.HTTP_200_OK if result['success'] else status.HTTP_400_BAD_REQUEST)


class AdminMpesaActionView(APIView):
    """Admin view to approve, reject, or revoke M-Pesa linking request"""
    permission_classes = [IsAuthenticated]

    def post(self, request, pk):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        action = request.data.get('action')  # 'approve', 'reject', or 'revoke'
        rejection_reason = request.data.get('rejection_reason', '')

        if action not in ('approve', 'reject', 'revoke'):
            return Response({
                'success': False,
                'message': 'Action must be "approve", "reject", or "revoke"'
            }, status=status.HTTP_400_BAD_REQUEST)

        from .models import MpesaLinkingRequest, VendorMpesaCredentials

        try:
            linking_request = MpesaLinkingRequest.objects.select_related(
                'vendor', 'vendor__user'
            ).get(pk=pk)
        except MpesaLinkingRequest.DoesNotExist:
            return Response({
                'success': False,
                'message': 'M-Pesa linking request not found'
            }, status=status.HTTP_404_NOT_FOUND)

        vendor_profile = linking_request.vendor
        user = vendor_profile.user

        # Handle revoke action for approved requests
        if action == 'revoke':
            if linking_request.status != 'approved':
                return Response({
                    'success': False,
                    'message': 'Can only revoke approved requests'
                }, status=status.HTTP_400_BAD_REQUEST)

            # Update linking request status
            linking_request.status = 'revoked'
            linking_request.rejection_reason = rejection_reason or 'Credentials revoked by admin'
            linking_request.reviewed_by = request.user
            linking_request.reviewed_at = timezone.now()
            linking_request.save()

            # Deactivate vendor credentials
            try:
                credentials = vendor_profile.mpesa_credentials
                credentials.is_active = False
                credentials.save()
            except VendorMpesaCredentials.DoesNotExist:
                pass

            # Send notification
            try:
                from notifications.models import Notification
                Notification.objects.create(
                    user=user,
                    notification_type='mpesa_revoked',
                    title='M-Pesa Access Revoked',
                    message=f'Your M-Pesa integration has been revoked. Reason: {rejection_reason or "No reason provided"}',
                )
            except Exception:
                pass

            return Response({
                'success': True,
                'message': f'M-Pesa credentials for {vendor_profile.shop_name} have been revoked'
            }, status=status.HTTP_200_OK)

        # For approve/reject, check that status is pending
        if linking_request.status != 'pending':
            return Response({
                'success': False,
                'message': f'Request has already been {linking_request.status}'
            }, status=status.HTTP_400_BAD_REQUEST)

        if action == 'approve':
            # Update linking request status
            linking_request.status = 'approved'
            linking_request.reviewed_by = request.user
            linking_request.reviewed_at = timezone.now()
            linking_request.save()

            # Create or update active credentials
            credentials, created = VendorMpesaCredentials.objects.update_or_create(
                vendor=vendor_profile,
                defaults={
                    'linking_request': linking_request,
                    'account_type': linking_request.account_type,
                    'business_short_code': linking_request.business_short_code,
                    'is_active': True,
                }
            )
            # Copy encrypted fields
            credentials.consumer_key = linking_request.consumer_key
            credentials.consumer_secret = linking_request.consumer_secret
            credentials.passkey = linking_request.passkey
            credentials.save()

            # Send notification
            try:
                from notifications.models import Notification
                Notification.objects.create(
                    user=user,
                    notification_type='mpesa_approved',
                    title='M-Pesa Linked Successfully',
                    message=f'Your M-Pesa credentials have been verified and linked to your shop.',
                )
            except Exception:
                pass

            return Response({
                'success': True,
                'message': f'M-Pesa credentials for {vendor_profile.shop_name} have been approved and linked'
            }, status=status.HTTP_200_OK)

        else:  # reject
            linking_request.status = 'rejected'
            linking_request.rejection_reason = rejection_reason
            linking_request.reviewed_by = request.user
            linking_request.reviewed_at = timezone.now()
            linking_request.save()

            # Send notification
            try:
                from notifications.models import Notification
                Notification.objects.create(
                    user=user,
                    notification_type='mpesa_rejected',
                    title='M-Pesa Linking Rejected',
                    message=f'Your M-Pesa credentials were rejected. Reason: {rejection_reason or "No reason provided"}',
                )
            except Exception:
                pass

            return Response({
                'success': True,
                'message': f'M-Pesa linking request for {vendor_profile.shop_name} has been rejected'
            }, status=status.HTTP_200_OK)


class MpesaStkPushView(APIView):
    """Initiate STK Push payment to customer via vendor's M-Pesa"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        from .models import VendorMpesaCredentials, MpesaPayment
        from .mpesa import MpesaAPI
        from products.models import Product

        try:
            return self._process_stk_push(request)
        except Exception as e:
            import traceback
            print(f"STK Push Error: {e}")
            print(traceback.format_exc())
            return Response({
                'success': False,
                'message': f'Payment processing error: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def _process_stk_push(self, request):
        from .models import VendorMpesaCredentials, MpesaPayment
        from .mpesa import MpesaAPI
        from products.models import Product

        user = request.user

        # Get required fields
        vendor_id = request.data.get('vendor_id')
        product_id = request.data.get('product_id')
        phone_number = request.data.get('phone_number', '').strip()
        amount = request.data.get('amount')

        # Validate
        if not vendor_id:
            return Response({
                'success': False,
                'message': 'vendor_id is required'
            }, status=status.HTTP_400_BAD_REQUEST)

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

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

        if not amount or float(amount) <= 0:
            return Response({
                'success': False,
                'message': 'Valid amount is required'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Format phone number (ensure 254 format)
        phone_number = phone_number.replace('+', '').replace(' ', '')
        if phone_number.startswith('0'):
            phone_number = '254' + phone_number[1:]
        elif not phone_number.startswith('254'):
            phone_number = '254' + phone_number

        # Get product
        try:
            product = Product.objects.get(id=product_id)
        except Product.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Product not found'
            }, status=status.HTTP_404_NOT_FOUND)

        # Get vendor credentials
        # Note: vendor_id from frontend could be User ID (from ShopProfile)
        # or VendorProfile ID (from ProductDetail), so we try both
        try:
            # Try by user_id first (ShopProfile sends User ID as vendor_id)
            try:
                vendor_profile = VendorProfile.objects.get(user_id=vendor_id)
            except VendorProfile.DoesNotExist:
                # Fall back to VendorProfile ID (ProductDetail sends VendorProfile ID)
                vendor_profile = VendorProfile.objects.get(id=vendor_id)

            credentials = vendor_profile.mpesa_credentials
            if not credentials or not credentials.is_active:
                return Response({
                    'success': False,
                    'message': 'Vendor does not have active M-Pesa integration'
                }, status=status.HTTP_400_BAD_REQUEST)
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor not found'
            }, status=status.HTTP_404_NOT_FOUND)
        except VendorMpesaCredentials.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor does not have M-Pesa integration'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Create payment record FIRST (for tracking)
        account_reference = f"P{product_id}-{uuid.uuid4().hex[:6].upper()}"
        transaction_desc = f"Payment for {product.name[:50]}"

        payment = MpesaPayment.objects.create(
            vendor=vendor_profile,
            product=product,
            buyer=user,
            amount=float(amount),
            phone_number=phone_number,
            account_reference=account_reference,
            transaction_desc=transaction_desc,
            status='pending'
        )

        # Validate decrypted credentials
        consumer_key = credentials.consumer_key
        consumer_secret = credentials.consumer_secret
        passkey = credentials.passkey

        if not consumer_key or not consumer_secret or not passkey:
            return Response({
                'success': False,
                'message': 'Vendor M-Pesa credentials are invalid or corrupted'
            }, status=status.HTTP_400_BAD_REQUEST)

        # Create MpesaAPI instance
        mpesa = MpesaAPI(
            consumer_key=consumer_key,
            consumer_secret=consumer_secret,
            passkey=passkey,
            shortcode=credentials.business_short_code,
            account_type=credentials.account_type
        )

        # Build callback URL
        callback_url = getattr(settings, 'MPESA_CALLBACK_URL', 'https://api.isoftke.com/api/payments/mpesa/callback/')

        # Initiate STK Push
        result = mpesa.stk_push(
            phone_number=phone_number,
            amount=float(amount),
            account_reference=account_reference,
            transaction_desc=transaction_desc,
            callback_url=callback_url
        )

        if result['success']:
            # Update payment with M-Pesa tracking IDs
            payment.merchant_request_id = result['data'].get('merchant_request_id')
            payment.checkout_request_id = result['data'].get('checkout_request_id')
            payment.status = 'processing'
            payment.save()

            return Response({
                'success': True,
                'message': 'STK Push initiated. Check your phone for M-Pesa prompt.',
                'data': {
                    'payment_id': payment.id,
                    'checkout_request_id': payment.checkout_request_id,
                    'merchant_request_id': payment.merchant_request_id,
                }
            }, status=status.HTTP_200_OK)
        else:
            # Mark payment as failed
            payment.status = 'failed'
            payment.result_desc = result['message']
            payment.save()

            return Response({
                'success': False,
                'message': result['message']
            }, status=status.HTTP_400_BAD_REQUEST)


class MpesaCallbackView(APIView):
    """Handle M-Pesa STK Push callbacks from Safaricom"""
    permission_classes = [AllowAny]

    @csrf_exempt
    def post(self, request):
        from .models import MpesaPayment

        try:
            data = request.data
            callback = data.get('Body', {}).get('stkCallback', {})

            merchant_request_id = callback.get('MerchantRequestID')
            checkout_request_id = callback.get('CheckoutRequestID')
            result_code = str(callback.get('ResultCode', ''))
            result_desc = callback.get('ResultDesc', '')

            # Find the payment
            try:
                payment = MpesaPayment.objects.get(checkout_request_id=checkout_request_id)
            except MpesaPayment.DoesNotExist:
                # Log and return OK to Safaricom
                return Response({'ResultCode': 0, 'ResultDesc': 'Accepted'})

            # Store callback data
            payment.callback_data = data
            payment.result_code = result_code
            payment.result_desc = result_desc

            if result_code == '0':
                # Success - extract receipt number
                callback_metadata = callback.get('CallbackMetadata', {}).get('Item', [])
                for item in callback_metadata:
                    if item.get('Name') == 'MpesaReceiptNumber':
                        payment.mpesa_receipt_number = item.get('Value')
                        break

                payment.status = 'completed'
                payment.completed_at = timezone.now()

                # Send notification to vendor
                try:
                    from notifications.models import Notification
                    Notification.objects.create(
                        user=payment.vendor.user,
                        notification_type='mpesa_payment_received',
                        title='Payment Received',
                        message=f'You received KES {payment.amount} via M-Pesa for {payment.product.name if payment.product else "a product"}. Receipt: {payment.mpesa_receipt_number}',
                    )
                except Exception:
                    pass

            elif result_code == '1032':
                payment.status = 'cancelled'
            elif result_code == '1037':
                payment.status = 'timeout'
            else:
                payment.status = 'failed'

            payment.save()

            return Response({'ResultCode': 0, 'ResultDesc': 'Accepted'})

        except Exception as e:
            return Response({'ResultCode': 0, 'ResultDesc': 'Accepted'})


class MpesaPaymentStatusView(APIView):
    """Check the status of an M-Pesa payment"""
    permission_classes = [IsAuthenticated]

    def get(self, request, payment_id):
        from .models import MpesaPayment

        try:
            payment = MpesaPayment.objects.select_related('product', 'vendor').get(
                id=payment_id,
                buyer=request.user
            )
        except MpesaPayment.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Payment not found'
            }, status=status.HTTP_404_NOT_FOUND)

        return Response({
            'success': True,
            'data': {
                'id': payment.id,
                'status': payment.status,
                'amount': float(payment.amount),
                'phone_number': payment.phone_number,
                'mpesa_receipt_number': payment.mpesa_receipt_number,
                'product_name': payment.product.name if payment.product else None,
                'vendor_name': payment.vendor.shop_name,
                'result_desc': payment.result_desc,
                'created_at': payment.created_at,
                'completed_at': payment.completed_at,
            }
        }, status=status.HTTP_200_OK)


class VendorMpesaPaymentsView(APIView):
    """List M-Pesa payments received by vendor"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        if user.user_type != 'vendor':
            return Response({
                'success': False,
                'message': 'Only vendors can view payments'
            }, status=status.HTTP_403_FORBIDDEN)

        try:
            vendor_profile = user.vendor_profile
        except VendorProfile.DoesNotExist:
            return Response({
                'success': False,
                'message': 'Vendor profile not found'
            }, status=status.HTTP_404_NOT_FOUND)

        try:
            from .models import MpesaPayment
            from django.db.models import Sum, Count

            # Get filter params
            status_filter = request.query_params.get('status', '')
            page = int(request.query_params.get('page', 1))
            page_size = int(request.query_params.get('page_size', 20))

            queryset = MpesaPayment.objects.filter(
                vendor=vendor_profile
            ).select_related('product', 'buyer').order_by('-created_at')

            if status_filter:
                queryset = queryset.filter(status=status_filter)

            # Get stats
            stats = MpesaPayment.objects.filter(
                vendor=vendor_profile,
                status='completed'
            ).aggregate(
                total_amount=Sum('amount'),
                total_count=Count('id')
            )

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

            data = []
            for p in payments_list:
                data.append({
                    'id': p.id,
                    'product_id': p.product.id if p.product else None,
                    'product_name': p.product.name if p.product else 'Unknown',
                    'product_image': request.build_absolute_uri(p.product.primary_image.url) if p.product and p.product.primary_image else None,
                    'buyer_name': p.buyer.full_name if p.buyer else 'Unknown',
                    'buyer_phone': p.phone_number,
                    'amount': float(p.amount),
                    'status': p.status,
                    'mpesa_receipt_number': p.mpesa_receipt_number,
                    'created_at': p.created_at,
                    'completed_at': p.completed_at,
                })

            return Response({
                'success': True,
                'data': {
                    'results': data,
                    'total': total,
                    'page': page,
                    'page_size': page_size,
                    'total_pages': (total + page_size - 1) // page_size,
                    'stats': {
                        'total_earned': float(stats['total_amount'] or 0),
                        'total_payments': stats['total_count'] or 0,
                    }
                }
            }, status=status.HTTP_200_OK)

        except Exception as e:
            import traceback
            print(f"VendorMpesaPayments Error: {e}")
            print(traceback.format_exc())
            return Response({
                'success': False,
                'message': f'Error loading payments: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class AdminMpesaPaymentsView(APIView):
    """Admin view to list all M-Pesa payments"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if request.user.user_type != 'admin':
            return Response({
                'success': False,
                'message': 'Admin access required'
            }, status=status.HTTP_403_FORBIDDEN)

        from .models import MpesaPayment
        from django.db.models import Sum, Count

        # Get filter params
        status_filter = request.query_params.get('status', '')
        vendor_id = request.query_params.get('vendor_id', '')
        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 = MpesaPayment.objects.select_related(
            'vendor', 'vendor__user', 'product', 'buyer'
        ).order_by('-created_at')

        if status_filter:
            queryset = queryset.filter(status=status_filter)

        if vendor_id:
            queryset = queryset.filter(vendor_id=vendor_id)

        if search:
            from django.db.models import Q
            queryset = queryset.filter(
                Q(vendor__shop_name__icontains=search) |
                Q(phone_number__icontains=search) |
                Q(mpesa_receipt_number__icontains=search) |
                Q(product__name__icontains=search)
            )

        # Get stats
        stats = MpesaPayment.objects.filter(status='completed').aggregate(
            total_amount=Sum('amount'),
            total_count=Count('id')
        )

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

        data = []
        for p in payments_list:
            data.append({
                'id': p.id,
                'vendor_id': p.vendor.id,
                'vendor_name': p.vendor.shop_name,
                'vendor_logo': request.build_absolute_uri(p.vendor.shop_logo.url) if p.vendor.shop_logo else None,
                'product_id': p.product.id if p.product else None,
                'product_name': p.product.name if p.product else 'Unknown',
                'buyer_id': p.buyer.id if p.buyer else None,
                'buyer_name': p.buyer.full_name if p.buyer else 'Unknown',
                'buyer_phone': p.phone_number,
                'amount': float(p.amount),
                'status': p.status,
                'mpesa_receipt_number': p.mpesa_receipt_number,
                'result_desc': p.result_desc,
                'created_at': p.created_at,
                'completed_at': p.completed_at,
            })

        return Response({
            'success': True,
            'data': {
                'results': data,
                'total': total,
                'page': page,
                'page_size': page_size,
                'total_pages': (total + page_size - 1) // page_size,
                'stats': {
                    'total_amount': float(stats['total_amount'] or 0),
                    'total_payments': stats['total_count'] or 0,
                }
            }
        }, status=status.HTTP_200_OK)
