from rest_framework import status
from rest_framework.decorators import api_view, permission_classes, parser_classes
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser
from .models import Property, PropertyImage, PropertyAddonsFee, PropertyBookmark, TempProperty, TempPropertyImage
from .serializers import PropertySerializer, TempPropertySerializer
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
from rest_framework_simplejwt.tokens import AccessToken
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
import time
from users.models import Organization, Agent
from users.serializers import AgentSerializer
from django.db.models import Q
from django.core.cache import cache

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Property
from .serializers import PropertySerializer

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework import status
from .models import Property
from .serializers import PropertySerializer
from .models import Property, PropertyImage
from .serializers import PropertySerializer
from django.db import models

from uuid import uuid4


@api_view(['GET'])
@permission_classes([AllowAny])
def test_connection(request):
    """Simple test endpoint to verify API connection"""
    return Response({'message': 'Property API is working!'}, status=status.HTTP_200_OK)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def test_auth(request):
    """Test endpoint to verify user authentication"""
    return Response({
        'message': 'Authentication working!',
        'user_id': request.user.id,
        'user_email': request.user.email,
        'is_authenticated': request.user.is_authenticated
    }, status=status.HTTP_200_OK)


@api_view(['GET'])
@permission_classes([AllowAny])
def check_token(request):
    """Check token validity without requiring authentication"""
    auth_header = request.META.get('HTTP_AUTHORIZATION', '')
    # print(f"Auth header received: {auth_header}")
    
    if not auth_header.startswith('JWT '):
        return Response({
            'valid': False,
            'error': 'No JWT token provided or wrong format'
        }, status=status.HTTP_401_UNAUTHORIZED)
    
    token = auth_header.split(' ')[1]
    # print(f"Token extracted: {token[:20]}...")
    
    try:
        # Try to validate the token
        token_obj = AccessToken(token)
        user_id = token_obj['user_id']
        
        # Check if user exists
        from django.contrib.auth import get_user_model
        User = get_user_model()
        user = User.objects.get(id=user_id)
        
        return Response({
            'valid': True,
            'user_id': user_id,
            'user_email': user.email,
            'token_exp': token_obj['exp'],
            'current_time': int(time.time())
        }, status=status.HTTP_200_OK)
        
    except (InvalidToken, TokenError, KeyError, User.DoesNotExist) as e:
        # print(f"Token validation error: {e}")
        return Response({
            'valid': False,
            'error': str(e)
        }, status=status.HTTP_401_UNAUTHORIZED)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
@parser_classes([MultiPartParser, FormParser])
def create_property(request):
    try:
        data = request.data.copy()
        max_file_size = 100 * 1024 * 1024  # 100MB
        for field_name, file_obj in request.FILES.items():
            if hasattr(file_obj, 'size') and file_obj.size > max_file_size:
                return Response({
                    'error': f'File {field_name} is too large. Maximum size is 100MB.'
                }, status=status.HTTP_400_BAD_REQUEST)
        transformed_data = data.copy()
        if not request.user.is_authenticated:
            return Response({'error': 'User not authenticated'}, status=status.HTTP_401_UNAUTHORIZED)
        user = request.user
        role = user.role
        
        # Check and handle subscription credits for addon features (only for direct creation, not payment flow)
        hide_address = data.get('hide_address', False)
        hide_contact = data.get('contact_details_hidden', False)
        is_payment_flow = data.get('is_payment_flow', False)  # Flag to distinguish payment flow
        
        # Check for active subscription
        from users.models import Subscription
        from django.utils import timezone

        active_subscription = Subscription.objects.filter(
            user=user,
            expiry_date__gt=timezone.now()
        ).order_by('-subscription_date').first()


        if (hide_address=="true" or hide_contact=="true") and not is_payment_flow and active_subscription:
            # Only deduct credits for direct property creation (no payment flow)
            
            # Check if user has enough credits for requested features
            credits_needed = {
                'hide_address': hide_address and active_subscription.hide_address_count <= 0,
                'hide_contact': hide_contact and active_subscription.hide_contact_count <= 0
            }
            
            # If any feature needs credits but user doesn't have them, block creation
            if any(credits_needed.values()):
                missing_features = []
                if credits_needed['hide_address']:
                    missing_features.append('hide address')
                if credits_needed['hide_contact']:
                    missing_features.append('hide contact')
                
                return Response({
                    'error': f'Insufficient credits for: {", ".join(missing_features)}. Please purchase credits or pay for these features.'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # Deduct credits for features that are being used
            credits_used = {
                'hide_address': False,
                'hide_contact': False
            }
            
            if hide_address=="true" and active_subscription.hide_address_count > 0:
                active_subscription.hide_address_count -= 1
                credits_used['hide_address'] = True
                
            
            if hide_contact=="true" and active_subscription.hide_contact_count > 0:
                active_subscription.hide_contact_count -= 1
                credits_used['hide_contact'] = True
                
            
            # Save the updated subscription
            active_subscription.save()

        orgs_user_id = data.get('organization')
        agents_user_id = data.get('agent')
        # Default assignments
        transformed_data['agent'] = None
        # AGENT
        if role == '2':
            if orgs_user_id:
                # Agent posts for organization: posted_by = organization, agent = self
                try:
                    agent = Agent.objects.get(user=user)
                    organization = Organization.objects.get(user=orgs_user_id)
                    if not organization.agents.filter(pk=agent.pk).exists():
                        return Response({'error': 'Agent not connected to this organization.'}, status=status.HTTP_400_BAD_REQUEST)
                    transformed_data['posted_by'] = organization.user.id
                    transformed_data['agent'] = agent.id
                except (Agent.DoesNotExist, Organization.DoesNotExist) as e:
                    return Response({'error': 'Invalid agent or organization.'}, status=status.HTTP_400_BAD_REQUEST)
            else:
                # Agent posts as individual: posted_by = self, agent = self
                try:
                    agent = Agent.objects.get(user=user)
                    transformed_data['posted_by'] = user.id
                    transformed_data['agent'] = agent.id
                except Agent.DoesNotExist:
                    return Response({'error': 'Agent profile not found.'}, status=status.HTTP_400_BAD_REQUEST)
        # ORGANIZATION
        elif role == '3':
            if agents_user_id:
                # Organization posts with agent: posted_by = self, agent = selected agent
                try:
                    organization = Organization.objects.get(user=user)
                    agent = Agent.objects.get(user=agents_user_id)
                    if not organization.agents.filter(id=agent.id).exists():
                        return Response({'error': 'Agent not part of this organization.'}, status=status.HTTP_400_BAD_REQUEST)
                    transformed_data['posted_by'] = user.id
                    transformed_data['agent'] = agent.id
                except (Organization.DoesNotExist, Agent.DoesNotExist):
                    return Response({'error': 'Invalid organization or agent.'}, status=status.HTTP_400_BAD_REQUEST)
            else:
                # Organization posts as individual: posted_by = self, agent = None
                transformed_data['posted_by'] = user.id
                transformed_data['agent'] = None
        # GENERAL USER
        else:
            transformed_data['posted_by'] = user.id
            transformed_data['agent'] = None
        
        # Handle thumbnail upload with size validation
        if 'thumbnail' in request.FILES:
            thumbnail_file = request.FILES['thumbnail']
            if thumbnail_file.size > max_file_size:
                return Response({
                    'error': 'Thumbnail file is too large. Maximum size is 100MB.'
                }, status=status.HTTP_400_BAD_REQUEST)
            transformed_data['thumbnail'] = thumbnail_file

        # Handle video upload with size validation
        if 'video' in request.FILES:
            video_file = request.FILES['video']
            if video_file.size > max_file_size:
                return Response({
                    'error': 'Video file is too large. Maximum size is 100MB.'
                }, status=status.HTTP_400_BAD_REQUEST)
            transformed_data['video'] = video_file

        # Handle view_360 upload with size validation
        if 'view_360' in request.FILES:
            view_360_file = request.FILES['view_360']
            if view_360_file.size > max_file_size:
                return Response({
                    'error': '360 View file is too large. Maximum size is 100MB.'
                }, status=status.HTTP_400_BAD_REQUEST)
            transformed_data['view_360'] = view_360_file
        
        # Create the property
        serializer = PropertySerializer(data=transformed_data, context={'request': request})
        if serializer.is_valid():
            property_instance = serializer.save()
            
            # Handle multiple images upload with size validation
            if 'images' in request.FILES:
                uploaded_images = []
                for image_file in request.FILES.getlist('images'):
                    if image_file.size > max_file_size:
                        return Response({
                            'error': f'Image file {image_file.name} is too large. Maximum size is 100MB.'
                        }, status=status.HTTP_400_BAD_REQUEST)
                    
                    try:
                        property_image = PropertyImage.objects.create(image=image_file)
                        uploaded_images.append(property_image)
                    except Exception as e:
                        return Response({
                            'error': f'Failed to upload image {image_file.name}: {str(e)}'
                        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                
                # Add all successfully uploaded images to the property
                for image in uploaded_images:
                    property_instance.featured_pictures.add(image)
                

                # Validation: At least one image and a thumbnail required
                if not property_instance.thumbnail or property_instance.featured_pictures.count() == 0:
                    property_instance.delete()
                    return Response({'error': 'At least one image and a thumbnail are required.'}, status=status.HTTP_400_BAD_REQUEST)

                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
            
    except Exception as e:
        return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
@parser_classes([MultiPartParser, FormParser])
def update_property(request, pk):
    property_obj = get_object_or_404(Property, pk=pk)

    # Debug prints for authorization
    # if property_obj.agent:
    #     print("property_obj.agent:", property_obj.agent, "agent.user:", property_obj.agent.user, "ID:", getattr(property_obj.agent.user, 'id', None))
    # else:
    #     print("property_obj.agent: None")

    # Allow edit if user is posted_by or agent's user
    if not (
        property_obj.posted_by == request.user or
        (property_obj.agent and property_obj.agent.user == request.user)
    ):
        return Response({'detail': 'Not authorized to edit this property.'}, status=status.HTTP_403_FORBIDDEN)

    data = request.data.copy()
    files = request.FILES

    # Handle agent/organization assignment (mirroring create_property logic)
    user = request.user
    role = getattr(user, 'role', None)
    orgs_user_id = data.get('organization')
    agents_user_id = data.get('agent')


    # Default assignments
    data['agent'] = None
    # AGENT
    if role == '2':
        if orgs_user_id not in [None, '', 'null', 'undefined']:
            # Agent posts for organization: posted_by = organization, agent = self
            try:
                from users.models import Agent, Organization
                agent = Agent.objects.get(user=user)
                organization = Organization.objects.get(user=orgs_user_id)
                if not organization.agents.filter(pk=agent.pk).exists():
                    return Response({'error': 'Agent not connected to this organization.'}, status=status.HTTP_400_BAD_REQUEST)
                data['posted_by'] = organization.user.id
                data['agent'] = agent.id
            except (Agent.DoesNotExist, Organization.DoesNotExist) as e:
                return Response({'error': 'Invalid organization.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            # Agent posts as individual: posted_by = self, agent = self
            try:
                from users.models import Agent
                agent = Agent.objects.get(user=user)
                data['posted_by'] = user.id
                data['agent'] = agent.id
            except Agent.DoesNotExist:
                return Response({'error': 'Agent profile not found.'}, status=status.HTTP_400_BAD_REQUEST)
    # ORGANIZATION
    elif role == '3':
        if agents_user_id not in [None, '', 'null', 'undefined']:
            # Organization posts with agent: posted_by = self, agent = selected agent
            try:
                from users.models import Organization, Agent
                organization = Organization.objects.get(user=user)
                agent = Agent.objects.get(user=agents_user_id)
                if not organization.agents.filter(id=agent.id).exists():
                    return Response({'error': 'Agent not part of this organization.'}, status=status.HTTP_400_BAD_REQUEST)
                data['posted_by'] = user.id
                data['agent'] = agent.id
            except (Organization.DoesNotExist, Agent.DoesNotExist):
                return Response({'error': 'Invalid agent.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            # Organization posts as individual: posted_by = self, agent = None
            data['posted_by'] = user.id
            data['agent'] = None
    # GENERAL USER
    else:
        data['posted_by'] = user.id
        data['agent'] = None

    # --- PATCH: Prevent updating hide_address/contact_details_hidden if payment is required ---
    from users.models import Subscription
    from django.utils import timezone
    # Determine if user is trying to newly enable add-ons
    new_hide_address = False
    new_hide_contact = False
    if 'hide_address' in data:
        new_hide_address = (not property_obj.hide_address) and (data.get('hide_address')  == 'true')
    if 'contact_details_hidden' in data:
        new_hide_contact = (not property_obj.contact_details_hidden) and (data.get('contact_details_hidden') =='true')
    # Calculate if payment is required for these add-ons

    payment_required = False
    if new_hide_address or new_hide_contact:
        active_subscription = Subscription.objects.filter(
            user=user,
            expiry_date__gt=timezone.now()
        ).order_by('-subscription_date').first()

        has_hide_address_credit = active_subscription and active_subscription.hide_address_count > 0
        has_hide_contact_credit = active_subscription and active_subscription.hide_contact_count > 0

        if active_subscription:
            if new_hide_address and active_subscription.hide_address_count > 0:
                active_subscription.hide_address_count -= 1
            if new_hide_contact and active_subscription.hide_contact_count > 0:
                active_subscription.hide_contact_count -= 1
            active_subscription.save()
        # Use your fee logic here if needed
        # Payment required if user has no credits for the new add-ons
        if (new_hide_address and not has_hide_address_credit) or (new_hide_contact and not has_hide_contact_credit):
            payment_required = True
    # If payment is required, do not update these fields now
    if payment_required:
        if 'hide_address' in data:
            data.pop('hide_address')
        if 'contact_details_hidden' in data:
            data.pop('contact_details_hidden')
    # --- END PATCH ---

    # Only update file fields if a new file is provided; otherwise, keep the existing file
    if 'thumbnail' in files:
        data['thumbnail'] = files['thumbnail']
    else:
        data['thumbnail'] = property_obj.thumbnail

    if 'video' in files:
        data['video'] = files['video']
    else:
        data['video'] = property_obj.video

    if 'view_360' in files:
        data['view_360'] = files['view_360']
    else:
        data['view_360'] = property_obj.view_360

    serializer = PropertySerializer(property_obj, data=data, partial=True)
    if serializer.is_valid():
        property_instance = serializer.save()

        # Handle deleted images
        deleted_images = request.data.getlist('deleted_images') if hasattr(request.data, 'getlist') else request.data.get('deleted_images', [])
        if deleted_images:
            if isinstance(deleted_images, str):
                deleted_images = [deleted_images]
            for img_id in deleted_images:
                try:
                    img_obj = property_instance.featured_pictures.get(id=img_id)
                    property_instance.featured_pictures.remove(img_obj)
                    img_obj.delete()
                except Exception as e:
                    print(f"Error deleting image: {e}")

        # Handle new images
        if 'images' in files:
            for image_file in files.getlist('images'):
                # Prevent duplicate images by checking if an image with the same name already exists for this property
                if property_instance.featured_pictures.filter(image=image_file.name).exists():
                    continue  # Skip duplicate
                try:
                    property_image = PropertyImage.objects.create(image=image_file)
                    property_instance.featured_pictures.add(property_image)
                except Exception as e:
                    print(f"Error uploading image")
        
        # Validation: At least one image required
        if property_instance.featured_pictures.count() == 0:
            return Response({'error': 'At least one property image is required.'}, status=status.HTTP_400_BAD_REQUEST)

        return Response(PropertySerializer(property_instance, context={'request': request}).data)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def delete_property(request, pk):
    property_obj = get_object_or_404(Property, pk=pk)

    # Check ownership
    if property_obj.posted_by != request.user:
        return Response({'detail': 'Not authorized to delete this property.'}, status=status.HTTP_403_FORBIDDEN)

    property_obj.delete()
    return Response({'detail': 'Property deleted successfully.'}, status=status.HTTP_204_NO_CONTENT)

@api_view(['GET'])
@permission_classes([AllowAny])  # change to IsAuthenticated if needed
def property_detail(request, pk):
    property_obj = get_object_or_404(Property, pk=pk)
    serializer = PropertySerializer(property_obj)
    return Response(serializer.data, status=status.HTTP_200_OK)

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def my_properties(request):
    properties = Property.objects.filter(Q(posted_by=request.user) | Q(agent__user=request.user)).distinct()
    serializer = PropertySerializer(properties, many=True, context={'request': request})
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(['GET'])
@permission_classes([AllowAny]) 
def search_properties(request):
    try:
        # Extract filters from query params
        post_type = request.GET.get('post_type')
        property_type = request.GET.get('property_type')
        lat = request.GET.get('latitude')
        lon = request.GET.get('longitude')
        radius = request.GET.get('radius', 5)  # Default 5 km

        if lat is not None and lon is not None:
            lat = float(lat)
            lon = float(lon)
            radius = float(radius)

        properties = Property.objects.search_with_filters(
            post_type=post_type,
            property_type=property_type,
            latitude=lat,
            longitude=lon,
            radius_km=radius
        )

        serialized = PropertySerializer(properties, many=True)
        return Response(serialized.data, status=status.HTTP_200_OK)

    except Exception as e:
        return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET'])
@permission_classes([AllowAny])  # Allow any user to access this
def filter_properties(request):
    latitude = request.GET.get('lat')
    longitude = request.GET.get('lon')
    radius = request.GET.get('radius', 5)  # Default radius is 5 km
    property_type = request.GET.get('property_type')
    post_type = request.GET.get('post_type')
    # print(request.GET)

    if not latitude or not longitude:
        return Response({'error': 'Latitude and Longitude are required.'}, status=status.HTTP_400_BAD_REQUEST)

    try:
        latitude = float(latitude)
        longitude = float(longitude)
        radius = float(radius)/1000
    except ValueError:
        return Response({'error': 'Invalid latitude, longitude, or radius value.'}, status=status.HTTP_400_BAD_REQUEST)

    properties = Property.objects.search_with_filters(
        latitude=latitude,
        longitude=longitude,
        radius_km=radius,
        property_type=property_type,
        post_type=post_type
    )

    # print(latitude, longitude, radius, property_type, post_type)
    # print(properties)

    serializer = PropertySerializer(properties, many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(['GET'])
@permission_classes([AllowAny])
def get_property_addons_fee(request):
    fee = PropertyAddonsFee.objects.first()
    if not fee:
        # Return default values if not set in DB
        data = {
            'hide_address_fee': 1.99,
            'hide_contact_fee': 1.55,
            'hide_address_and_contact_combined_fee': 2.99,
        }
    else:
        data = {
            'hide_address_fee': float(fee.hide_address_fee),
            'hide_contact_fee': float(fee.hide_contact_fee),
            'hide_address_and_contact_combined_fee': float(fee.hide_address_and_contact_combined_fee),
        }
    return Response(data)

@api_view(['GET'])
@permission_classes([AllowAny])
def calculate_property_addon_fee(request):
    hide_address = request.GET.get('hide_address') == 'true'
    hide_contact = request.GET.get('hide_contact') == 'true'
    fee = PropertyAddonsFee.objects.first()
    if not fee:
        hide_address_fee = 1.99
        hide_contact_fee = 1.55
        combined_fee = 2.99
    else:
        hide_address_fee = float(fee.hide_address_fee)
        hide_contact_fee = float(fee.hide_contact_fee)
        combined_fee = float(fee.hide_address_and_contact_combined_fee)
    if hide_address and hide_contact:
        total_fee = combined_fee
    elif hide_address:
        total_fee = hide_address_fee
    elif hide_contact:
        total_fee = hide_contact_fee
    else:
        total_fee = 0.0
    return Response({'fee': total_fee})

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_subscription_addon_fee(request):
    """Get subscription-based addon fee calculation"""
    try:
        hide_address = request.GET.get('hide_address', 'false').lower() == 'true'
        hide_contact = request.GET.get('hide_contact', 'false').lower() == 'true'
        
        # Get base fees
        fee_obj = PropertyAddonsFee.objects.first()
        hide_address_fee = float(fee_obj.hide_address_fee)
        hide_contact_fee = float(fee_obj.hide_contact_fee)
        combined_fee = float(fee_obj.hide_address_and_contact_combined_fee)
        
        # Calculate fee based on selection
        if hide_address and hide_contact:
            fee = combined_fee
        elif hide_address:
            fee = hide_address_fee
        elif hide_contact:
            fee = hide_contact_fee
        else:
            fee = 0
        
        # Check for active subscription
        from users.models import Subscription
        from django.utils import timezone
        active_subscription = Subscription.objects.filter(
            user=request.user,
            expiry_date__gt=timezone.now()
        ).order_by('-subscription_date').first()
        
        subscription_info = None
        can_use_credits = False
        remaining_credits = {}
        
        if active_subscription:
            # Check if user can use credits for each feature individually
            can_use_hide_address = active_subscription.hide_address_count > 0 and hide_address
            can_use_hide_contact = active_subscription.hide_contact_count > 0 and hide_contact
            
            # Calculate fee based on what user needs to pay for (after using credits)
            if hide_address and hide_contact:
                # Both selected - check if we can use combined fee or need to calculate individually
                if can_use_hide_address and can_use_hide_contact:
                    # Both can be covered by credits
                    fee = 0
                elif can_use_hide_address:
                    # Only hide address can be covered by credits, pay for hide contact
                    fee = hide_contact_fee
                elif can_use_hide_contact:
                    # Only hide contact can be covered by credits, pay for hide address
                    fee = hide_address_fee
                else:
                    # Neither can be covered by credits, use combined fee
                    fee = combined_fee
            elif hide_address:
                fee = 0 if can_use_hide_address else hide_address_fee
            elif hide_contact:
                fee = 0 if can_use_hide_contact else hide_contact_fee
            else:
                fee = 0
            
            # User can use credits if they have credits for ANY of the selected features
            can_use_credits = can_use_hide_address or can_use_hide_contact
            
            subscription_info = {
                'package_name': active_subscription.package.name,
                'remaining_hide_address_count': active_subscription.hide_address_count,
                'remaining_hide_contact_count': active_subscription.hide_contact_count,
            }
            
            remaining_credits = {
                'hide_address': active_subscription.hide_address_count,
                'hide_contact': active_subscription.hide_contact_count,
            }
        
        return Response({
            'fee': round(fee, 2),
            'subscription': subscription_info,
            'can_use_credits': can_use_credits,
            'remaining_credits': remaining_credits,
        })
        
    except Exception as e:
        return Response({'error': str(e)}, status=500)



@api_view(['GET'])
@permission_classes([AllowAny])
def property_details_page(request, pk):
    property_obj = get_object_or_404(Property, pk=pk)
    serializer = PropertySerializer(property_obj, context={'request': request})
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def property_bookmarks(request):
    bookmarks = PropertyBookmark.objects.filter(user=request.user).select_related('property')
    properties = [bookmark.property for bookmark in bookmarks]
    serializer = PropertySerializer(properties, many=True, context={'request': request})
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def toggle_property_bookmark(request):
    property_id = request.data.get('property_id') or request.query_params.get('property_id')
    if not property_id:
        return Response({'error': 'property_id is required'}, status=status.HTTP_400_BAD_REQUEST)
    try:
        property_obj = Property.objects.get(pk=property_id)
    except Property.DoesNotExist:
        return Response({'error': 'Property not found'}, status=status.HTTP_404_NOT_FOUND)
    bookmarked = PropertyBookmark.toggle(request.user, property_obj)
    return Response({'bookmarked': bookmarked}, status=status.HTTP_200_OK)


from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .models import PropertyBoostPrice

@api_view(['GET'])
@permission_classes([AllowAny])
def get_boosting_price(request):
    price_obj = PropertyBoostPrice.objects.last()
    price = str(price_obj.price if price_obj else 4.99)
    return Response({"price": price})  # Always USD

from decimal import Decimal, ROUND_HALF_UP
from .models import Property, PropertyBoostPrice
from django.conf import settings
import paypalrestsdk

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def create_boost_paypal_payment(request, property_id):
    user = request.user
    try:
        prop = Property.objects.get(id=property_id, posted_by=user)
    except Property.DoesNotExist:
        return Response({"error": "Property not found"}, status=404)

    price_obj = PropertyBoostPrice.objects.last()
    price = price_obj.price if price_obj else Decimal('4.99')
    final_price = str(price.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))
    currency = "EUR"  # Hardcoded

    paypalrestsdk.configure({
        "mode": settings.PAYPAL_MODE,
        "client_id": settings.PAYPAL_CLIENT_ID,
        "client_secret": settings.PAYPAL_CLIENT_SECRET,
    })

    payment = paypalrestsdk.Payment({
        "intent": "sale",
        "payer": {"payment_method": "paypal"},
        "redirect_urls": {
            "return_url": settings.PAYPAL_BOOST_SUCCESS_URL + f"?property_id={prop.id}",
            "cancel_url": settings.PAYPAL_CANCEL_URL,
        },
        "transactions": [{
            "amount": {
                "total": final_price,
                "currency": currency,
            },
            "description": f"Boost Property {prop.property_id}",
        }]
    })

    if payment.create():
        # Save payment id to your model for later confirmation
        # (Optional: create a BoostPayment record to track it)
        approval_url = next((link.href for link in payment.links if link.rel == "approval_url"), None)
        return Response({"approval_url": approval_url})
    else:
        # print("PayPal Payment Error:", payment.error)
        return Response({'error': 'Payment creation failed', 'details': payment.error}, status=400)

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from django.conf import settings
from django.utils import timezone
import paypalrestsdk
from decimal import Decimal
from .models import Property, PropertyBoost, PropertyBoostPrice  # Update path as needed

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def paypal_boost_success(request):
    payment_id = request.data.get('paymentId')
    payer_id = request.data.get('payerId')
    property_id = request.data.get('property_id')

    if not all([payment_id, payer_id, property_id]):
        return Response({'error': 'Missing required fields.'}, status=status.HTTP_400_BAD_REQUEST)

    try:
        prop = Property.objects.get(id=property_id)
    except Property.DoesNotExist:
        return Response({'error': 'Property not found.'}, status=status.HTTP_404_NOT_FOUND)

    # PayPal config
    paypalrestsdk.configure({
        "mode": settings.PAYPAL_MODE,
        "client_id": settings.PAYPAL_CLIENT_ID,
        "client_secret": settings.PAYPAL_CLIENT_SECRET,
    })

    try:
        payment = paypalrestsdk.Payment.find(payment_id)
        if payment.execute({"payer_id": payer_id}):
            # Success: create/update boost
            user = request.user

            # How long is boost? (Default: 24 hours)
            boost_duration = getattr(settings, "BOOST_DURATION_HOURS", 24)
            now = timezone.now()

            # Find existing boost that hasn't expired and update, or create new
            boost, created = PropertyBoost.objects.get_or_create(
                property=prop, user=user,
                defaults={
                    'boosted_at': now,
                    'expires_at': now + timezone.timedelta(hours=boost_duration)
                }
            )
            if not created:
                # Extend from now or from previous expiry, whichever is later
                boost.boosted_at = now
                boost.expires_at = max(now, boost.expires_at) + timezone.timedelta(hours=boost_duration)
                boost.save()

            return Response({'success': True, 'expires_at': boost.expires_at})

        else:
            return Response({'error': 'Payment execution failed.'}, status=status.HTTP_400_BAD_REQUEST)

    except Exception as e:
        # print("PayPal Boost Error:", str(e))
        return Response({'error': f'Payment verify error: {str(e)}'}, status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
@parser_classes([MultiPartParser, FormParser])
def create_temp_property(request):
    """
    Create a TempProperty with all data and files. Returns temp_property_id.
    """
    import logging
    logger = logging.getLogger(__name__)
    
    # Debug: Log incoming request data
    # print("=== CREATE TEMP PROPERTY DEBUG ===")
    # print(f"Request user: {request.user.id} ({request.user.email})")
    # print(f"Request data: {request.data}")
    # print(f"Request files: {request.FILES}")
    # print(f"Request headers: {dict(request.headers)}")
    
    data = request.data.copy()
    data['user'] = request.user.id
    
    # Handle agent field properly (similar to create_property logic)
    user = request.user
    role = user.role
    orgs_user_id = data.get('organization')
    agents_user_id = data.get('agent')
    
    # Default assignments
    data['agent'] = None
    
    # AGENT
    if role == '2':
        if orgs_user_id:
            # Agent posts for organization: posted_by = organization, agent = self
            try:
                agent = Agent.objects.get(user=user)
                organization = Organization.objects.get(user=orgs_user_id)
                if not organization.agents.filter(pk=agent.pk).exists():
                    return Response({'error': 'Agent not connected to this organization.'}, status=status.HTTP_400_BAD_REQUEST)
                data['agent'] = agent.id
            except (Agent.DoesNotExist, Organization.DoesNotExist) as e:
                # print(e)
                return Response({'error': 'Invalid agent or organization.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            # Agent posts as individual: posted_by = self, agent = self
            try:
                agent = Agent.objects.get(user=user)
                data['agent'] = agent.id
            except Agent.DoesNotExist:
                return Response({'error': 'Agent profile not found.'}, status=status.HTTP_400_BAD_REQUEST)
    # ORGANIZATION
    elif role == '3':
        if agents_user_id:
            # Organization posts with agent: posted_by = self, agent = selected agent
            try:
                organization = Organization.objects.get(user=user)
                agent = Agent.objects.get(user=agents_user_id)
                if not organization.agents.filter(id=agent.id).exists():
                    return Response({'error': 'Agent not part of this organization.'}, status=status.HTTP_400_BAD_REQUEST)
                data['agent'] = agent.id
            except (Organization.DoesNotExist, Agent.DoesNotExist):
                return Response({'error': 'Invalid organization or agent.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            # Organization posts as individual: posted_by = self, agent = None
            data['agent'] = None
    # GENERAL USER
    else:
        data['agent'] = None
    
    # Debug: Log specific fields we're concerned about
    # print(f"Agent field: {data.get('agent')}")
    # print(f"Latitude field: {data.get('latitude')}")
    # print(f"Longitude field: {data.get('longitude')}")
    # print(f"House no field: {data.get('house_no')}")
    
    # # Debug: Log all data keys to see what's actually being received
    # print(f"All data keys: {list(data.keys())}")
    # print(f"All data values: {list(data.values())}")
    
    # # Debug: Check if fields exist in request.data directly
    # print(f"Request.data agent: {request.data.get('agent')}")
    # print(f"Request.data latitude: {request.data.get('latitude')}")
    # print(f"Request.data longitude: {request.data.get('longitude')}")
    
    # print(f"Final data being sent to serializer: {data}")
    
    serializer = TempPropertySerializer(data=data)
    # print(f"Serializer initial data: {serializer.initial_data}")
    
    if serializer.is_valid():
        # print("Serializer is valid, saving temp property...")
        temp_property = serializer.save()
        # print(f"TempProperty saved with ID: {temp_property.id}")
        
        # Debug: Log saved values
        # print(f"Saved agent: {temp_property.agent}")
        # print(f"Saved latitude: {temp_property.latitude}")
        # print(f"Saved longitude: {temp_property.longitude}")
        # print(f"Saved house_no: {temp_property.house_no}")
        
        # Handle images
        if 'images' in request.FILES:
            # print(f"Processing {len(request.FILES.getlist('images'))} images...")
            for image_file in request.FILES.getlist('images'):
                TempPropertyImage.objects.create(temp_property=temp_property, image=image_file)
                # print(f"Created image: {image_file.name}")
        
        success_response = {'temp_property_id': temp_property.id}
        # print(f"SUCCESS: {success_response}")
        return Response(success_response, status=201)
    else:
        error_msg = f'Serializer validation failed: {serializer.errors}'
        # print(f"ERROR: {error_msg}")
        # print(f"Serializer errors: {serializer.errors}")
        return Response({
            'error': 'TempProperty creation failed due to validation errors',
            'details': serializer.errors,
            'debug_data': data
        }, status=400)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def finalize_temp_property(request):
    """
    Move data/files from TempProperty to Property, then delete TempProperty.
    Expects temp_property_id in POST data.
    """
    import logging
    logger = logging.getLogger(__name__)
    
    # Debug: Log incoming request data
    # print("=== FINALIZE TEMP PROPERTY DEBUG ===")
    # print(f"Request user: {request.user.id} ({request.user.email})")
    # print(f"Request data: {request.data}")
    # print(f"Request headers: {dict(request.headers)}")
    
    temp_property_id = request.data.get('temp_property_id')
    # print(f"Temp property ID: {temp_property_id}")
    
    if not temp_property_id:
        error_msg = 'Missing temp_property_id'
        # print(f"ERROR: {error_msg}")
        return Response({'error': error_msg}, status=400)
    
    try:
        temp = TempProperty.objects.get(id=temp_property_id, user=request.user)
        # print(f"Found TempProperty: {temp.id}")
        # print(f"TempProperty fields: {[f.name for f in TempProperty._meta.fields]}")
    except TempProperty.DoesNotExist:
        error_msg = f'TempProperty not found with id {temp_property_id} for user {request.user.id}'
        # print(f"ERROR: {error_msg}")
        return Response({'error': error_msg}, status=404)
    except Exception as e:
        error_msg = f'Error finding TempProperty: {str(e)}'
        # print(f"ERROR: {error_msg}")
        logger.error(error_msg, exc_info=True)
        return Response({'error': error_msg}, status=500)
    
    # Prepare data for Property, skip empty file fields
    property_data = {}
    # print("Preparing property data...")
    
    try:
        for field in TempProperty._meta.fields:
            if field.name in ['id', 'user', 'created_at']:
                # print(f"Skipping field: {field.name}")
                continue
            
            value = getattr(temp, field.name)
            # print(f"Field: {field.name}, Value: {value}, Type: {type(value)}")
            
            # Handle file fields
            if isinstance(field, (models.FileField, models.ImageField)):
                if not value or not getattr(value, 'name', None):
                    # print(f"Skipping empty file field: {field.name}")
                    continue
                # Keep the file object for serializer
                property_data[field.name] = value
                continue
            
            # Handle empty string fields that should be None or default values
            if isinstance(value, str) and value.strip() == '':
                if field.name in ['built_year', 'garages_count', 'garage_size']:
                    # Set default values for numeric fields
                    if field.name == 'built_year':
                        property_data[field.name] = None
                    elif field.name == 'garages_count':
                        property_data[field.name] = None
                    elif field.name == 'garage_size':
                        property_data[field.name] = None
                    # print(f"Set default value for {field.name}: {property_data[field.name]}")
                elif field.name in ['latitude', 'longitude']:
                    # Skip empty lat/lng
                    # print(f"Skipping empty field: {field.name}")
                    continue
                else:
                    # For other empty strings, set to None
                    property_data[field.name] = None
                    # print(f"Set None for empty field: {field.name}")
            else:
                # Handle model instances (like Agent objects)
                if hasattr(value, '__class__') and value.__class__.__name__ in ['Agent', 'User', 'Organization']:
                    property_data[field.name] = value.id if value else None
                    # print(f"Converted {field.name} to ID: {property_data[field.name]}")
                else:
                    # Handle latitude/longitude decimal places
                    if field.name in ['latitude', 'longitude'] and isinstance(value, str):
                        try:
                            # Round to 6 decimal places
                            float_val = float(value)
                            rounded_val = round(float_val, 6)
                            property_data[field.name] = str(rounded_val)
                            # print(f"Rounded {field.name} to 6 decimal places: {property_data[field.name]}")
                        except (ValueError, TypeError):
                            property_data[field.name] = value
                    else:
                        property_data[field.name] = value
        
        # Add required fields that might be missing
        if 'description' not in property_data or not property_data['description']:
            property_data['description'] = f"Property in {property_data.get('city', 'Unknown location')}"
            # print(f"Added default description: {property_data['description']}")
        
        property_data['posted_by'] = request.user.id
        
        # Create a safe version for logging (without file objects and model instances)
        safe_property_data = {}
        for key, value in property_data.items():
            if hasattr(value, 'name') and hasattr(value, 'url'):
                # Handle file objects (ImageFieldFile, FileFieldFile)
                safe_property_data[key] = f"<File: {getattr(value, 'name', 'unknown')}>"
            elif hasattr(value, '__class__') and value.__class__.__name__ in ['Agent', 'User', 'Organization']:
                # Handle model instances
                safe_property_data[key] = f"<{value.__class__.__name__}: {getattr(value, 'id', 'unknown')}>"
            else:
                safe_property_data[key] = value
        
        # print(f"Final property_data: {safe_property_data}")
        
    except Exception as e:
        error_msg = f'Error preparing property data: {str(e)}'
        # print(f"ERROR: {error_msg}")
        logger.error(error_msg, exc_info=True)
        return Response({'error': error_msg}, status=500)
    
    # Validate and save property
    try:
        # print("Creating PropertySerializer...")
        serializer = PropertySerializer(data=property_data, context={'request': request})
        # print(f"Serializer initial data: {serializer.initial_data}")
        
        if serializer.is_valid():
            # print("Serializer is valid, saving property...")
            prop = serializer.save()
            # print(f"Property saved with ID: {prop.id}")
            
            # Handle subscription credits for addon features (after successful property creation)
            hide_address = property_data.get('hide_address', False)
            hide_contact = property_data.get('contact_details_hidden', False)
            
            if hide_address or hide_contact:
                # print(f"Processing credits for hide_address: {hide_address}, hide_contact: {hide_contact}")
                # Check for active subscription
                from users.models import Subscription
                from django.utils import timezone
                active_subscription = Subscription.objects.filter(
                    user=request.user,
                    expiry_date__gt=timezone.now()
                ).order_by('-subscription_date').first()
                
                if active_subscription:
                    # Get the original credit counts before any deduction
                    original_hide_address_count = active_subscription.hide_address_count
                    original_hide_contact_count = active_subscription.hide_contact_count
                    
                    # print(f"Original credits - hide_address: {original_hide_address_count}, hide_contact: {original_hide_contact_count}")
                    
                    # Determine which features used credits vs money
                    # If user has credits for a feature and the feature is enabled, they used credits
                    # If user has no credits for a feature and the feature is enabled, they paid money
                    credits_used = {
                        'hide_address': False,
                        'hide_contact': False
                    }
                    
                    if hide_address:
                        if original_hide_address_count > 0:
                            # User had credits, so they used credits for this feature
                            active_subscription.hide_address_count -= 1
                            credits_used['hide_address'] = True
                            # print(f"Used hide_address credit for user {request.user.email}. Remaining: {active_subscription.hide_address_count}")
                        else:
                            # User had no credits, so they paid money for this feature
                            print(f"User paid money for hide_address feature (no credits available)")
                    
                    if hide_contact:
                        if original_hide_contact_count > 0:
                            # User had credits, so they used credits for this feature
                            active_subscription.hide_contact_count -= 1
                            credits_used['hide_contact'] = True
                            # print(f"Used hide_contact credit for user {request.user.email}. Remaining: {active_subscription.hide_contact_count}")
                        else:
                            # User had no credits, so they paid money for this feature
                            print(f"User paid money for hide_contact feature (no credits available)")
                    
                    # Save the updated subscription
                    active_subscription.save()
                    # print(f"Credits used for user {request.user.email}: {credits_used}")
                else:
                    print(f"No active subscription found for user {request.user.email}")
            
            # Copy images
            try:
                # print(f"Copying {temp.images.count()} images...")
                for temp_img in temp.images.all():
                    # print(f"Processing image: {temp_img.image.name}")
                    img_instance = PropertyImage.objects.create(image=temp_img.image)
                    prop.featured_pictures.add(img_instance)
                    # print(f"Added image {img_instance.id} to property")
                
                # print("All images copied successfully")
            except Exception as e:
                error_msg = f'Error copying images: {str(e)}'
                # print(f"ERROR: {error_msg}")
                logger.error(error_msg, exc_info=True)
                # Don't fail the whole operation, just log the error
                # print("Continuing without images...")
            
            # Delete temp property
            try:
                temp.delete()
                # print("TempProperty deleted successfully")
            except Exception as e:
                error_msg = f'Error deleting TempProperty: {str(e)}'
                # print(f"ERROR: {error_msg}")
                logger.error(error_msg, exc_info=True)
                # Don't fail the whole operation, just log the error
            
            success_response = {'success': True, 'property_id': prop.id}
            return Response(success_response, status=200)
            
        else:
            error_msg = f'Serializer validation failed: {serializer.errors}'
            return Response({
                'error': 'Property creation failed due to validation errors',
                'details': serializer.errors,
                'debug_data': safe_property_data
            }, status=400)
            
    except Exception as e:
        error_msg = f'Unexpected error during property creation'
        logger.error(error_msg, exc_info=True)
        return Response({
            'error': 'Property creation failed due to unexpected error',
            'details': str(e),
            'debug_data': safe_property_data
        }, status=500)


from datetime import timedelta
from users.models import Subscription
import json

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def instant_boost_property(request):
    property_id = request.data.get('property_id')

    if not property_id:
        return Response({'error': 'Missing property_id.'}, status=400)

    try:
        prop = Property.objects.get(id=property_id)
    except Property.DoesNotExist:
        return Response({'error': 'Property not found.'}, status=404)

    user = request.user

    # Check if the user has an active subscription with boost_count > 0
    sub = Subscription.objects.filter(user=user, expiry_date__gt=timezone.now(), boost_count__gt=0).order_by('-expiry_date').first()
    if not sub:
        return Response({'error': 'No available boost in your subscription.'}, status=403)

    # Default boost duration (in hours)
    boost_duration = getattr(settings, "BOOST_DURATION_HOURS", 24)
    now = timezone.now()

    # Find existing boost, or create new
    boost, created = PropertyBoost.objects.get_or_create(
        property=prop, user=user,
        defaults={
            'boosted_at': now,
            'expires_at': now + timezone.timedelta(hours=boost_duration)
        }
    )
    if not created:
        # Extend boost: from now or previous expiry, whichever is later
        boost.boosted_at = now
        boost.expires_at = max(now, boost.expires_at) + timezone.timedelta(hours=boost_duration)
        boost.save()

    # Decrement boost_count
    sub.boost_count = max(sub.boost_count - 1, 0)
    sub.save(update_fields=["boost_count"])

    return Response({'success': True, 'expires_at': boost.expires_at})

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def check_addon_credit(request):
    """
    Check if user has credit for hide_address or contact_details_hidden.
    Expects: { 'hide_address': true/false, 'contact_details_hidden': true/false }
    """
    from users.models import Subscription
    from django.utils import timezone

    hide_address = request.data.get('hide_address', False)
    hide_contact = request.data.get('contact_details_hidden', False)
    user = request.user

    active_subscription = Subscription.objects.filter(
        user=user,
        expiry_date__gt=timezone.now()
    ).order_by('-subscription_date').first()

    result = {
        'hide_address': False,
        'contact_details_hidden': False
    }
    if active_subscription:
        if hide_address:
            result['hide_address'] = active_subscription.hide_address_count > 0
        if hide_contact:
            result['contact_details_hidden'] = active_subscription.hide_contact_count > 0

    return Response(result)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def finalize_addon_payment(request):
    """
    After payment, update the main property with the paid add-ons and delete the temp property.
    Expects: { 'property_id': int, 'temp_property_id': int, 'hide_address': true/false, 'contact_details_hidden': true/false }
    """
    property_id = request.data.get('property_id')
    temp_property_id = request.data.get('temp_property_id')
    hide_address = request.data.get('hide_address', False)
    hide_contact = request.data.get('contact_details_hidden', False)

    from .models import Property, TempProperty

    try:
        prop = Property.objects.get(id=property_id)
        temp = TempProperty.objects.get(id=temp_property_id, user=request.user)
    except (Property.DoesNotExist, TempProperty.DoesNotExist):
        return Response({'error': 'Property or TempProperty not found.'}, status=404)

    # Update only the paid fields
    if hide_address:
        prop.hide_address = temp.hide_address
    if hide_contact:
        prop.contact_details_hidden = temp.contact_details_hidden

    prop.save()
    temp.delete()
    return Response({'success': True})

# --- EDIT ADDON PAYMENT FLOW ---

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def edit_addon_payment(request):
    """
    Initiate PayPal payment for editing add-ons (hide_address/contact_details_hidden) on a property.
    Expects: { 'property_id': int, 'hide_address': bool, 'contact_details_hidden': bool }
    Returns: { 'approval_url': str, 'payment_session_id': str }
    """
    property_id = request.data.get('property_id')
    hide_address = request.data.get('hide_address', False)
    hide_contact = request.data.get('contact_details_hidden', False)
    user = request.user

    if not property_id:
        return Response({'error': 'Missing property_id.'}, status=400)

    # Calculate fee (reuse logic from calculate_property_addon_fee)
    fee_obj = PropertyAddonsFee.objects.first()
    hide_address_fee = float(fee_obj.hide_address_fee) if fee_obj else 1.99
    hide_contact_fee = float(fee_obj.hide_contact_fee) if fee_obj else 1.55
    combined_fee = float(fee_obj.hide_address_and_contact_combined_fee) if fee_obj else 2.99
    if hide_address and hide_contact:
        total_fee = combined_fee
    elif hide_address:
        total_fee = hide_address_fee
    elif hide_contact:
        total_fee = hide_contact_fee
    else:
        total_fee = 0.0
    if total_fee == 0.0:
        return Response({'error': 'No add-on selected for payment.'}, status=400)

    # PayPal payment creation
    from django.conf import settings
    import paypalrestsdk
    from decimal import Decimal, ROUND_HALF_UP
    paypalrestsdk.configure({
        "mode": settings.PAYPAL_MODE,
        "client_id": settings.PAYPAL_CLIENT_ID,
        "client_secret": settings.PAYPAL_CLIENT_SECRET,
    })
    final_price = str(Decimal(total_fee).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))
    currency = "EUR"
    payment_session_id = str(uuid4())
    payment = paypalrestsdk.Payment({
        "intent": "sale",
        "payer": {"payment_method": "paypal"},
        "redirect_urls": {
            "return_url": settings.PAYPAL_EDIT_ADDON_SUCCESS_URL + f"?session_id={payment_session_id}",
            "cancel_url": settings.PAYPAL_CANCEL_URL,
        },
        "transactions": [{
            "amount": {
                "total": final_price,
                "currency": currency,
            },
            "description": f"Edit Add-ons for Property {property_id}",
        }]
    })
    if payment.create():
        approval_url = next((link.href for link in payment.links if link.rel == "approval_url"), None)
        # Store session info in cache (5 min expiry)
        cache.set(f"edit_addon_payment:{payment_session_id}", {
            'user_id': user.id,
            'property_id': property_id,
            'hide_address': hide_address,
            'contact_details_hidden': hide_contact,
            'payment_id': payment.id,
            'status': 'pending',
        }, timeout=300)
        return Response({
            'approval_url': approval_url,
            'payment_session_id': payment_session_id
        })
    else:
        return Response({'error': 'Payment creation failed', 'details': payment.error}, status=400)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def confirm_edit_addon_payment(request):
    """
    Confirm PayPal payment for editing add-ons.
    Expects: { 'payment_session_id': str, 'paymentId': str, 'payerId': str }
    Updates cache status to 'confirmed' if successful.
    """
    payment_session_id = request.data.get('payment_session_id')
    payment_id = request.data.get('paymentId')
    payer_id = request.data.get('payerId')
    if not all([payment_session_id, payment_id, payer_id]):
        return Response({'error': 'Missing required fields.'}, status=400)
    session = cache.get(f"edit_addon_payment:{payment_session_id}")
    if not session or session.get('payment_id') != payment_id:
        return Response({'error': 'Invalid or expired payment session.'}, status=404)
    from django.conf import settings
    import paypalrestsdk
    paypalrestsdk.configure({
        "mode": settings.PAYPAL_MODE,
        "client_id": settings.PAYPAL_CLIENT_ID,
        "client_secret": settings.PAYPAL_CLIENT_SECRET,
    })
    try:
        payment = paypalrestsdk.Payment.find(payment_id)
        if payment.execute({"payer_id": payer_id}):
            session['status'] = 'confirmed'
            cache.set(f"edit_addon_payment:{payment_session_id}", session, timeout=300)
            return Response({'success': True})
        else:
            return Response({'error': 'Payment execution failed.'}, status=400)
    except Exception as e:
        return Response({'error': f'Payment verify error: {str(e)}'}, status=400)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def finalize_edit_addon_payment(request):
    """
    Finalize the edit add-on payment and update only the property add-on fields that were purchased, leaving the others unchanged.
    Expects: { 'payment_session_id': str }
    """
    payment_session_id = request.data.get('payment_session_id')
    if not payment_session_id:
        return Response({'error': 'Missing payment_session_id.'}, status=400)
    session = cache.get(f"edit_addon_payment:{payment_session_id}")
    if not session or session.get('status') != 'confirmed':
        return Response({'error': 'Payment not confirmed or session expired.'}, status=400)
    try:
        prop = Property.objects.get(id=session['property_id'])
        # Only update the add-on(s) that were purchased in this session
        from users.models import Subscription
        from django.utils import timezone
        updated_fields = []
        if session.get('hide_address'):
            prop.hide_address = True
            updated_fields.append('hide_address')
        if session.get('contact_details_hidden'):
            prop.contact_details_hidden = True
            updated_fields.append('contact_details_hidden')
        prop.save(update_fields=updated_fields)
        # Decrement subscription credits if used
        active_subscription = Subscription.objects.filter(
            user=request.user,
            expiry_date__gt=timezone.now()
        ).order_by('-subscription_date').first()
        if active_subscription:
            if session.get('hide_address') and active_subscription.hide_address_count > 0:
                active_subscription.hide_address_count -= 1
            if session.get('contact_details_hidden') and active_subscription.hide_contact_count > 0:
                active_subscription.hide_contact_count -= 1
            active_subscription.save()
        # Optionally, clear the cache
        cache.delete(f"edit_addon_payment:{payment_session_id}")
        return Response({'success': True, 'property_id': prop.id})
    except Property.DoesNotExist:
        return Response({'error': 'Property not found.'}, status=404)
