from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
from django.urls import reverse
from .models import (
    Package, ForeignerLead, ForeignerInterest, ForeignerProfile, ForeignerLead, FurniturePackage,
    UserPayableItem, WalletAccount, RefundableDeposit, MarketingResource, PaymentTransaction,
    PaymentTransactionItem,
)
from rental_app.models import RentalListing, RentalInterest
from dating_app.models import DatingInterest, DatingPartnerProfile
from service_partner_app.models import ServicePartnerInterest, ServicePartnerProfile
from .forms import (
    ForeignerLeadForm, ConsultationRequestForm, ContactMessageForm, ForeignerProfileEditForm, 
    ForeignerProfileImageForm, UsernameChangeForm, ForeignerInterestForm, ForeignerPasswordResetForm,
    WalletTopUpForm, GuestHostBookingSelectionForm
    
)
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden, JsonResponse
from django.utils import timezone
from django.contrib.auth import get_user_model, login, update_session_auth_hash
from django.db import transaction
from django.core.mail import send_mail
from django.conf import settings
from datetime import date
import re
import random
import string
from decimal import Decimal, InvalidOperation
from django.db.models import Sum, Q
from django.contrib.auth.forms import PasswordChangeForm
from django.views.decorators.http import require_POST
from common.choices import NATIONALITY_CHOICES, COUNTRY_CHOICES
from .utils import (
    send_account_credentials_email, 
    create_foreigner_default_payable_items, 
    get_platform_fee_settings, 
    update_foreigner_package_based_payable_items,
    update_foreigner_furniture_payable_items,
    update_foreigner_rental_payable_items,
    sync_foreigner_payable_items,
)
from django.contrib.auth import logout
from affiliates_app.utils import create_affiliate_referral_from_signup
from django.contrib.auth.views import (
    LoginView,
    PasswordResetView,
    PasswordResetDoneView,
    PasswordResetConfirmView,
    PasswordResetCompleteView,
)
from django.urls import reverse_lazy

from .email_services import (
    send_guest_signup_welcome_email, 
    send_foreigner_payment_invoice_email,
    send_guest_dating_interest_notification_email,
)
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from common.choices import SRI_LANKA_CITY_CHOICES, LANGUAGE_CHOICES
from django.db import models
from common.payment_gateway_services import (
    get_paypal_access_token,
    get_paypal_base_url,
    get_paypal_approval_url,
    capture_paypal_order,
)
from .utils import (
    user_can_topup_wallet,
    get_or_create_wallet_account,
    mark_foreigner_transaction_items_paid,

)

from hosting_app.models import (
    HostVenue,
    HostEventPackage,
    HostMealPlan,
    HostAddOnService,
    HostBookingRequest,
)

from hosting_app.models import (
    PublicListingStatus, 
    HostBookingPaymentStatus, 
    BookingRequestStatus,
)
from hosting_app.utils import create_or_update_guest_host_booking_order
import stripe

from django.conf import settings
import base64
import requests

User = get_user_model()

def create_paypal_order(payment_transaction, request):
    """
    Creates a PayPal order and returns PayPal response JSON.
    """
    access_token = get_paypal_access_token()
    base_url = get_paypal_base_url()

    create_order_url = f'{base_url}/v2/checkout/orders'

    return_url = request.build_absolute_uri(
        reverse(
            'expat_life:foreigner_paypal_payment_success',
            kwargs={'transaction_id': payment_transaction.id}
        )
    )

    cancel_url = request.build_absolute_uri(
        reverse(
            'expat_life:foreigner_payment_cancelled',
            kwargs={'transaction_id': payment_transaction.id}
        )
    )

    amount_value = payment_transaction.gateway_amount_usd.quantize(Decimal('0.01'))

    payload = {
        'intent': 'CAPTURE',
        'purchase_units': [
            {
                'reference_id': str(payment_transaction.id),
                'description': f'Guest Payment - Transaction #{payment_transaction.id}',
                'custom_id': str(payment_transaction.id),
                'amount': {
                    'currency_code': 'USD',
                    'value': str(amount_value),
                },
            }
        ],
        'application_context': {
            'brand_name': 'Ensolanka Live in Sri Lanka',
            'landing_page': 'BILLING',
            'user_action': 'PAY_NOW',
            'return_url': return_url,
            'cancel_url': cancel_url,
        },
    }

    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {access_token}',
        'PayPal-Request-Id': f'guest-payable-{payment_transaction.id}',
    }

    response = requests.post(
        create_order_url,
        json=payload,
        headers=headers,
        timeout=30,
    )

    if response.status_code not in [200, 201]:
        raise Exception(f"PayPal order creation failed: {response.text}")

    return response.json()

# Wallet top up

def complete_wallet_topup_transaction(payment_transaction, gateway_session_id='', gateway_transaction_id=''):
    """
    Completes a wallet top-up transaction safely.

    This function:
    - locks the PaymentTransaction
    - locks/creates the WalletAccount
    - credits the wallet
    - marks transaction as paid

    It prevents double wallet credit if the success URL is refreshed.
    """

    with transaction.atomic():
        locked_transaction = PaymentTransaction.objects.select_for_update().get(
            id=payment_transaction.id,
            user=payment_transaction.user,
            profile_type=payment_transaction.profile_type,
        )

        if locked_transaction.status == 'paid':
            return locked_transaction, False

        if locked_transaction.payment_purpose != 'wallet_topup':
            raise Exception("This transaction is not a wallet top-up transaction.")

        amount_to_credit = locked_transaction.gateway_amount_usd or Decimal('0.00')

        if amount_to_credit <= Decimal('0.00'):
            raise Exception("Invalid wallet top-up amount.")

        wallet, created = WalletAccount.objects.select_for_update().get_or_create(
            user=locked_transaction.user,
            profile_type=locked_transaction.profile_type,
            defaults={'balance_usd': Decimal('0.00')}
        )

        wallet.balance_usd = (wallet.balance_usd or Decimal('0.00')) + amount_to_credit
        wallet.save(update_fields=['balance_usd'])

        locked_transaction.gateway_session_id = gateway_session_id or locked_transaction.gateway_session_id
        locked_transaction.gateway_transaction_id = gateway_transaction_id or locked_transaction.gateway_transaction_id
        locked_transaction.total_amount_usd = amount_to_credit
        locked_transaction.gateway_amount_usd = amount_to_credit
        locked_transaction.wallet_deduction_usd = Decimal('0.00')
        locked_transaction.status = 'paid'
        locked_transaction.paid_at = timezone.now()
        locked_transaction.failure_reason = ''
        locked_transaction.save(update_fields=[
            'gateway_session_id',
            'gateway_transaction_id',
            'total_amount_usd',
            'gateway_amount_usd',
            'wallet_deduction_usd',
            'status',
            'paid_at',
            'failure_reason',
            'updated_at',
        ])

        return locked_transaction, True
    
#++++++++++++++++++

def create_paypal_wallet_topup_order(payment_transaction, request):
    access_token = get_paypal_access_token()
    base_url = get_paypal_base_url()

    create_order_url = f'{base_url}/v2/checkout/orders'

    return_url = request.build_absolute_uri(
        reverse(
            'expat_life:foreigner_wallet_topup_paypal_success',
            kwargs={'transaction_id': payment_transaction.id}
        )
    )

    cancel_url = request.build_absolute_uri(
        reverse(
            'expat_life:foreigner_wallet_topup_cancelled',
            kwargs={'transaction_id': payment_transaction.id}
        )
    )

    amount_value = payment_transaction.gateway_amount_usd.quantize(Decimal('0.01'))

    payload = {
        'intent': 'CAPTURE',
        'purchase_units': [
            {
                'reference_id': str(payment_transaction.id),
                'description': f'Guest Wallet Top-up - Transaction #{payment_transaction.id}',
                'custom_id': f'wallet_topup_{payment_transaction.id}',
                'amount': {
                    'currency_code': 'USD',
                    'value': str(amount_value),
                },
            }
        ],
        'application_context': {
            'brand_name': 'Ensolanka Live in Sri Lanka',
            'landing_page': 'BILLING',
            'user_action': 'PAY_NOW',
            'return_url': return_url,
            'cancel_url': cancel_url,
        },
    }

    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {access_token}',
        'PayPal-Request-Id': f'guest-wallet-topup-{payment_transaction.id}',
    }

    response = requests.post(
        create_order_url,
        json=payload,
        headers=headers,
        timeout=30,
    )

    if response.status_code not in [200, 201]:
        raise Exception(f"PayPal wallet top-up order creation failed: {response.text}")

    return response.json()

#====================================================================
#normal Views

def marketing_resources(request):
    selected_lang = request.GET.get('lang', 'all')
 
    resources = MarketingResource.objects.filter(is_active=True)
 
    if selected_lang and selected_lang != 'all':
        resources = resources.filter(language=selected_lang)
 
    return render(request, 'expat_life/info_center.html', {
        'resources': resources,
        'selected_lang': selected_lang,
        'language_choices': LANGUAGE_CHOICES,
    })

def terms_page(request):
    return render(request, 'expat_life/terms.html')

def faq_page(request):
    return render(request, 'expat_life/faq.html')
    
def privacy_policy_page(request):
    return render(request, 'expat_life/privacy_policy.html')

def disclaimer_page(request):
    return render(request, 'expat_life/disclaimer.html')

def refund_payment_policy_page(request):
    return render(request, 'expat_life/refund_payment_policy.html')

def cookie_policy_page(request):
    return render(request, 'expat_life/cookie_policy.html')

class ForeignerPasswordResetView(PasswordResetView):
    template_name = 'registration/foreigner_password_reset.html'

    form_class = ForeignerPasswordResetForm

    email_template_name = 'emails/expat_life/password_reset_email.txt'
    html_email_template_name = 'emails/expat_life/password_reset_email.html'
    subject_template_name = 'emails/expat_life/password_reset_subject.txt'

    success_url = reverse_lazy('expat_life:foreigner_password_reset_done')
    from_email = "Live in Sri Lanka <dsjayathunge@gmail.com>" 

    def get_extra_email_context(self):
        return {
            "site_url": self.request.build_absolute_uri("/"),
        }

    def form_valid(self, form):
        self.extra_email_context = self.get_extra_email_context()

        email = form.cleaned_data.get('email')

        user_exists_as_foreigner = User.objects.filter(
            email__iexact=email,
            foreigner_profile__isnull=False,
            is_active=True
        ).exists()

        if not user_exists_as_foreigner:
            messages.warning(
                self.request,
                "If this email belongs to a registered guest account, password reset instructions will be sent."
            )

        return super().form_valid(form)


class ForeignerPasswordResetDoneView(PasswordResetDoneView):
    template_name = 'registration/foreigner_password_reset_done.html'


class ForeignerPasswordResetConfirmView(PasswordResetConfirmView):
    template_name = 'registration/foreigner_password_reset_confirm.html'
    success_url = reverse_lazy('expat_life:foreigner_password_reset_complete')


class ForeignerPasswordResetCompleteView(PasswordResetCompleteView):
    template_name = 'registration/foreigner_password_reset_complete.html'


@require_POST
def smart_logout(request):
    redirect_url = 'expat_life:home'

    user = request.user

    if user.is_authenticated:
        if hasattr(user, 'property_manager_client_profile'):
            redirect_url = 'property_manager_app:home_property_manager'

        elif hasattr(user, 'rental_owner_profile'):
            redirect_url = 'rental_app:home_rental'

        elif hasattr(user, 'dating_profile'):
            redirect_url = 'dating_app:home_dating'

        elif hasattr(user, 'service_partner_profile'):
            redirect_url = 'service_partner_app:home_service_partner'

        elif hasattr(user, 'affiliate_profile'):
            redirect_url = 'affiliates_app:home_affiliates'

        elif hasattr(user, 'host_profile'):
            redirect_url = 'hosting_app:home_hosting'

        elif hasattr(user, 'hosting_client_profile'):
            redirect_url = 'hosting_app:home_hosting'

        elif hasattr(user, 'foreigner_profile'):
            redirect_url = 'expat_life:home'

    logout(request)

    return redirect(redirect_url)

class ForeignerLoginView(LoginView):
    template_name = 'registration/foreigner_login.html'

    def form_valid(self, form):
        response = super().form_valid(form)
        user = self.request.user

        foreigner_profile = getattr(user, 'foreigner_profile', None)
        if foreigner_profile:
            return response

        messages.warning(
            self.request,
            "This login page is only for foreigner accounts. Please use the correct login area for your account type."
        )

        logout(self.request)

        if hasattr(user, 'rental_owner_profile'):
            return redirect('rental_app:rental_owner_login')
        elif hasattr(user, 'dating_profile'):
            return redirect('dating_app:dating_partner_login')
        elif hasattr(user, 'service_partner_profile'):
            return redirect('service_partner_app:service_partner_login')

        return redirect('expat_life:home')

    def get_success_url(self):
        return self.get_redirect_url() or reverse('expat_life:foreigner_dashboard')


def generate_username_from_name(full_name):
    base_name = re.sub(r'[^a-zA-Z0-9]', '', full_name.lower())
    if not base_name:
        base_name = 'foreigner'

    base = f"fr_{base_name}"
    username = base
    counter = 1

    while User.objects.filter(username=username).exists():
        username = f"{base}{counter}"
        counter += 1

    return username


def generate_random_password(length=10):
    chars = string.ascii_letters + string.digits
    return ''.join(random.choice(chars) for _ in range(length))


@transaction.atomic
def foreigner_signup(request):
    if request.method == 'POST':
        form = ForeignerLeadForm(request.POST)

        if form.is_valid():
            lead = form.save(commit=False)

            email = form.cleaned_data['email'].strip().lower()
            full_name = form.cleaned_data['full_name'].strip()

            existing_user = User.objects.filter(email__iexact=email).first()
            if existing_user:
                form.add_error('email', 'An account with this email already exists.')
            else:
                username = generate_username_from_name(full_name)
                password = generate_random_password()

                lead.email = email
                lead.save()

                name_parts = full_name.split()
                first_name = name_parts[0] if name_parts else ''
                last_name = ' '.join(name_parts[1:]) if len(name_parts) > 1 else ''

                user = User.objects.create_user(
                    username=username,
                    email=email,
                    password=password,
                    first_name=first_name,
                    last_name=last_name
                )

                foreigner_profile = ForeignerProfile.objects.create(
                    user=user,
                    lead=lead,
                    is_confirmed=lead.is_confirmed_foreigner,
                    can_view_private_listings=False,
                    can_book_arrangements=False,
                    status='approved',
                    is_public=lead.is_public,
                )

                create_foreigner_default_payable_items(user=user, lead=lead)

                # --- Affiliate referral linking ---
                create_affiliate_referral_from_signup(
                    request,
                    user=user,
                    lead=lead,
                    profile=foreigner_profile,
                )
                # ----------------------------------

                transaction.on_commit(
                    lambda: send_guest_signup_welcome_email(
                        user=user,
                        full_name=full_name,
                        email=email,
                        username=username,
                        temporary_password=password,
                        request=request,
                    )
                )

                login(request, user)

                request.session['new_account_username'] = username
                request.session['new_account_password'] = password
                request.session['new_account_email'] = email
                request.session['account_role'] = 'Guest'
                request.session['just_signed_up'] = True

                messages.success(request, "Your signup was submitted successfully.")
                return redirect('expat_life:foreigner_dashboard')
        else:
            messages.error(request, "Please correct the errors below and try again.")
    else:
        form = ForeignerLeadForm()

    return render(request, 'expat_life/foreigner_signup.html', {'form': form})


def home(request):
    featured_packages = Package.objects.filter(is_active=True, is_featured=True).order_by('order')
    all_packages = Package.objects.filter(is_active=True).order_by('order')

    foreigner_profile = None
    if request.user.is_authenticated:
        foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    return render(request, 'expat_life/home.html', {
        'featured_packages': featured_packages,
        'all_packages': all_packages,
        'foreigner_profile': foreigner_profile,
    })


def about_us(request):
    return render(request, 'expat_life/about.html')

def about_sri_lanka(request):
    return render(request, 'expat_life/about_sri_lanka.html')


def package_list(request):
    packages = Package.objects.filter(is_active=True).order_by('order')

    foreigner_profile = None
    lead = None
    selected_package_id = None
    is_foreigner_user = False

    if request.user.is_authenticated:
        foreigner_profile = getattr(request.user, 'foreigner_profile', None)
        if foreigner_profile:
            is_foreigner_user = True
            lead = getattr(foreigner_profile, 'lead', None)
            if lead and lead.interested_package_id:
                selected_package_id = lead.interested_package_id

    return render(request, 'expat_life/package_list.html', {
        'packages': packages,
        'foreigner_profile': foreigner_profile,
        'lead': lead,
        'is_foreigner_user': is_foreigner_user,
        'selected_package_id': selected_package_id,
    })


def package_detail(request, slug):
    package = get_object_or_404(Package, slug=slug, is_active=True)

    lead = None
    already_selected = False

    if request.user.is_authenticated:
        profile = getattr(request.user, 'foreigner_profile', None)
        if profile and profile.lead:
            lead = profile.lead
            already_selected = (lead.interested_package_id == package.id)

    return render(request, 'expat_life/package_detail.html', {
        'package': package,
        'lead': lead,
        'already_selected': already_selected,
    })

@login_required
def select_package(request, slug):
    if request.method != 'POST':
        return redirect('expat_life:package_detail', slug=slug)

    package = get_object_or_404(Package, slug=slug, is_active=True)

    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile or not profile.lead:
        messages.error(request, "You need a foreigner account before selecting a package.")
        return redirect('expat_life:foreigner_signup')

    lead = profile.lead

    # Once locked, lifestyle package should not be changed directly
    if profile.is_main_package_locked:
        messages.error(
            request,
            "You cannot change the lifestyle package because your main package is already locked after service activation."
        )

        if lead.interested_package:
            return redirect('expat_life:package_detail', slug=lead.interested_package.slug)

        return redirect('expat_life:package_detail', slug=slug)

    lead.interested_package = package
    lead.save(update_fields=['interested_package'])

    update_foreigner_package_based_payable_items(request.user, lead)

    messages.success(
        request,
        f"{package.name} has been selected as your current package. Related payable fees were updated."
    )
    return redirect('expat_life:package_detail', slug=package.slug)



def consultation_request(request):
    if request.method == 'POST':
        form = ConsultationRequestForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect(
                reverse('expat_life:success_page') +
                '?type=consultation'
            )
    else:
        form = ConsultationRequestForm()
    return render(request, 'expat_life/consultation_request.html', {'form': form})


def contact_page(request):
    if request.method == 'POST':
        form = ContactMessageForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect(
                reverse('expat_life:success_page') +
                '?type=contact'
            )
    else:
        form = ContactMessageForm()
    return render(request, 'expat_life/contact_page.html', {'form': form})



def success_page(request):
    success_type = request.GET.get('type', 'general')

    page_data = {
        'general': {
            'title': 'Thank You',
            'heading': 'Thank You for Reaching Out',
            'message': 'Your submission has been received successfully.',
            'button_1_text': 'Go to Home',
            'button_1_url': 'expat_life:home',
            'button_2_text': 'View Packages',
            'button_2_url': 'expat_life:package_list',
        },
        'signup': {
            'title': 'Signup Submitted',
            'heading': 'Your Free Signup Has Been Submitted',
            'message': 'Thank you for sharing your details. We have received your information successfully and created your account.',
            'button_1_text': 'View Packages',
            'button_1_url': 'expat_life:package_list',
            'button_2_text': 'Book Consultation',
            'button_2_url': 'expat_life:consultation_request',
        },
        'consultation': {
            'title': 'Consultation Requested',
            'heading': 'Your Consultation Request Has Been Submitted',
            'message': 'Thank you. Your consultation request has been received. We can now review your request and discuss the most suitable next step.',
            'button_1_text': 'View Packages',
            'button_1_url': 'expat_life:package_list',
            'button_2_text': 'Contact Us',
            'button_2_url': 'expat_life:contact_page',
        },
        'contact': {
            'title': 'Message Sent',
            'heading': 'Your Message Has Been Sent Successfully',
            'message': 'Thank you for contacting us. We have received your message and will review it as soon as possible.',
            'button_1_text': 'Go to Home',
            'button_1_url': 'expat_life:home',
            'button_2_text': 'View Packages',
            'button_2_url': 'expat_life:package_list',
        },
    }

    context = page_data.get(success_type, page_data['general']).copy()

    context['signup_type'] = success_type
    context['username'] = request.session.pop('new_account_username', None)
    context['password'] = request.session.pop('new_account_password', None)
    context['new_account_email'] = request.session.pop('new_account_email', None)
    context['account_role'] = request.session.pop('account_role', None)

    return render(request, 'expat_life/success_page.html', context)

@login_required
def foreigner_dashboard(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile:
        return HttpResponseForbidden("You do not have a guest profile.")

    # --- NEW: get or create the foreigner wallet ---
    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='foreigner',
        defaults={'balance_usd': 0}   # not strictly needed because default=0, but explicit
    )

    lead = profile.lead

    default_profile_image = 'expat_life/images/default-profile-neutral.png'

    if lead and lead.gender:
        if lead.gender == 'male':
            default_profile_image = 'expat_life/images/default-profile-male.png'
        elif lead.gender == 'female':
            default_profile_image = 'expat_life/images/default-profile-female.png'
        else:
            default_profile_image = 'expat_life/images/default-profile-neutral.png'

    current_host_booking = HostBookingRequest.objects.filter(
        booked_by_user=request.user,
        guest_profile=profile,
        payment_status__in=[
            HostBookingPaymentStatus.UNPAID,
            HostBookingPaymentStatus.DUE,
        ],
    ).exclude(
        status__in=[
            BookingRequestStatus.PAID,
            BookingRequestStatus.COMPLETED,
            BookingRequestStatus.CANCELLED,
            BookingRequestStatus.REJECTED,
        ]
    ).order_by('-submitted_at').first()

    context = {
        'profile': profile,
        'lead': lead,
        'wallet': wallet,  
        'default_profile_image': default_profile_image,
        'consultations': lead.consultations.all() if lead else [],
        'just_signed_up': request.session.pop('just_signed_up', False),
        'username': request.session.pop('new_account_username', None),
        'password': request.session.pop('new_account_password', None),
        'new_account_email': request.session.pop('new_account_email', None),
        'account_role': request.session.pop('account_role', None),
        'current_host_booking': current_host_booking,
    }
    return render(request, 'expat_life/dashboard/foreigner_dashboard.html', context)


from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden
from django.shortcuts import render


@login_required
def foreigner_profile_page(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    lead = getattr(profile, 'lead', None)

    # Default image logic based on gender
    default_image = 'expat_life/images/default-profile-neutral.png'

    if lead and lead.gender:
        if lead.gender == 'male':
            default_image = 'expat_life/images/default-profile-male.png'
        elif lead.gender == 'female':
            default_image = 'expat_life/images/default-profile-female.png'
        else:
            default_image = 'expat_life/images/default-profile-neutral.png'

    return render(request, 'expat_life/dashboard/foreigner_profile.html', {
        'profile': profile,
        'lead': lead,
        'default_profile_image': default_image,
    })

@login_required
def edit_foreigner_profile(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    if request.method == 'POST':
        form = ForeignerProfileEditForm(request.POST, instance=profile)
        if form.is_valid():
            form.save()
            messages.success(request, "Profile updated successfully.")
            return redirect('expat_life:foreigner_profile_page')
    else:
        form = ForeignerProfileEditForm(instance=profile)

    return render(request, 'expat_life/dashboard/edit_foreigner_profile.html', {
        'form': form,
        'profile': profile,
    })


@login_required
@require_POST
def upload_foreigner_profile_image(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile:
        return JsonResponse({
            'success': False,
            'error': 'Foreigner profile not found.'
        }, status=403)

    if 'profile_image' not in request.FILES:
        return JsonResponse({
            'success': False,
            'error': 'No image was uploaded.'
        }, status=400)

    form = ForeignerProfileImageForm(request.POST, request.FILES, instance=profile)

    if form.is_valid():
        form.save()
        profile.refresh_from_db()

        image_url = profile.profile_image.url if profile.profile_image else ''
        return JsonResponse({
            'success': True,
            'image_url': image_url,
            'message': 'Profile image updated successfully.'
        })

    error_message = "Invalid image upload."
    if form.errors.get('profile_image'):
        error_message = form.errors['profile_image'][0]

    return JsonResponse({
        'success': False,
        'error': error_message
    }, status=400)


@login_required
def change_foreigner_username(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    if request.method == 'POST':
        form = UsernameChangeForm(request.POST, instance=request.user, user=request.user)
        if form.is_valid():
            form.save()
            messages.success(request, "Username updated successfully.")
            return redirect('expat_life:foreigner_profile_page')
    else:
        form = UsernameChangeForm(instance=request.user, user=request.user)

    return render(request, 'expat_life/dashboard/change_foreigner_username.html', {
        'form': form,
        'profile': profile,
    })


@login_required
def change_foreigner_password(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        if form.is_valid():
            user = form.save()
            update_session_auth_hash(request, user)
            messages.success(request, "Password changed successfully.")
            return redirect('expat_life:foreigner_profile_page')
    else:
        form = PasswordChangeForm(request.user)

    return render(request, 'expat_life/dashboard/change_foreigner_password.html', {
        'form': form,
        'profile': profile,
    })


@login_required
def private_listings(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    if not profile.is_confirmed or not profile.can_view_private_listings:
        return render(request, 'expat_life/dashboard/access_pending.html', {
            'profile': profile
        })

    return render(request, 'expat_life/dashboard/private_listings.html', {
        'profile': profile
    })

def sri_lanka_digital_nomad_visa(request):
    return render(request, 'expat_life/sri_lanka_digital_nomad_visa.html')

"""
def foreigners_home(request):
    dating_profile = getattr(request.user, 'dating_profile', None)

    show_all_featured_foreigners = False

    if request.user.is_authenticated and dating_profile:
        show_all_featured_foreigners = (
            dating_profile.status == 'approved'
            and dating_profile.is_public is True
        )

    if show_all_featured_foreigners:
        base_profiles = ForeignerProfile.objects.filter(
            status='approved',
            is_featured=True
        ).select_related('lead', 'user')
    else:
        base_profiles = ForeignerProfile.objects.filter(
            status='approved',
            is_public=True,
            is_featured=True
        ).select_related('lead', 'user')

    featured_profiles = base_profiles.order_by('-joined_at')[:6]
    latest_profiles = base_profiles.order_by('-joined_at')[:25]

    context = {
        'featured_profiles': featured_profiles,
        'latest_profiles': latest_profiles,
    }
    return render(request, 'expat_life/foreigners_home.html', context)
"""
def rental_home(request):
    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    show_all_featured_listings = False

    if request.user.is_authenticated and foreigner_profile:
        lead_confirmed = bool(
            foreigner_profile.lead and foreigner_profile.lead.is_confirmed_foreigner
        )

        show_all_featured_listings = (
            foreigner_profile.status == 'approved'
            and foreigner_profile.is_confirmed is True
            and foreigner_profile.can_view_private_listings is True
            and lead_confirmed is True
        )

    if show_all_featured_listings:
        base_listings = RentalListing.objects.filter(
            is_approved=True,
            is_active=True,
            is_available=True,
            is_featured=True
        )
    else:
        base_listings = RentalListing.objects.filter(
            is_approved=True,
            is_active=True,
            is_available=True,
            visibility='public',
            is_featured=True
        )

    featured_properties = base_listings.prefetch_related('images').order_by('-created_at')[:6]
    latest_properties = base_listings.prefetch_related('images').order_by('-created_at')[:8]

    return render(request, 'expat_life/rental_home.html', {
        'featured_properties': featured_properties,
        'latest_properties': latest_properties,
    })

def public_rental_list(request):
    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    is_foreigner_authenticated = False
    is_confirmed_foreigner = False
    can_view_private_listings = False
    can_notify_interest = False
    show_all_active_listings = False

    if request.user.is_authenticated and foreigner_profile:
        is_foreigner_authenticated = True
        is_confirmed_foreigner = foreigner_profile.is_confirmed
        can_view_private_listings = (
            foreigner_profile.is_confirmed and foreigner_profile.can_view_private_listings
        )
        can_notify_interest = (
            foreigner_profile.is_confirmed and foreigner_profile.can_book_arrangements
        )

        lead_confirmed = bool(
            foreigner_profile.lead and foreigner_profile.lead.is_confirmed_foreigner
        )

        show_all_active_listings = (
            foreigner_profile.status == 'approved'
            and foreigner_profile.is_confirmed is True
            and foreigner_profile.can_view_private_listings is True
            and lead_confirmed is True
        )

    if show_all_active_listings:
        listings = RentalListing.objects.filter(
            is_approved=True,
            is_active=True,
            is_available=True,
        )
    else:
        if is_foreigner_authenticated:
            listings = RentalListing.objects.filter(
                is_approved=True,
                is_active=True,
                is_available=True,
                visibility='public'
            )
        else:
            listings = RentalListing.objects.filter(
                is_approved=True,
                is_active=True,
                is_available=True,
                visibility='public',
                is_featured=True
            )

    # Filters
    city = request.GET.get('city', '').strip()
    property_type = request.GET.get('property_type', '').strip()
    furnishing = request.GET.get('furnishing', '').strip()
    bedrooms = request.GET.get('bedrooms', '').strip()
    min_rent = request.GET.get('min_rent', '').strip()
    max_rent = request.GET.get('max_rent', '').strip()

    has_wifi = request.GET.get('has_wifi')
    has_ac = request.GET.get('has_ac')
    has_kitchen = request.GET.get('has_kitchen')
    has_parking = request.GET.get('has_parking')
    near_beach = request.GET.get('near_beach')
    suitable_for_remote_work = request.GET.get('suitable_for_remote_work')

    if city:
        listings = listings.filter(city=city)

    if property_type:
        listings = listings.filter(property_type=property_type)

    if furnishing:
        listings = listings.filter(furnishing=furnishing)

    if bedrooms:
        try:
            listings = listings.filter(bedrooms__gte=int(bedrooms))
        except ValueError:
            pass

    if min_rent:
        try:
            listings = listings.filter(monthly_rent_usd__gte=min_rent)
        except ValueError:
            pass

    if max_rent:
        try:
            listings = listings.filter(monthly_rent_usd__lte=max_rent)
        except ValueError:
            pass

    if has_wifi:
        listings = listings.filter(has_wifi=True)
    if has_ac:
        listings = listings.filter(has_ac=True)
    if has_kitchen:
        listings = listings.filter(has_kitchen=True)
    if has_parking:
        listings = listings.filter(has_parking=True)
    if near_beach:
        listings = listings.filter(near_beach=True)
    if suitable_for_remote_work:
        listings = listings.filter(suitable_for_remote_work=True)

    listings = listings.prefetch_related('images').order_by('-is_featured', '-created_at')

    # Pagination
    paginator = Paginator(listings, 12)  # 12 items per page
    page_number = request.GET.get('page')

    try:
        page_obj = paginator.page(page_number)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)

    # Keep current filters in pagination links, but remove "page"
    query_params = request.GET.copy()
    if 'page' in query_params:
        query_params.pop('page')
    query_string = query_params.urlencode()

    context = {
        'listings': page_obj,   # keep template compatibility
        'page_obj': page_obj,
        'paginator': paginator,

        'is_foreigner_authenticated': is_foreigner_authenticated,
        'is_confirmed_foreigner': is_confirmed_foreigner,
        'can_view_private_listings': can_view_private_listings,
        'can_notify_interest': can_notify_interest,

        'selected_city': city,
        'selected_property_type': property_type,
        'selected_furnishing': furnishing,
        'selected_bedrooms': bedrooms,
        'selected_min_rent': min_rent,
        'selected_max_rent': max_rent,

        'property_type_choices': RentalListing.PROPERTY_TYPE_CHOICES,
        'furnishing_choices': RentalListing.FURNISHING_CHOICES,
        'city_choices': SRI_LANKA_CITY_CHOICES,

        'query_string': query_string,
        'total_results': paginator.count,
    }
    return render(request, 'expat_life/public_rental_list.html', context)

@login_required
def rental_detail(request, slug):
    listing = get_object_or_404(
        RentalListing.objects.prefetch_related('images'),
        slug=slug,
        is_approved=True,
        is_active=True,
        is_available=True
    )

    foreigner_profile = None
    is_foreigner_authenticated = False
    is_confirmed_foreigner = False
    can_view_private_listings = False
    can_notify_interest = False
    existing_interest = None
    is_final_selected = False

    if request.user.is_authenticated:
        foreigner_profile = getattr(request.user, 'foreigner_profile', None)

        if not foreigner_profile:
            messages.warning(
                request,
                "Only registered foreigner users can view rental property details."
            )

            if hasattr(request.user, 'rental_owner_profile'):
                return redirect('rental_app:rental_owner_dashboard')
            elif hasattr(request.user, 'dating_profile'):
                return redirect('dating_app:dating_partner_dashboard')
            elif hasattr(request.user, 'service_partner_profile'):
                return redirect('service_partner_app:service_partner_dashboard')

            return redirect('expat_life:home')

        if foreigner_profile.status != 'approved':
            messages.warning(
                request,
                "Your foreigner profile is not approved yet, so property details are not available."
            )
            return redirect('expat_life:foreigner_dashboard')

        is_foreigner_authenticated = True
        is_confirmed_foreigner = foreigner_profile.is_confirmed
        can_view_private_listings = (
            foreigner_profile.is_confirmed and foreigner_profile.can_view_private_listings
        )
        can_notify_interest = (
            foreigner_profile.is_confirmed and foreigner_profile.can_book_arrangements
        )

    if not is_foreigner_authenticated:
        messages.warning(request, "Please sign up as a foreigner to view property details.")
        return redirect('expat_life:foreigner_signup')

    if listing.visibility == 'private' and not can_view_private_listings:
        messages.warning(request, "This property is available only to confirmed foreigners with private access.")
        return redirect('expat_life:public_rental_list')

    if foreigner_profile:
        existing_interest = listing.rental_interests.filter(foreigner=foreigner_profile).first()

        lead = getattr(foreigner_profile, 'lead', None)
        if lead and lead.final_rental_property_id == listing.id:
            is_final_selected = True

    return render(request, 'expat_life/rental_detail.html', {
        'listing': listing,
        'all_images': listing.images.all(),
        'is_foreigner_authenticated': is_foreigner_authenticated,
        'is_confirmed_foreigner': is_confirmed_foreigner,
        'can_view_private_listings': can_view_private_listings,
        'can_notify_interest': can_notify_interest,
        'existing_interest': existing_interest,
        'is_final_selected': is_final_selected,
    })

def dating_home(request):
    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    show_all_approved_profiles = False

    if request.user.is_authenticated and foreigner_profile:
        lead_confirmed = bool(
            foreigner_profile.lead and foreigner_profile.lead.is_confirmed_foreigner
        )

        show_all_approved_profiles = (
            foreigner_profile.status == 'approved'
            and foreigner_profile.is_confirmed is True
            and foreigner_profile.can_view_private_listings is True
            and lead_confirmed is True
        )

    if show_all_approved_profiles:
        base_profiles = DatingPartnerProfile.objects.filter(
            status='approved',
            is_featured=True
        )
    else:
        base_profiles = DatingPartnerProfile.objects.filter(
            status='approved',
            is_public=True,
            is_featured=True
        )

    featured_profiles = base_profiles.order_by('-created_at')[:6]
    latest_profiles = base_profiles.order_by('-created_at')[:25]

    context = {
        'featured_profiles': featured_profiles,
        'latest_profiles': latest_profiles,
    }
    return render(request, 'expat_life/dating_home.html', context)


def public_partner_list(request):
    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    show_all_approved_profiles = False

    if request.user.is_authenticated and foreigner_profile:
        lead_confirmed = bool(
            foreigner_profile.lead and foreigner_profile.lead.is_confirmed_foreigner
        )

        show_all_approved_profiles = (
            foreigner_profile.status == 'approved'
            and foreigner_profile.is_confirmed is True
            and foreigner_profile.can_view_private_listings is True
            and lead_confirmed is True
        )

    if show_all_approved_profiles:
        profiles = DatingPartnerProfile.objects.filter(
            status='approved'
        )
    else:
        if request.user.is_authenticated:
            profiles = DatingPartnerProfile.objects.filter(
                status='approved',
                is_public=True
            )
        else:
            profiles = DatingPartnerProfile.objects.filter(
                status='approved',
                is_public=True,
                is_featured=True
            )

    gender = request.GET.get('gender', '').strip()
    goal = request.GET.get('goal', '').strip()
    city = request.GET.get('city', '').strip()

    if gender:
        profiles = profiles.filter(gender=gender)

    if goal:
        profiles = profiles.filter(relationship_goal=goal)

    if city:
        profiles = profiles.filter(city__icontains=city)

    profiles = profiles.order_by('-is_featured', '-created_at')

    # Pagination
    paginator = Paginator(profiles, 9)  # 9 profiles per page
    page_number = request.GET.get('page')

    try:
        page_obj = paginator.page(page_number)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)

    # Keep filters while moving between pages
    query_params = request.GET.copy()
    if 'page' in query_params:
        query_params.pop('page')
    query_string = query_params.urlencode()

    context = {
        'profiles': page_obj,
        'page_obj': page_obj,
        'paginator': paginator,
        'total_results': paginator.count,
        'query_string': query_string,

        'selected_gender': gender,
        'selected_goal': goal,
        'selected_city': city,
    }
    return render(request, 'expat_life/public_partner_list.html', context)

@login_required
def public_partner_detail(request, pk):
    foreigner_profile = None
    is_foreigner_authenticated = False
    is_confirmed_foreigner = False
    can_view_private_listings = False
    can_notify_interest = False
    existing_interest = None
    interest_is_active = False
    interest_is_withdrawn = False

    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    if not foreigner_profile:
        messages.warning(
            request,
            "Only registered foreigner users can view dating partner profile details."
        )

        if hasattr(request.user, 'rental_owner_profile'):
            return redirect('rental_app:rental_owner_dashboard')
        elif hasattr(request.user, 'dating_profile'):
            return redirect('dating_app:dating_partner_dashboard')
        elif hasattr(request.user, 'service_partner_profile'):
            return redirect('service_partner_app:service_partner_dashboard')

        return redirect('expat_life:home')
    


    if foreigner_profile.status != 'approved':
        messages.warning(
            request,
            "Your foreigner profile is not approved yet, so dating partner details are not available."
        )
        return redirect('expat_life:foreigner_dashboard')

    if request.user.is_authenticated:
        if foreigner_profile:
            if foreigner_profile.status != 'approved':
                messages.warning(
                    request,
                    "Your foreigner profile is not approved yet, so property details are not available."
                )
                return redirect('expat_life:foreigner_dashboard')
            is_foreigner_authenticated = True
            is_confirmed_foreigner = foreigner_profile.is_confirmed
            can_view_private_listings = (
                foreigner_profile.is_confirmed and foreigner_profile.can_view_private_listings
            )
            can_notify_interest = (
                foreigner_profile.is_confirmed and foreigner_profile.can_book_arrangements
            )

    if not is_foreigner_authenticated:
        messages.warning(request, "Please sign up as a foreigner to view property details.")
        return redirect('expat_life:foreigner_signup')


    profile = get_object_or_404(
        DatingPartnerProfile,
        pk=pk,
        status='approved',
    )

    additional_photos = profile.additional_photos.filter(
        status='approved',
        is_public=True
    ).order_by('display_order', '-uploaded_at')

    if foreigner_profile:
        existing_interest = profile.dating_interests.filter(
            foreigner=foreigner_profile
        ).first()

    if existing_interest:
        interest_is_active = existing_interest.status not in ['withdrawn', 'closed']
        interest_is_withdrawn = existing_interest.status == 'withdrawn'

    return render(request, 'expat_life/public_partner_detail.html', {
        'profile': profile,
        'additional_photos': additional_photos,
        'is_foreigner_authenticated': is_foreigner_authenticated,
        'is_confirmed_foreigner': is_confirmed_foreigner,
        'can_view_private_listings': can_view_private_listings,
        'can_notify_interest': can_notify_interest,
        'existing_interest': existing_interest,
        'interest_is_active': interest_is_active,
        'interest_is_withdrawn': interest_is_withdrawn,
    })

def service_partner_home(request):
    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    show_all_featured_profiles = False

    if request.user.is_authenticated and foreigner_profile:
        lead_confirmed = bool(
            foreigner_profile.lead and foreigner_profile.lead.is_confirmed_foreigner
        )

        show_all_featured_profiles = (
            foreigner_profile.status == 'approved'
            and foreigner_profile.is_confirmed is True
            and foreigner_profile.can_view_private_listings is True
            and lead_confirmed is True
        )

    if show_all_featured_profiles:
        base_profiles = ServicePartnerProfile.objects.filter(
            status='approved',
            is_featured=True
        )
    else:
        base_profiles = ServicePartnerProfile.objects.filter(
            status='approved',
            is_public=True,
            is_featured=True
        )

    featured_profiles = base_profiles.order_by('-created_at')[:6]
    latest_profiles = base_profiles.order_by('-created_at')[:8]

    return render(request, 'expat_life/service_partner_home.html', {
        'featured_profiles': featured_profiles,
        'latest_profiles': latest_profiles,
    })

def public_assistant_list(request):
    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    is_foreigner_authenticated = False
    is_confirmed_foreigner = False
    can_view_private_listings = False
    can_notify_interest = False
    show_all_approved_profiles = False

    if request.user.is_authenticated and foreigner_profile:
        is_foreigner_authenticated = True
        is_confirmed_foreigner = foreigner_profile.is_confirmed
        can_view_private_listings = (
            foreigner_profile.is_confirmed and foreigner_profile.can_view_private_listings
        )
        can_notify_interest = (
            foreigner_profile.is_confirmed and foreigner_profile.can_book_arrangements
        )

        lead_confirmed = bool(
            foreigner_profile.lead and foreigner_profile.lead.is_confirmed_foreigner
        )

        show_all_approved_profiles = (
            foreigner_profile.status == 'approved'
            and foreigner_profile.is_confirmed is True
            and foreigner_profile.can_view_private_listings is True
            and lead_confirmed is True
        )

    if show_all_approved_profiles:
        profiles = ServicePartnerProfile.objects.filter(
            status='approved'
        )
    else:
        if request.user.is_authenticated:
            profiles = ServicePartnerProfile.objects.filter(
                status='approved',
                is_public=True
            )
        else:
            profiles = ServicePartnerProfile.objects.filter(
                status='approved',
                is_public=True,
                is_featured=True
            )

    service_type = request.GET.get('service_type', '').strip()
    city = request.GET.get('city', '').strip()
    q = request.GET.get('q', '').strip()

    if service_type:
        profiles = profiles.filter(service_type=service_type)

    if city:
        profiles = profiles.filter(city=city)

    if q:
        profiles = profiles.filter(
            models.Q(display_name__icontains=q) |
            models.Q(full_name__icontains=q) |
            models.Q(short_intro__icontains=q) |
            models.Q(about_me__icontains=q) |
            models.Q(skills__icontains=q) |
            models.Q(experience_summary__icontains=q) |
            models.Q(languages_spoken__icontains=q)
        )

    profiles = profiles.order_by('-is_featured', '-created_at')

    # Pagination
    paginator = Paginator(profiles, 9)  # 9 cards per page
    page_number = request.GET.get('page')

    try:
        page_obj = paginator.page(page_number)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)

    # Preserve filters while changing pages
    query_params = request.GET.copy()
    if 'page' in query_params:
        query_params.pop('page')
    query_string = query_params.urlencode()

    return render(request, 'expat_life/public_assistant_list.html', {
        'profiles': page_obj,
        'page_obj': page_obj,
        'paginator': paginator,
        'total_results': paginator.count,
        'query_string': query_string,

        'is_foreigner_authenticated': is_foreigner_authenticated,
        'is_confirmed_foreigner': is_confirmed_foreigner,
        'can_view_private_listings': can_view_private_listings,
        'can_notify_interest': can_notify_interest,

        'selected_service_type': service_type,
        'selected_city': city,
        'search_query': q,
        'service_type_choices': ServicePartnerProfile.SERVICE_TYPE_CHOICES,
        'city_choices': SRI_LANKA_CITY_CHOICES,
    })

@login_required
def public_assistant_detail(request, pk):
    foreigner_profile = None
    is_foreigner_authenticated = False
    is_confirmed_foreigner = False
    can_view_private_listings = False
    can_notify_interest = False
    existing_interest = None

    foreigner_profile = getattr(request.user, 'foreigner_profile', None)

    if not foreigner_profile:
        messages.warning(
            request,
            "Only registered foreigner users can view local service assistant profile details."
        )

        if hasattr(request.user, 'rental_owner_profile'):
            return redirect('rental_app:rental_owner_dashboard')
        elif hasattr(request.user, 'dating_profile'):
            return redirect('dating_app:dating_partner_dashboard')
        elif hasattr(request.user, 'service_partner_profile'):
            return redirect('service_partner_app:service_partner_dashboard')

        return redirect('expat_life:home')

    if foreigner_profile.status != 'approved':
        messages.warning(
            request,
            "Your foreigner profile is not approved yet, so assistant profile details are not available."
        )
        return redirect('expat_life:foreigner_dashboard')

    if request.user.is_authenticated:
        if foreigner_profile:
            if foreigner_profile.status != 'approved':
                messages.warning(
                    request,
                    "Your foreigner profile is not approved yet, so assistant profile details are not available."
                )
                return redirect('expat_life:foreigner_dashboard')

            is_foreigner_authenticated = True
            is_confirmed_foreigner = foreigner_profile.is_confirmed
            can_view_private_listings = (
                foreigner_profile.is_confirmed and foreigner_profile.can_view_private_listings
            )
            can_notify_interest = (
                foreigner_profile.is_confirmed and foreigner_profile.can_book_arrangements
            )

    if not is_foreigner_authenticated:
        messages.warning(request, "Please sign up as a foreigner to view assistant details.")
        return redirect('expat_life:foreigner_signup')

    profile = get_object_or_404(
        ServicePartnerProfile,
        pk=pk,
        status='approved',
    )

    if foreigner_profile:
        existing_interest = profile.service_partner_interests.filter(
            foreigner=foreigner_profile
        ).first()

    return render(request, 'expat_life/public_assistant_detail.html', {
        'profile': profile,
        'is_foreigner_authenticated': is_foreigner_authenticated,
        'is_confirmed_foreigner': is_confirmed_foreigner,
        'can_view_private_listings': can_view_private_listings,
        'can_notify_interest': can_notify_interest,
        'existing_interest': existing_interest,
    })

def public_foreigners_list(request):
    dating_profile = getattr(request.user, 'dating_profile', None)

    show_all_approved_foreigners = False

    if request.user.is_authenticated and dating_profile:
        show_all_approved_foreigners = (
            dating_profile.status == 'approved'
            and dating_profile.is_public is True
        )

    if show_all_approved_foreigners:
        profiles = ForeignerProfile.objects.filter(
            status='approved'
        ).select_related('lead', 'user')
    else:
        if request.user.is_authenticated:
            profiles = ForeignerProfile.objects.filter(
                status='approved',
                is_public=True
            ).select_related('lead', 'user')
        else:
            profiles = ForeignerProfile.objects.filter(
                status='approved',
                is_public=True,
                is_featured=True
            ).select_related('lead', 'user')

    nationality = request.GET.get('nationality', '').strip()
    gender = request.GET.get('gender', '').strip()
    budget = request.GET.get('monthly_budget', '').strip()

    if nationality:
        profiles = profiles.filter(lead__nationality=nationality)

    if gender:
        profiles = profiles.filter(lead__gender=gender)

    if budget:
        profiles = profiles.filter(lead__monthly_budget=budget)

    profiles = profiles.order_by('-is_featured', '-joined_at')

    paginator = Paginator(profiles, 9)  # 9 cards per page
    page_number = request.GET.get('page')

    try:
        page_obj = paginator.page(page_number)
    except PageNotAnInteger:
        page_obj = paginator.page(1)
    except EmptyPage:
        page_obj = paginator.page(paginator.num_pages)

    query_params = request.GET.copy()
    if 'page' in query_params:
        query_params.pop('page')
    query_string = query_params.urlencode()

    return render(request, 'expat_life/public_foreigners_list.html', {
        'profiles': page_obj,
        'page_obj': page_obj,
        'paginator': paginator,
        'total_results': paginator.count,
        'query_string': query_string,

        'selected_nationality': nationality,
        'selected_gender': gender,
        'selected_budget': budget,
        'nationality_choices': NATIONALITY_CHOICES,
        'gender_choices': ForeignerLead.GENDER_CHOICES,
        'budget_choices': ForeignerLead.BUDGET_CHOICES,
    })

@login_required
def public_foreigner_detail(request, pk):
    dating_profile = getattr(request.user, 'dating_profile', None)
    is_dating_partner_authenticated = False
    can_view_private_listings = False
    can_notify_interest = False
    can_view_contact_details = False
    mutual_interest_exists = False

    if not dating_profile:
        messages.warning(
            request,
            "Only registered dating partners can view foreigner profile details."
        )

        if hasattr(request.user, 'rental_owner_profile'):
            return redirect('rental_app:rental_owner_dashboard')
        elif hasattr(request.user, 'foreigner_profile'):
            return redirect('expat_life:foreigner_dashboard')
        elif hasattr(request.user, 'service_partner_profile'):
            return redirect('service_partner_app:service_partner_dashboard')

        return redirect('dating_app:home_dating')

    if dating_profile.status != 'approved':
        messages.warning(
            request,
            "Your dating partner profile is not approved yet, so foreigner profile details are not available."
        )
        return redirect('dating_app:dating_partner_dashboard')

    is_dating_partner_authenticated = True
    can_view_private_listings = dating_profile.can_view_private_listings
    can_notify_interest = dating_profile.can_book_arrangements

    profile = ForeignerProfile.objects.filter(pk=pk, status='approved').first()

    if not profile:
        messages.warning(request, "The requested foreigner profile was not found or is not available.")
        return redirect('dating_app:public_foreigners_list')

    if not profile.is_public and not can_view_private_listings:
        messages.warning(
            request,
            "This foreigner profile is private. Your dating partner account does not currently have permission to view private profiles."
        )
        return redirect('dating_app:public_foreigners_list')

    allowed_statuses = ['interested', 'reviewing', 'contacted', 'matched']

    existing_interest = ForeignerInterest.objects.filter(
        dating_partner=dating_profile,
        foreigner=profile,
        status__in=allowed_statuses
    ).first()

    foreigner_interest_in_partner = DatingInterest.objects.filter(
        foreigner=profile,
        partner=dating_profile,
        status__in=allowed_statuses
    ).first()

    mutual_interest_exists = bool(existing_interest and foreigner_interest_in_partner)

    can_view_contact_details = bool(
        dating_profile.is_confirmed and mutual_interest_exists
    )

    return render(request, 'dating_app/public_foreigner_detail.html', {
        'profile': profile,
        'is_dating_partner_authenticated': is_dating_partner_authenticated,
        'can_view_private_listings': can_view_private_listings,
        'can_notify_interest': can_notify_interest,
        'can_view_contact_details': can_view_contact_details,
        'mutual_interest_exists': mutual_interest_exists,
        'existing_interest': existing_interest,
        'foreigner_interest_in_partner': foreigner_interest_in_partner,
        'dating_partner_is_confirmed': dating_profile.is_confirmed,
    })

@login_required
def express_foreigner_interest(request, pk):
    dating_profile = getattr(request.user, 'dating_profile', None)

    if not dating_profile:
        messages.warning(
            request,
            "Only registered dating partners can express interest in foreigner profiles."
        )
        return redirect('expat_life:home')

    if dating_profile.status != 'approved':
        messages.warning(
            request,
            "Your dating partner profile is not approved yet."
        )
        return redirect('dating_app:dating_partner_dashboard')

    if not dating_profile.can_book_arrangements:
        messages.warning(
            request,
            "You are not yet allowed to submit interest requests."
        )
        return redirect('dating_app:dating_partner_dashboard')

    if dating_profile.can_view_private_listings:
        foreigner = get_object_or_404(
            ForeignerProfile,
            pk=pk,
            status='approved'
        )
    else:
        foreigner = get_object_or_404(
            ForeignerProfile,
            pk=pk,
            status='approved',
            is_public=True
        )

    if request.method == 'POST':
        form = ForeignerInterestForm(request.POST)

        if form.is_valid():
            message = form.cleaned_data.get('message', '')

            interest, created = ForeignerInterest.objects.get_or_create(
                dating_partner=dating_profile,
                foreigner=foreigner,
                defaults={
                    'message': message,
                    'status': 'interested',
                }
            )

            if created:
                try:
                    send_guest_dating_interest_notification_email(
                        foreigner=foreigner,
                        dating_partner=dating_profile,
                        interest=interest,
                        request=request,
                    )
                except Exception:
                    pass

                messages.success(
                    request,
                    "Your interest has been sent successfully."
                )

            else:
                if form.cleaned_data.get('message'):
                    interest.message = form.cleaned_data['message']
                    interest.save(update_fields=['message'])

                messages.info(
                    request,
                    "You have already expressed interest in this foreigner profile. Your message was updated."
                )

            return redirect(
                'expat_life:public_foreigner_detail',
                pk=foreigner.pk
            )

    messages.error(request, "Invalid request.")
    return redirect(
        'expat_life:public_foreigner_detail',
        pk=foreigner.pk
    )

@login_required
def select_final_rental_property(request, interest_id):
    if request.method != 'POST':
        return redirect('expat_life:my_interested_properties')

    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile or not profile.lead:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    interest = get_object_or_404(
        RentalInterest,
        id=interest_id,
        foreigner=profile
    )

    lead = profile.lead

    # Once rental cycle is active, final rental property must be locked.
    if profile.is_rental_cycle_active:
        messages.error(
            request,
            "You cannot change the final rental property because your rental cycle is already active."
        )
        return redirect('expat_life:my_interested_properties')

    previous_listing_id = lead.final_rental_property_id

    # If another property was previously marked as selected, reset it
    if previous_listing_id and previous_listing_id != interest.listing_id:
        RentalInterest.objects.filter(
            foreigner=profile,
            listing_id=previous_listing_id,
            status='selected'
        ).update(status='interested')

    # Set new final property
    lead.final_rental_property = interest.listing
    lead.final_rental_selected_at = timezone.now()
    lead.save(update_fields=['final_rental_property', 'final_rental_selected_at'])

    # Mark this one as selected
    RentalInterest.objects.filter(
        foreigner=profile,
        listing=interest.listing
    ).update(status='selected')

    # Refresh rental-related payable items
    update_foreigner_rental_payable_items(request.user, lead)

    messages.success(
        request,
        f'"{interest.listing.title}" has been selected as your final rental property.'
    )
    return redirect('expat_life:my_interested_properties')

@login_required
def my_interested_properties(request):
    profile = getattr(request.user, 'foreigner_profile', None)
    if not profile or not profile.lead:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    interests = RentalInterest.objects.filter(
        foreigner=profile
    ).select_related('listing').order_by('-created_at')

    lead = profile.lead

    return render(request, 'expat_life/dashboard/my_interested_properties.html', {
        'profile': profile,
        'lead': lead,
        'interests': interests,
    })

def calculate_age(date_of_birth):
    if not date_of_birth:
        return None

    today = date.today()
    return (
        today.year
        - date_of_birth.year
        - ((today.month, today.day) < (date_of_birth.month, date_of_birth.day))
    )


@login_required
def my_interested_dating_profiles(request):
    profile = getattr(request.user, 'foreigner_profile', None)

    if not profile:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    interests = DatingInterest.objects.filter(
        foreigner=profile,
        partner__status='approved',
    ).select_related('partner').order_by('-created_at')

    for interest in interests:
        interest.partner_age = calculate_age(interest.partner.date_of_birth)

    return render(request, 'expat_life/dashboard/my_interested_dating_profiles.html', {
        'profile': profile,
        'interests': interests,
    })

def calculate_age_from_dob(date_of_birth):
    if not date_of_birth:
        return None

    today = date.today()
    return (
        today.year
        - date_of_birth.year
        - ((today.month, today.day) < (date_of_birth.month, date_of_birth.day))
    )


@login_required
def my_interested_service_partners(request):
    profile = getattr(request.user, 'foreigner_profile', None)

    if not profile:
        return HttpResponseForbidden("You do not have a foreigner profile.")

    interests = ServicePartnerInterest.objects.filter(
        foreigner=profile,
        partner__status='approved'
    ).select_related('partner').order_by('-created_at')

    for interest in interests:
        partner = interest.partner

        if partner.age:
            interest.partner_age = partner.age
        else:
            interest.partner_age = calculate_age_from_dob(partner.date_of_birth)

    return render(request, 'expat_life/dashboard/my_interested_service_partners.html', {
        'profile': profile,
        'interests': interests,
    })

def furniture_package_list(request):
    furniture_packages = FurniturePackage.objects.filter(
        is_active=True
    ).prefetch_related('items').order_by('order', 'level')

    foreigner_profile = None
    lead = None
    selected_furniture_package_id = None
    is_foreigner_user = False

    if request.user.is_authenticated:
        foreigner_profile = getattr(request.user, 'foreigner_profile', None)
        if foreigner_profile:
            is_foreigner_user = True
            lead = getattr(foreigner_profile, 'lead', None)
            if lead and lead.selected_furniture_package_id:
                selected_furniture_package_id = lead.selected_furniture_package_id

    return render(request, 'expat_life/furniture_package_list.html', {
        'furniture_packages': furniture_packages,
        'foreigner_profile': foreigner_profile,
        'lead': lead,
        'selected_furniture_package_id': selected_furniture_package_id,
        'is_foreigner_user': is_foreigner_user,
    })


def furniture_package_detail(request, slug):
    furniture_package = get_object_or_404(
        FurniturePackage.objects.prefetch_related('items'),
        slug=slug,
        is_active=True
    )

    lead = None
    already_selected = False
    is_foreigner_user = False

    if request.user.is_authenticated:
        profile = getattr(request.user, 'foreigner_profile', None)
        if profile:
            is_foreigner_user = True
            lead = getattr(profile, 'lead', None)
            if lead:
                already_selected = (
                    lead.selected_furniture_package_id == furniture_package.id
                )

    return render(request, 'expat_life/furniture_package_detail.html', {
        'furniture_package': furniture_package,
        'lead': lead,
        'already_selected': already_selected,
        'is_foreigner_user': is_foreigner_user,
    })


@login_required
def select_furniture_package(request, slug):
    if request.method != 'POST':
        return redirect('expat_life:furniture_package_detail', slug=slug)

    furniture_package = get_object_or_404(
        FurniturePackage,
        slug=slug,
        is_active=True
    )

    foreigner_profile = getattr(request.user, 'foreigner_profile', None)
    if not foreigner_profile:
        messages.error(request, "This account is not registered as a foreigner.")
        return redirect('expat_life:home')

    lead = getattr(foreigner_profile, 'lead', None)
    if not lead:
        messages.error(request, "Your foreigner lead record was not found.")
        return redirect('expat_life:foreigner_dashboard')

    # Once furniture cycle is active, selected furniture package must be locked.
    if foreigner_profile.is_furniture_cycle_active:
        messages.error(
            request,
            "You cannot change the furniture package because your furniture rental cycle is already active."
        )
        return redirect(
            'expat_life:furniture_package_detail',
            slug=lead.selected_furniture_package.slug if lead.selected_furniture_package else slug
        )

    lead.selected_furniture_package = furniture_package
    lead.save(update_fields=['selected_furniture_package'])

    # Refresh furniture-related payable items
    update_foreigner_furniture_payable_items(request.user, lead)

    messages.success(
        request,
        f'Furniture package "{furniture_package.name}" has been selected successfully. Related payable items were updated.'
    )
    return redirect('expat_life:furniture_package_detail', slug=furniture_package.slug)


@login_required
def foreigner_payment_center(request):
    foreigner = getattr(request.user, 'foreigner_profile', None)
    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')
    
    # --- get or create the foreigner wallet ---
    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='foreigner',
        defaults={'balance_usd': 0}
    )

    # --- Query active refundable deposits for this user (foreigner) ---
    active_deposits = RefundableDeposit.objects.filter(
        user=request.user,
        profile_type='foreigner',
        status='active'
    ).order_by('created_at')  # show oldest first

    # --- rest of your existing code (lead, sync, payable_items, sorting, etc.) ---
    lead = getattr(foreigner, 'lead', None)
    if lead:
        sync_foreigner_payable_items(request.user, lead)

    payable_items = list(
        UserPayableItem.objects.filter(
            user=request.user,
            profile_type='foreigner',
            is_active=True
        )
    )

    payment_order = {
        'account_confirmation': 1,
        'one_time_service_fee': 2,
        'rental_deposit': 3,
        'furniture_rental_deposit': 4,
        'monthly_rental': 5,
        'furniture_rental': 6,
        'featured_profile_fee': 20,
        'other': 99,
    }

    payable_items.sort(
        key=lambda item: (
            payment_order.get(item.payment_for, 50),
            item.due_date or item.created_at.date(),
            item.created_at
        )
    )

    due_items = [item for item in payable_items if item.payment_status == 'due']
    upcoming_items = [item for item in payable_items if item.payment_status == 'upcoming' and not item.is_optional]
    optional_items = [item for item in payable_items if item.is_optional and item.payment_status not in ['due', 'paid']]
    paid_items = [item for item in payable_items if item.payment_status == 'paid']

    selectable_item_ids = [item.id for item in payable_items if item.payment_status == 'due' and item.amount_usd > 0]

    total_due = sum((item.amount_usd for item in due_items), Decimal('0.00'))
    total_upcoming = sum((item.amount_usd for item in upcoming_items), Decimal('0.00'))
    total_paid = sum((item.amount_usd for item in paid_items), Decimal('0.00'))

    context = {
        'foreigner': foreigner,
        'lead': lead,
        'wallet': wallet,
        'active_deposits': active_deposits,      # <-- add this
        'payable_items': payable_items,
        'due_items': due_items,
        'upcoming_items': upcoming_items,
        'optional_items': optional_items,
        'paid_items': paid_items,
        'selectable_item_ids': selectable_item_ids,
        'total_due': total_due,
        'total_upcoming': total_upcoming,
        'total_paid': total_paid,
    }
    return render(request, 'expat_life/foreigner_payment_center.html', context)

@login_required
def foreigner_payment_checkout(request):
    foreigner = getattr(request.user, 'foreigner_profile', None)
    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')

    if request.method != 'POST':
        messages.error(request, "Please select at least one payment item first.")
        return redirect('expat_life:foreigner_payment_center')

    # --- NEW: get or create the foreigner wallet ---
    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='foreigner',
        defaults={'balance_usd': 0}   # not strictly needed because default=0, but explicit
    )


    selected_ids = request.POST.getlist('selected_items')

    if not selected_ids:
        messages.error(request, "Please select at least one payment item.")
        return redirect('expat_life:foreigner_payment_center')

    payable_items = list(
        UserPayableItem.objects.filter(
            id__in=selected_ids,
            user=request.user,
            profile_type='foreigner',
            is_active=True,
            payment_status='due'
        ).exclude(amount_usd__lte=0)
    )

    if not payable_items:
        messages.error(request, "No valid payable items were selected.")
        return redirect('expat_life:foreigner_payment_center')

    total_amount = sum((item.amount_usd for item in payable_items), Decimal('0.00'))

    context = {
        'foreigner': foreigner,
        'wallet': wallet,  
        'payable_items': payable_items,
        'selected_ids': [str(item.id) for item in payable_items],
        'total_amount': total_amount,
    }
    return render(request, 'expat_life/foreigner_payment_checkout.html', context)

@login_required
def foreigner_payment_checkout_pay(request):
    foreigner = getattr(request.user, 'foreigner_profile', None)

    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')

    if request.method != 'POST':
        messages.error(request, "Invalid payment request.")
        return redirect('expat_life:foreigner_payment_center')

    # ---------------------------------------------------------
    # 1. Collect selected items and checkout options
    # ---------------------------------------------------------
    selected_ids = request.POST.getlist('selected_items')
    payment_method = request.POST.get('payment_method')
    use_wallet = request.POST.get('use_wallet') == '1'

    if not selected_ids:
        messages.error(request, "Please select at least one payment item.")
        return redirect('expat_life:foreigner_payment_center')

    payable_items = list(
        UserPayableItem.objects.filter(
            id__in=selected_ids,
            user=request.user,
            profile_type='foreigner',
            is_active=True,
            payment_status='due',
        ).exclude(amount_usd__lte=0)
    )

    if not payable_items:
        messages.error(request, "No valid payable items were selected.")
        return redirect('expat_life:foreigner_payment_center')

    total_amount = sum(
        (item.amount_usd for item in payable_items),
        Decimal('0.00')
    )

    total_amount = Decimal(total_amount).quantize(Decimal('0.01'))

    # ---------------------------------------------------------
    # 2. Wallet calculation
    # ---------------------------------------------------------
    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='foreigner',
        defaults={'balance_usd': Decimal('0.00')}
    )

    wallet_balance = wallet.balance_usd or Decimal('0.00')
    wallet_deduction = Decimal('0.00')
    amount_to_charge = total_amount

    if use_wallet and wallet_balance > Decimal('0.00'):
        wallet_deduction = min(wallet_balance, total_amount)
        wallet_deduction = Decimal(wallet_deduction).quantize(Decimal('0.01'))
        amount_to_charge = total_amount - wallet_deduction

    amount_to_charge = Decimal(amount_to_charge).quantize(Decimal('0.01'))

    # ---------------------------------------------------------
    # 3. Wallet-only payment
    # ---------------------------------------------------------
    if amount_to_charge <= Decimal('0.00'):
        with transaction.atomic():
            locked_wallet = WalletAccount.objects.select_for_update().get(
                id=wallet.id
            )

            if locked_wallet.balance_usd < wallet_deduction:
                messages.error(
                    request,
                    "Your wallet balance changed. Please try again."
                )
                return redirect('expat_life:foreigner_payment_center')

            payment_transaction = PaymentTransaction.objects.create(
                user=request.user,
                profile_type='foreigner',
                payment_purpose='payable_items',
                payment_method='wallet',
                total_amount_usd=total_amount,
                wallet_deduction_usd=wallet_deduction,
                gateway_amount_usd=Decimal('0.00'),
                status='paid',
                paid_at=timezone.now(),
            )

            for item in payable_items:
                PaymentTransactionItem.objects.create(
                    transaction=payment_transaction,
                    payable_item=item,
                    amount_usd=item.amount_usd,
                )

            mark_result = mark_foreigner_transaction_items_paid(
                payment_transaction=payment_transaction,
                notes=f"Paid using wallet. Transaction #{payment_transaction.id}",
            )

            if not mark_result["success"]:
                payment_transaction.failure_reason = "\n".join(mark_result["failed"])
                payment_transaction.status = "failed"
                payment_transaction.failed_at = timezone.now()
                payment_transaction.save(update_fields=[
                    "failure_reason",
                    "status",
                    "failed_at",
                    "updated_at",
                ])

                messages.error(
                    request,
                    "Payment could not be fully completed. Please contact support."
                )
                return redirect(
                    "expat_life:foreigner_payment_failed",
                    transaction_id=payment_transaction.id
                )

            locked_wallet.balance_usd -= wallet_deduction
            locked_wallet.save(update_fields=['balance_usd'])

        # Clear old checkout session values
        request.session.pop('foreigner_payment_transaction_id', None)
        request.session.pop('foreigner_checkout_selected_ids', None)
        request.session.pop('foreigner_checkout_total', None)
        request.session.pop('foreigner_checkout_profile_type', None)
        request.session.pop('foreigner_use_wallet', None)
        request.session.pop('foreigner_wallet_deduction', None)


        try:
            send_foreigner_payment_invoice_email(
                payment_transaction=payment_transaction,
                request=request,
            )
        except Exception as e:
            payment_transaction.failure_reason = (
                f"{payment_transaction.failure_reason or ''}\n"
                f"Invoice email failed: {str(e)}"
            )
            payment_transaction.save(update_fields=[
                "failure_reason",
                "updated_at",
            ])

        messages.success(
            request,
            "Payment completed successfully using your wallet balance."
        )

        return redirect(
            'expat_life:foreigner_payment_success',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 4. Validate gateway payment method
    # ---------------------------------------------------------
    if payment_method == 'stripe':
        final_payment_method = (
            'mixed_stripe_wallet'
            if wallet_deduction > Decimal('0.00')
            else 'stripe'
        )

    elif payment_method == 'paypal':
        final_payment_method = (
            'mixed_paypal_wallet'
            if wallet_deduction > Decimal('0.00')
            else 'paypal'
        )

    else:
        messages.error(request, "Please choose a valid payment method.")
        return redirect('expat_life:foreigner_payment_center')

    # ---------------------------------------------------------
    # 5. Create pending payment transaction
    # ---------------------------------------------------------
    with transaction.atomic():
        payment_transaction = PaymentTransaction.objects.create(
            user=request.user,
            profile_type='foreigner',
            payment_purpose='payable_items',
            payment_method=final_payment_method,
            total_amount_usd=total_amount,
            wallet_deduction_usd=wallet_deduction,
            gateway_amount_usd=amount_to_charge,
            status='pending',
        )

        for item in payable_items:
            PaymentTransactionItem.objects.create(
                transaction=payment_transaction,
                payable_item=item,
                amount_usd=item.amount_usd,
            )

    # ---------------------------------------------------------
    # 6. Store checkout details in session for gateway step
    # ---------------------------------------------------------
    request.session['foreigner_payment_transaction_id'] = payment_transaction.id
    request.session['foreigner_checkout_selected_ids'] = [
        item.id for item in payable_items
    ]
    request.session['foreigner_checkout_total'] = str(amount_to_charge)
    request.session['foreigner_checkout_profile_type'] = 'foreigner'
    request.session['foreigner_use_wallet'] = use_wallet
    request.session['foreigner_wallet_deduction'] = str(wallet_deduction)

    # ---------------------------------------------------------
    # 7. Redirect to selected gateway
    # ---------------------------------------------------------
    if payment_method == 'stripe':
        return redirect('expat_life:start_foreigner_stripe_checkout')

    if payment_method == 'paypal':
        return redirect('expat_life:start_foreigner_paypal_checkout')

    messages.error(request, "Please choose a valid payment method.")
    return redirect('expat_life:foreigner_payment_center')
    
@login_required
def start_foreigner_stripe_checkout(request):
    foreigner = getattr(request.user, 'foreigner_profile', None)

    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')

    transaction_id = request.session.get('foreigner_payment_transaction_id')

    if not transaction_id:
        messages.error(request, "No checkout transaction found.")
        return redirect('expat_life:foreigner_payment_center')

    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
        status='pending',
    )

    if payment_transaction.payment_method not in ['stripe', 'mixed_stripe_wallet']:
        messages.error(request, "Invalid payment method for Stripe checkout.")
        return redirect('expat_life:foreigner_payment_center')

    if payment_transaction.gateway_amount_usd <= Decimal('0.00'):
        messages.error(request, "Invalid Stripe payment amount.")
        return redirect('expat_life:foreigner_payment_center')

    payable_items = list(
        payment_transaction.items.select_related('payable_item').all()
    )

    if not payable_items:
        messages.error(request, "No payment items found for this transaction.")
        return redirect('expat_life:foreigner_payment_center')

    if not settings.STRIPE_SECRET_KEY:
        messages.error(request, "Stripe payment is not configured.")
        return redirect('expat_life:foreigner_payment_center')

    stripe.api_key = settings.STRIPE_SECRET_KEY

    try:
        line_items = []

        # ---------------------------------------------------------
        # If wallet is partially used, Stripe should charge only
        # the remaining gateway amount.
        # ---------------------------------------------------------
        if payment_transaction.wallet_deduction_usd > Decimal('0.00'):
            stripe_amount_cents = int(
                (payment_transaction.gateway_amount_usd * Decimal('100')).quantize(Decimal('1'))
            )

            line_items = [{
                'price_data': {
                    'currency': 'usd',
                    'product_data': {
                        'name': f'Guest Payment - Transaction #{payment_transaction.id}',
                        'description': (
                            f'Total: ${payment_transaction.total_amount_usd}, '
                            f'Wallet used: ${payment_transaction.wallet_deduction_usd}, '
                            f'Stripe payment: ${payment_transaction.gateway_amount_usd}'
                        ),
                    },
                    'unit_amount': stripe_amount_cents,
                },
                'quantity': 1,
            }]

        else:
            for transaction_item in payable_items:
                payable_item = transaction_item.payable_item

                stripe_amount_cents = int(
                    (transaction_item.amount_usd * Decimal('100')).quantize(Decimal('1'))
                )

                line_items.append({
                    'price_data': {
                        'currency': 'usd',
                        'product_data': {
                            'name': payable_item.title,
                            'description': (
                                getattr(payable_item, 'description', '') 
                                or 'Guest payment item'
                            ),
                        },
                        'unit_amount': stripe_amount_cents,
                    },
                    'quantity': 1,
                })

        success_url = request.build_absolute_uri(
            reverse(
                'expat_life:foreigner_stripe_payment_success',
                kwargs={'transaction_id': payment_transaction.id}
            )
        ) + '?session_id={CHECKOUT_SESSION_ID}'

        cancel_url = request.build_absolute_uri(
            reverse(
                'expat_life:foreigner_payment_cancelled',
                kwargs={'transaction_id': payment_transaction.id}
            )
        )

        checkout_session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            mode='payment',
            line_items=line_items,
            success_url=success_url,
            cancel_url=cancel_url,
            customer_email=request.user.email or None,
            client_reference_id=str(payment_transaction.id),
            metadata={
                'payment_transaction_id': str(payment_transaction.id),
                'user_id': str(request.user.id),
                'profile_type': 'foreigner',
                'payment_purpose': 'payable_items',
            },
        )

        if not checkout_session.url:
            messages.error(
                request,
                "Stripe checkout session was created, but no checkout URL was returned."
            )
            return redirect('expat_life:foreigner_payment_center')

        payment_transaction.gateway_session_id = checkout_session.id
        payment_transaction.status = 'processing'
        payment_transaction.save(update_fields=[
            'gateway_session_id',
            'status',
            'updated_at',
        ])

        return redirect(checkout_session.url)

    except Exception as e:
        payment_transaction.failure_reason = str(e)
        payment_transaction.save(update_fields=[
            'failure_reason',
            'updated_at',
        ])

        messages.error(
            request,
            "Stripe checkout could not be started. Please try again."
        )

        return redirect('expat_life:foreigner_payment_center')

@login_required
def foreigner_stripe_payment_success(request, transaction_id):
    foreigner = getattr(request.user, 'foreigner_profile', None)

    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')

    session_id = request.GET.get('session_id')

    if not session_id:
        messages.error(request, "Stripe payment session not found.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=transaction_id
        )

    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
    )

    # If already paid, avoid duplicate wallet deduction / duplicate item updates.
    if payment_transaction.status == 'paid':
        messages.success(request, "This payment has already been completed.")
        return redirect(
            'expat_life:foreigner_payment_success',
            transaction_id=payment_transaction.id
        )

    if payment_transaction.payment_method not in ['stripe', 'mixed_stripe_wallet']:
        messages.error(request, "Invalid payment method for Stripe confirmation.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    if not settings.STRIPE_SECRET_KEY:
        messages.error(request, "Stripe payment is not configured.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    stripe.api_key = settings.STRIPE_SECRET_KEY

    # ---------------------------------------------------------
    # 1. Retrieve Stripe Checkout Session
    # ---------------------------------------------------------
    try:
        stripe_session = stripe.checkout.Session.retrieve(session_id)

    except Exception as e:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"Stripe session retrieve failed: {str(e)}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "Could not verify Stripe payment.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 2. Verify Stripe metadata transaction ID
    # ---------------------------------------------------------
    metadata_transaction_id = None
    stripe_metadata = getattr(stripe_session, 'metadata', None)

    if stripe_metadata:
        try:
            stripe_metadata = dict(stripe_metadata)
            metadata_transaction_id = stripe_metadata.get('payment_transaction_id')
        except Exception:
            metadata_transaction_id = getattr(
                stripe_metadata,
                'payment_transaction_id',
                None
            )

    if str(metadata_transaction_id) != str(payment_transaction.id):
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = "Stripe metadata transaction ID mismatch."
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "Stripe payment verification failed.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 3. Verify Stripe payment status
    # ---------------------------------------------------------
    stripe_payment_status = getattr(stripe_session, 'payment_status', None)

    if stripe_payment_status != 'paid':
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = (
            f"Stripe payment status was not paid: {stripe_payment_status}"
        )
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "Stripe payment was not completed.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 4. Verify amount
    # ---------------------------------------------------------
    expected_amount_cents = int(
        (payment_transaction.gateway_amount_usd * Decimal('100')).quantize(Decimal('1'))
    )

    stripe_amount_total = getattr(stripe_session, 'amount_total', None)

    if stripe_amount_total is not None and int(stripe_amount_total) != expected_amount_cents:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = (
            f"Stripe amount mismatch. Expected {expected_amount_cents}, "
            f"received {stripe_amount_total}."
        )
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "Stripe payment amount verification failed.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 5. Payment verified. Safely update database.
    # ---------------------------------------------------------
    try:
        with transaction.atomic():
            locked_transaction = PaymentTransaction.objects.select_for_update().get(
                id=payment_transaction.id,
                user=request.user,
                profile_type='foreigner',
            )

            # Prevent duplicate processing if user refreshes success URL.
            if locked_transaction.status == 'paid':
                messages.success(request, "This payment has already been completed.")
                return redirect(
                    'expat_life:foreigner_payment_success',
                    transaction_id=locked_transaction.id
                )

            wallet_deduction = locked_transaction.wallet_deduction_usd or Decimal('0.00')

            # -------------------------------------------------
            # 5A. Deduct wallet only if this was mixed payment
            # -------------------------------------------------
            if wallet_deduction > Decimal('0.00'):
                wallet = WalletAccount.objects.select_for_update().get(
                    user=request.user,
                    profile_type='foreigner',
                )

                if wallet.balance_usd < wallet_deduction:
                    locked_transaction.status = 'failed'
                    locked_transaction.failure_reason = (
                        "Wallet balance was insufficient during Stripe success confirmation."
                    )
                    locked_transaction.failed_at = timezone.now()
                    locked_transaction.save(update_fields=[
                        'status',
                        'failure_reason',
                        'failed_at',
                        'updated_at',
                    ])

                    messages.error(
                        request,
                        "Payment was received by Stripe, but wallet deduction failed. "
                        "Please contact support."
                    )
                    return redirect(
                        'expat_life:foreigner_payment_failed',
                        transaction_id=locked_transaction.id
                    )

                wallet.balance_usd -= wallet_deduction
                wallet.save(update_fields=['balance_usd'])

            # -------------------------------------------------
            # 5B. Mark selected payable items as paid
            # IMPORTANT:
            # This must run for BOTH full Stripe and mixed Stripe+wallet payments.
            # -------------------------------------------------
            mark_result = mark_foreigner_transaction_items_paid(
                payment_transaction=locked_transaction,
                notes=f"Paid by Stripe. Transaction #{locked_transaction.id}",
            )

            if not mark_result["success"]:
                locked_transaction.status = 'failed'
                locked_transaction.failure_reason = "\n".join(mark_result["failed"])
                locked_transaction.failed_at = timezone.now()
                locked_transaction.save(update_fields=[
                    'status',
                    'failure_reason',
                    'failed_at',
                    'updated_at',
                ])

                messages.error(
                    request,
                    "Stripe payment was received, but the system could not complete all payment actions. "
                    "Please contact support."
                )

                return redirect(
                    'expat_life:foreigner_payment_failed',
                    transaction_id=locked_transaction.id
                )

            # -------------------------------------------------
            # 5C. Mark transaction as paid
            # -------------------------------------------------
            locked_transaction.gateway_session_id = stripe_session.id
            locked_transaction.gateway_transaction_id = (
                getattr(stripe_session, 'payment_intent', '') or stripe_session.id
            )
            locked_transaction.status = 'paid'
            locked_transaction.paid_at = timezone.now()
            locked_transaction.failure_reason = ''
            locked_transaction.save(update_fields=[
                'gateway_session_id',
                'gateway_transaction_id',
                'status',
                'paid_at',
                'failure_reason',
                'updated_at',
            ])

    except Exception as e:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"Database payment completion failed: {str(e)}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(
            request,
            "Payment was verified, but the system could not complete the payment record. "
            "Please contact support."
        )
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 6. Send invoice email
    # ---------------------------------------------------------
    try:
        refreshed_transaction = PaymentTransaction.objects.get(
            id=payment_transaction.id
        )

        send_foreigner_payment_invoice_email(
            payment_transaction=refreshed_transaction,
            request=request,
        )

    except Exception as e:
        refreshed_transaction = PaymentTransaction.objects.get(
            id=payment_transaction.id
        )

        refreshed_transaction.failure_reason = (
            f"{refreshed_transaction.failure_reason or ''}\n"
            f"Invoice email failed: {str(e)}"
        )
        refreshed_transaction.save(update_fields=[
            "failure_reason",
            "updated_at",
        ])

    # ---------------------------------------------------------
    # 7. Clear checkout session data
    # ---------------------------------------------------------
    request.session.pop('foreigner_payment_transaction_id', None)
    request.session.pop('foreigner_checkout_selected_ids', None)
    request.session.pop('foreigner_checkout_total', None)
    request.session.pop('foreigner_checkout_profile_type', None)
    request.session.pop('foreigner_use_wallet', None)
    request.session.pop('foreigner_wallet_deduction', None)

    messages.success(request, "Stripe payment completed successfully.")

    return redirect(
        'expat_life:foreigner_payment_success',
        transaction_id=payment_transaction.id
    )

@login_required
def start_foreigner_paypal_checkout(request):
    foreigner = getattr(request.user, 'foreigner_profile', None)

    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')

    transaction_id = request.session.get('foreigner_payment_transaction_id')

    if not transaction_id:
        messages.error(request, "No checkout transaction found.")
        return redirect('expat_life:foreigner_payment_center')

    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
        status='pending',
    )

    if payment_transaction.payment_method not in ['paypal', 'mixed_paypal_wallet']:
        messages.error(request, "Invalid payment method for PayPal checkout.")
        return redirect('expat_life:foreigner_payment_center')

    if payment_transaction.gateway_amount_usd <= Decimal('0.00'):
        messages.error(request, "Invalid PayPal payment amount.")
        return redirect('expat_life:foreigner_payment_center')

    payable_items = list(
        payment_transaction.items.select_related('payable_item').all()
    )

    if not payable_items:
        messages.error(request, "No payment items found for this transaction.")
        return redirect('expat_life:foreigner_payment_center')

    try:
        order_data = create_paypal_order(payment_transaction, request)
        approval_url = get_paypal_approval_url(order_data)

        if not approval_url:
            raise Exception("PayPal approval URL not found.")

        payment_transaction.gateway_session_id = order_data.get('id', '')
        payment_transaction.status = 'processing'
        payment_transaction.save(update_fields=[
            'gateway_session_id',
            'status',
            'updated_at',
        ])

        return redirect(approval_url)

    except Exception as e:
        payment_transaction.failure_reason = str(e)
        payment_transaction.save(update_fields=[
            'failure_reason',
            'updated_at',
        ])

        messages.error(
            request,
            "PayPal checkout could not be started. Please try again."
        )

        return redirect('expat_life:foreigner_payment_center')

@login_required
def foreigner_paypal_payment_success(request, transaction_id):
    foreigner = getattr(request.user, 'foreigner_profile', None)

    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')

    paypal_order_id = request.GET.get('token')

    if not paypal_order_id:
        messages.error(request, "PayPal payment order not found.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=transaction_id
        )

    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
    )

    if payment_transaction.status == 'paid':
        messages.success(request, "This payment has already been completed.")
        return redirect(
            'expat_life:foreigner_payment_success',
            transaction_id=payment_transaction.id
        )

    if payment_transaction.payment_method not in ['paypal', 'mixed_paypal_wallet']:
        messages.error(request, "Invalid payment method for PayPal confirmation.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    if payment_transaction.gateway_session_id and payment_transaction.gateway_session_id != paypal_order_id:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = "PayPal order ID mismatch."
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "PayPal payment verification failed.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    try:
        capture_data = capture_paypal_order(paypal_order_id)

    except Exception as e:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"PayPal capture failed: {str(e)}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "Could not capture PayPal payment.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    paypal_status = capture_data.get('status')

    if paypal_status != 'COMPLETED':
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"PayPal payment status was not completed: {paypal_status}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "PayPal payment was not completed.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    try:
        purchase_units = capture_data.get('purchase_units', [])
        first_purchase_unit = purchase_units[0] if purchase_units else {}
        payments = first_purchase_unit.get('payments', {})
        captures = payments.get('captures', [])
        first_capture = captures[0] if captures else {}

        captured_amount = first_capture.get('amount', {})
        captured_value = Decimal(str(captured_amount.get('value', '0.00'))).quantize(Decimal('0.01'))
        captured_currency = captured_amount.get('currency_code')

        expected_amount = payment_transaction.gateway_amount_usd.quantize(Decimal('0.01'))

        if captured_currency != 'USD' or captured_value != expected_amount:
            payment_transaction.status = 'failed'
            payment_transaction.failure_reason = (
                f"PayPal amount mismatch. Expected USD {expected_amount}, "
                f"received {captured_currency} {captured_value}."
            )
            payment_transaction.failed_at = timezone.now()
            payment_transaction.save(update_fields=[
                'status',
                'failure_reason',
                'failed_at',
                'updated_at',
            ])

            messages.error(request, "PayPal payment amount verification failed.")
            return redirect(
                'expat_life:foreigner_payment_failed',
                transaction_id=payment_transaction.id
            )

        paypal_capture_id = first_capture.get('id', paypal_order_id)

    except Exception as e:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"PayPal capture response parsing failed: {str(e)}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "PayPal payment verification failed.")
        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    try:
        with transaction.atomic():
            locked_transaction = PaymentTransaction.objects.select_for_update().get(
                id=payment_transaction.id,
                user=request.user,
                profile_type='foreigner',
            )

            if locked_transaction.status == 'paid':
                messages.success(request, "This payment has already been completed.")
                return redirect(
                    'expat_life:foreigner_payment_success',
                    transaction_id=locked_transaction.id
                )

            wallet_deduction = locked_transaction.wallet_deduction_usd or Decimal('0.00')

            if wallet_deduction > Decimal('0.00'):
                wallet = WalletAccount.objects.select_for_update().get(
                    user=request.user,
                    profile_type='foreigner',
                )

                if wallet.balance_usd < wallet_deduction:
                    locked_transaction.status = 'failed'
                    locked_transaction.failure_reason = (
                        "Wallet balance was insufficient during PayPal success confirmation."
                    )
                    locked_transaction.failed_at = timezone.now()
                    locked_transaction.save(update_fields=[
                        'status',
                        'failure_reason',
                        'failed_at',
                        'updated_at',
                    ])

                    messages.error(
                        request,
                        "Payment was received by PayPal, but wallet deduction failed. "
                        "Please contact support."
                    )
                    return redirect(
                        'expat_life:foreigner_payment_failed',
                        transaction_id=locked_transaction.id
                    )

                wallet.balance_usd -= wallet_deduction
                wallet.save(update_fields=['balance_usd'])

            mark_result = mark_foreigner_transaction_items_paid(
                payment_transaction=locked_transaction,
                notes=f"Paid by PayPal. Transaction #{locked_transaction.id}",
            )

            if not mark_result["success"]:
                locked_transaction.status = 'failed'
                locked_transaction.failure_reason = "\n".join(mark_result["failed"])
                locked_transaction.failed_at = timezone.now()
                locked_transaction.save(update_fields=[
                    'status',
                    'failure_reason',
                    'failed_at',
                    'updated_at',
                ])

                messages.error(
                    request,
                    "PayPal payment was received, but the system could not complete all payment actions. Please contact support."
                )

                return redirect(
                    'expat_life:foreigner_payment_failed',
                    transaction_id=locked_transaction.id
                )

            locked_transaction.gateway_session_id = paypal_order_id
            locked_transaction.gateway_transaction_id = paypal_capture_id
            locked_transaction.status = 'paid'
            locked_transaction.paid_at = timezone.now()
            locked_transaction.failure_reason = ''
            locked_transaction.save(update_fields=[
                'gateway_session_id',
                'gateway_transaction_id',
                'status',
                'paid_at',
                'failure_reason',
                'updated_at',
            ])

    except Exception as e:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"Database payment completion failed: {str(e)}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(
            request,
            "Payment was verified, but the system could not complete the payment record. "
            "Please contact support."
        )

        return redirect(
            'expat_life:foreigner_payment_failed',
            transaction_id=payment_transaction.id
        )

    try:
        refreshed_transaction = PaymentTransaction.objects.get(
            id=payment_transaction.id
        )

        send_foreigner_payment_invoice_email(
            payment_transaction=refreshed_transaction,
            request=request,
        )

    except Exception as e:
        refreshed_transaction = PaymentTransaction.objects.get(
            id=payment_transaction.id
        )

        refreshed_transaction.failure_reason = (
            f"{refreshed_transaction.failure_reason or ''}\n"
            f"Invoice email failed: {str(e)}"
        )
        refreshed_transaction.save(update_fields=[
            "failure_reason",
            "updated_at",
        ])

    request.session.pop('foreigner_payment_transaction_id', None)
    request.session.pop('foreigner_checkout_selected_ids', None)
    request.session.pop('foreigner_checkout_total', None)
    request.session.pop('foreigner_checkout_profile_type', None)
    request.session.pop('foreigner_use_wallet', None)
    request.session.pop('foreigner_wallet_deduction', None)

    messages.success(request, "PayPal payment completed successfully.")

    return redirect(
        'expat_life:foreigner_payment_success',
        transaction_id=payment_transaction.id
    )


#Wallet top up

@login_required
def foreigner_wallet_topup(request):
    """
    Guest / Foreigner direct wallet top-up page.

    No UserPayableItem is created here.
    User enters amount and selects Stripe or PayPal.
    """

    profile = getattr(request.user, 'foreigner_profile', None)

    if not profile:
        messages.error(
            request,
            "Guest wallet top-up is available only for registered Guest accounts."
        )
        return redirect('expat_life:home')

    profile_type = 'foreigner'
    wallet = get_or_create_wallet_account(request.user, profile_type)

    if request.method == 'POST':
        form = WalletTopUpForm(request.POST)

        if form.is_valid():
            amount_usd = form.cleaned_data['amount_usd']
            payment_method = form.cleaned_data['payment_method']

            request.session['wallet_topup_profile_type'] = profile_type
            request.session['wallet_topup_amount_usd'] = str(amount_usd)
            request.session['wallet_topup_return_url'] = 'expat_life:foreigner_wallet_topup'

            if payment_method == 'stripe':
                return redirect('expat_life:start_wallet_topup_stripe_checkout')

            if payment_method == 'paypal':
                return redirect('expat_life:start_wallet_topup_paypal_checkout')

            messages.error(request, "Please select a valid payment method.")
    else:
        form = WalletTopUpForm(initial={
            'payment_method': 'stripe',
        })

    return render(request, 'expat_life/foreigner_wallet_topup.html', {
        'form': form,
        'wallet': wallet,
        'profile': profile,
        'profile_type': profile_type,
        'page_title': 'Guest Wallet Top-up',
        'account_label': 'Guest Wallet',
    })

@login_required
def start_wallet_topup_stripe_checkout(request):
    profile_type = request.session.get('wallet_topup_profile_type')
    amount_usd = request.session.get('wallet_topup_amount_usd')
    return_url = request.session.get('wallet_topup_return_url', 'expat_life:home')

    if not profile_type or not amount_usd:
        messages.error(request, "No wallet top-up checkout details found.")
        return redirect(return_url)

    if not user_can_topup_wallet(request.user, profile_type):
        messages.error(
            request,
            "Wallet top-up is not available for this account type."
        )
        return redirect(return_url)

    try:
        amount_usd = Decimal(str(amount_usd)).quantize(Decimal('0.01'))
    except (InvalidOperation, TypeError, ValueError):
        messages.error(request, "Invalid wallet top-up amount.")
        return redirect(return_url)

    if amount_usd <= Decimal('0.00'):
        messages.error(request, "Wallet top-up amount must be greater than zero.")
        return redirect(return_url)

    if not settings.STRIPE_SECRET_KEY:
        messages.error(request, "Stripe payment is not configured.")
        return redirect(return_url)

    stripe.api_key = settings.STRIPE_SECRET_KEY

    try:
        payment_transaction = PaymentTransaction.objects.create(
            user=request.user,
            profile_type=profile_type,
            payment_purpose='wallet_topup',
            payment_method='stripe',
            total_amount_usd=amount_usd,
            wallet_deduction_usd=Decimal('0.00'),
            gateway_amount_usd=amount_usd,
            status='pending',
        )

        success_url = request.build_absolute_uri(
            reverse(
                'expat_life:foreigner_wallet_topup_stripe_success',
                kwargs={'transaction_id': payment_transaction.id}
            )
        ) + '?session_id={CHECKOUT_SESSION_ID}'

        cancel_url = request.build_absolute_uri(
            reverse(
                'expat_life:foreigner_wallet_topup_cancelled',
                kwargs={'transaction_id': payment_transaction.id}
            )
        )

        stripe_amount_cents = int(
            (amount_usd * Decimal('100')).quantize(Decimal('1'))
        )

        checkout_session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            mode='payment',
            line_items=[
                {
                    'price_data': {
                        'currency': 'usd',
                        'product_data': {
                            'name': 'Guest Wallet Top-up',
                            'description': f'Wallet top-up for Live in Sri Lanka Guest account. Transaction #{payment_transaction.id}',
                        },
                        'unit_amount': stripe_amount_cents,
                    },
                    'quantity': 1,
                }
            ],
            success_url=success_url,
            cancel_url=cancel_url,
            customer_email=request.user.email or None,
            client_reference_id=str(payment_transaction.id),
            metadata={
                'payment_transaction_id': str(payment_transaction.id),
                'user_id': str(request.user.id),
                'profile_type': profile_type,
                'payment_purpose': 'wallet_topup',
                'amount_usd': str(amount_usd),
            },
        )

        if not checkout_session.url:
            raise Exception("Stripe checkout URL was not returned.")

        payment_transaction.gateway_session_id = checkout_session.id
        payment_transaction.status = 'processing'
        payment_transaction.save(update_fields=[
            'gateway_session_id',
            'status',
            'updated_at',
        ])

        request.session['wallet_topup_transaction_id'] = payment_transaction.id

        return redirect(checkout_session.url)

    except Exception as e:
        messages.error(
            request,
            f"Stripe wallet top-up checkout could not be started. {str(e)}"
        )
        return redirect(return_url)

@login_required
def foreigner_wallet_topup_stripe_success(request, transaction_id):
    session_id = request.GET.get('session_id')

    if not session_id:
        messages.error(request, "Stripe wallet top-up session not found.")
        return redirect('expat_life:foreigner_wallet_topup_failed', transaction_id=transaction_id)

    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
        payment_purpose='wallet_topup',
    )

    if payment_transaction.status == 'paid':
        messages.success(request, "This wallet top-up has already been completed.")
        return redirect('expat_life:foreigner_wallet_topup')

    if payment_transaction.payment_method != 'stripe':
        messages.error(request, "Invalid payment method for Stripe wallet top-up.")
        return redirect('expat_life:foreigner_wallet_topup_failed', transaction_id=transaction_id)

    stripe.api_key = settings.STRIPE_SECRET_KEY

    try:
        stripe_session = stripe.checkout.Session.retrieve(session_id)

        metadata_transaction_id = None
        stripe_metadata = getattr(stripe_session, 'metadata', None)

        if stripe_metadata:
            try:
                stripe_metadata = dict(stripe_metadata)
                metadata_transaction_id = stripe_metadata.get('payment_transaction_id')
            except Exception:
                metadata_transaction_id = getattr(
                    stripe_metadata,
                    'payment_transaction_id',
                    None
                )

        if str(metadata_transaction_id) != str(payment_transaction.id):
            raise Exception("Stripe metadata transaction ID mismatch.")

        stripe_payment_status = getattr(stripe_session, 'payment_status', None)

        if stripe_payment_status != 'paid':
            raise Exception(f"Stripe payment status was not paid: {stripe_payment_status}")

        expected_amount_cents = int(
            (payment_transaction.gateway_amount_usd * Decimal('100')).quantize(Decimal('1'))
        )

        stripe_amount_total = getattr(stripe_session, 'amount_total', None)

        if stripe_amount_total is not None and int(stripe_amount_total) != expected_amount_cents:
            raise Exception(
                f"Stripe amount mismatch. Expected {expected_amount_cents}, received {stripe_amount_total}."
            )

        gateway_transaction_id = (
            getattr(stripe_session, 'payment_intent', '') or stripe_session.id
        )

        complete_wallet_topup_transaction(
            payment_transaction=payment_transaction,
            gateway_session_id=stripe_session.id,
            gateway_transaction_id=gateway_transaction_id,
        )

    except Exception as e:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"Stripe wallet top-up failed: {str(e)}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "Stripe wallet top-up could not be completed.")
        return redirect('expat_life:foreigner_wallet_topup_failed', transaction_id=payment_transaction.id)

    request.session.pop('wallet_topup_profile_type', None)
    request.session.pop('wallet_topup_amount_usd', None)
    request.session.pop('wallet_topup_return_url', None)
    request.session.pop('wallet_topup_transaction_id', None)

    messages.success(request, "Your Guest wallet has been topped up successfully.")
    return redirect('expat_life:foreigner_wallet_topup')

@login_required
def start_wallet_topup_paypal_checkout(request):
    profile_type = request.session.get('wallet_topup_profile_type')
    amount_usd = request.session.get('wallet_topup_amount_usd')
    return_url = request.session.get('wallet_topup_return_url', 'expat_life:home')

    if not profile_type or not amount_usd:
        messages.error(request, "No wallet top-up checkout details found.")
        return redirect(return_url)

    if not user_can_topup_wallet(request.user, profile_type):
        messages.error(
            request,
            "Wallet top-up is not available for this account type."
        )
        return redirect(return_url)

    try:
        amount_usd = Decimal(str(amount_usd)).quantize(Decimal('0.01'))
    except (InvalidOperation, TypeError, ValueError):
        messages.error(request, "Invalid wallet top-up amount.")
        return redirect(return_url)

    if amount_usd <= Decimal('0.00'):
        messages.error(request, "Wallet top-up amount must be greater than zero.")
        return redirect(return_url)

    try:
        payment_transaction = PaymentTransaction.objects.create(
            user=request.user,
            profile_type=profile_type,
            payment_purpose='wallet_topup',
            payment_method='paypal',
            total_amount_usd=amount_usd,
            wallet_deduction_usd=Decimal('0.00'),
            gateway_amount_usd=amount_usd,
            status='pending',
        )

        order_data = create_paypal_wallet_topup_order(payment_transaction, request)
        approval_url = get_paypal_approval_url(order_data)

        if not approval_url:
            raise Exception("PayPal approval URL not found.")

        payment_transaction.gateway_session_id = order_data.get('id', '')
        payment_transaction.status = 'processing'
        payment_transaction.save(update_fields=[
            'gateway_session_id',
            'status',
            'updated_at',
        ])

        request.session['wallet_topup_transaction_id'] = payment_transaction.id

        return redirect(approval_url)

    except Exception as e:
        messages.error(
            request,
            f"PayPal wallet top-up checkout could not be started. {str(e)}"
        )
        return redirect(return_url)
    
@login_required
def foreigner_wallet_topup_paypal_success(request, transaction_id):
    paypal_order_id = request.GET.get('token')

    if not paypal_order_id:
        messages.error(request, "PayPal wallet top-up order not found.")
        return redirect('expat_life:foreigner_wallet_topup_failed', transaction_id=transaction_id)

    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
        payment_purpose='wallet_topup',
    )

    if payment_transaction.status == 'paid':
        messages.success(request, "This wallet top-up has already been completed.")
        return redirect('expat_life:foreigner_wallet_topup')

    if payment_transaction.payment_method != 'paypal':
        messages.error(request, "Invalid payment method for PayPal wallet top-up.")
        return redirect('expat_life:foreigner_wallet_topup_failed', transaction_id=payment_transaction.id)

    if payment_transaction.gateway_session_id and payment_transaction.gateway_session_id != paypal_order_id:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = "PayPal wallet top-up order ID mismatch."
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "PayPal wallet top-up verification failed.")
        return redirect('expat_life:foreigner_wallet_topup_failed', transaction_id=payment_transaction.id)

    try:
        capture_data = capture_paypal_order(paypal_order_id)

        paypal_status = capture_data.get('status')

        if paypal_status != 'COMPLETED':
            raise Exception(f"PayPal payment status was not completed: {paypal_status}")

        purchase_units = capture_data.get('purchase_units', [])
        first_purchase_unit = purchase_units[0] if purchase_units else {}
        payments = first_purchase_unit.get('payments', {})
        captures = payments.get('captures', [])
        first_capture = captures[0] if captures else {}

        captured_amount = first_capture.get('amount', {})
        captured_value = Decimal(str(captured_amount.get('value', '0.00'))).quantize(Decimal('0.01'))
        captured_currency = captured_amount.get('currency_code')

        expected_amount = payment_transaction.gateway_amount_usd.quantize(Decimal('0.01'))

        if captured_currency != 'USD' or captured_value != expected_amount:
            raise Exception(
                f"PayPal amount mismatch. Expected USD {expected_amount}, "
                f"received {captured_currency} {captured_value}."
            )

        paypal_capture_id = first_capture.get('id', paypal_order_id)

        complete_wallet_topup_transaction(
            payment_transaction=payment_transaction,
            gateway_session_id=paypal_order_id,
            gateway_transaction_id=paypal_capture_id,
        )

    except Exception as e:
        payment_transaction.status = 'failed'
        payment_transaction.failure_reason = f"PayPal wallet top-up failed: {str(e)}"
        payment_transaction.failed_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'failure_reason',
            'failed_at',
            'updated_at',
        ])

        messages.error(request, "PayPal wallet top-up could not be completed.")
        return redirect('expat_life:foreigner_wallet_topup_failed', transaction_id=payment_transaction.id)

    request.session.pop('wallet_topup_profile_type', None)
    request.session.pop('wallet_topup_amount_usd', None)
    request.session.pop('wallet_topup_return_url', None)
    request.session.pop('wallet_topup_transaction_id', None)

    messages.success(request, "Your Guest wallet has been topped up successfully.")
    return redirect('expat_life:foreigner_wallet_topup')

@login_required
def foreigner_payment_success(request, transaction_id):
    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner'
    )

    return render(request, 'expat_life/foreigner_payment_success.html', {
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Successful',
    })

@login_required
def foreigner_payment_cancelled(request, transaction_id):
    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
    )

    if payment_transaction.status in ['pending', 'processing']:
        payment_transaction.status = 'cancelled'
        payment_transaction.cancelled_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'cancelled_at',
            'updated_at',
        ])

    messages.warning(
        request,
        "Payment was cancelled. Your selected payment items are still due."
    )

    return render(request, 'expat_life/foreigner_payment_cancelled.html', {
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Cancelled',
    })


@login_required
def foreigner_payment_failed(request, transaction_id):
    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
    )

    return render(request, 'expat_life/foreigner_payment_failed.html', {
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Failed',
    })


@login_required
def foreigner_wallet_topup_cancelled(request, transaction_id):
    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
        payment_purpose='wallet_topup',
    )

    if payment_transaction.status in ['pending', 'processing']:
        payment_transaction.status = 'cancelled'
        payment_transaction.cancelled_at = timezone.now()
        payment_transaction.save(update_fields=[
            'status',
            'cancelled_at',
            'updated_at',
        ])

    messages.warning(request, "Wallet top-up was cancelled. No amount was added to your wallet.")
    return redirect('expat_life:foreigner_wallet_topup')


@login_required
def foreigner_wallet_topup_failed(request, transaction_id):
    payment_transaction = get_object_or_404(
        PaymentTransaction,
        id=transaction_id,
        user=request.user,
        profile_type='foreigner',
        payment_purpose='wallet_topup',
    )

    messages.error(
        request,
        "Wallet top-up failed. Please try again or contact support if money was deducted."
    )

    return redirect('expat_life:foreigner_wallet_topup')


#END OF PAYMENT CHECKOUT

def host_experiences_home(request):
    """
    Guest-facing introduction page for Hosting Experiences.

    This explains romantic dinners, proposals, celebrations,
    birthday events, private dinners, honeymoon moments, and
    custom hosted experiences in Sri Lanka.
    """

    featured_venues = HostVenue.objects.filter(
        is_public=True,
        is_featured=True,
        listing_status=PublicListingStatus.APPROVED
    ).select_related(
        'host_profile'
    ).order_by('-updated_at')[:6]

    latest_venues = HostVenue.objects.filter(
        is_public=True,
        listing_status=PublicListingStatus.APPROVED
    ).select_related(
        'host_profile'
    ).order_by('-created_at')[:6]

    context = {
        'featured_venues': featured_venues,
        'latest_venues': latest_venues,
    }

    return render(
        request,
        'expat_life/host_experiences_home.html',
        context
    )

def guest_host_venue_list(request):
    """
    Public / guest-facing venue list for hosting experiences.
    Guests can browse venues before booking.
    """

    venues = HostVenue.objects.filter(
        is_public=True,
        listing_status=PublicListingStatus.APPROVED
    ).select_related(
        'host_profile'
    ).order_by('-is_featured', '-created_at')

    district = request.GET.get('district', '').strip()
    city = request.GET.get('city', '').strip()
    category = request.GET.get('category', '').strip()
    event_type = request.GET.get('event_type', '').strip()
    q = request.GET.get('q', '').strip()

    if district:
        venues = venues.filter(district=district)

    if city:
        venues = venues.filter(city=city)

    if category:
        venues = venues.filter(venue_category=category)

    if q:
        venues = venues.filter(
            Q(venue_name__icontains=q) |
            Q(short_description__icontains=q) |
            Q(full_description__icontains=q) |
            Q(city__icontains=q) |
            Q(district__icontains=q)
        )

    if event_type == 'romantic_dates':
        venues = venues.filter(supports_romantic_dates=True)
    elif event_type == 'proposal_events':
        venues = venues.filter(supports_proposal_events=True)
    elif event_type == 'anniversaries':
        venues = venues.filter(supports_anniversaries=True)
    elif event_type == 'birthdays':
        venues = venues.filter(supports_birthdays=True)
    elif event_type == 'honeymoon':
        venues = venues.filter(supports_honeymoon_experiences=True)
    elif event_type == 'private_dinners':
        venues = venues.filter(supports_private_dinners=True)
    elif event_type == 'engagements':
        venues = venues.filter(supports_engagement_events=True)
    elif event_type == 'small_weddings':
        venues = venues.filter(supports_small_weddings=True)
    elif event_type == 'custom':
        venues = venues.filter(supports_custom_celebrations=True)

    context = {
        'venues': venues,
        'district': district,
        'city': city,
        'category': category,
        'event_type': event_type,
        'q': q,
    }

    return render(
        request,
        'expat_life/guest_host_venue_list.html',
        context
    )

def guest_host_venue_detail(request, slug):
    """
    Guest-facing venue detail page.

    Shows venue details, event packages, meal plans, and add-on services.
    Booking/order flow will be added later.
    """

    venue = get_object_or_404(
        HostVenue.objects.select_related('host_profile'),
        slug=slug,
        is_public=True,
        listing_status=PublicListingStatus.APPROVED
    )

    event_packages = venue.event_packages.filter(
        is_active=True,
        listing_status=PublicListingStatus.APPROVED
    ).order_by('-is_featured', 'title')

    meal_plans = venue.meal_plans.filter(
        is_active=True,
        listing_status=PublicListingStatus.APPROVED
    ).order_by('-is_featured', 'title')

    add_on_services = venue.add_on_services.filter(
        is_active=True,
        listing_status=PublicListingStatus.APPROVED
    ).order_by('-is_featured', 'title')

    gallery_images = venue.gallery_images.all().order_by('display_order', '-created_at')

    related_venues = HostVenue.objects.filter(
        is_public=True,
        listing_status=PublicListingStatus.APPROVED,
        district=venue.district
    ).exclude(
        id=venue.id
    ).select_related(
        'host_profile'
    ).order_by('-is_featured', '-created_at')[:4]

    context = {
        'venue': venue,
        'event_packages': event_packages,
        'meal_plans': meal_plans,
        'add_on_services': add_on_services,
        'gallery_images': gallery_images,
        'related_venues': related_venues,
    }

    return render(
        request,
        'expat_life/guest_host_venue_detail.html',
        context
    )

@login_required
def guest_host_booking_start(request, slug):
    """
    Guest selects package, meal plan, add-ons, event date/time,
    and creates/updates one unpaid hosting booking order.

    This also creates/updates the matching UserPayableItem.
    """

    guest_profile = getattr(request.user, 'foreigner_profile', None)

    if not guest_profile:
        messages.error(
            request,
            "Only registered Guests can book hosting experiences from the Guest app."
        )
        return redirect('expat_life:guest_host_venue_detail', slug=slug)

    venue = get_object_or_404(
        HostVenue.objects.select_related('host_profile'),
        slug=slug,
        is_public=True,
        listing_status=PublicListingStatus.APPROVED
    )

    if request.method == 'POST':
        form = GuestHostBookingSelectionForm(request.POST, venue=venue)

        if form.is_valid():
            booking = create_or_update_guest_host_booking_order(
                user=request.user,
                venue=venue,
                selected_package=form.cleaned_data.get('selected_package'),
                selected_meal_plan=form.cleaned_data.get('selected_meal_plan'),
                selected_add_ons=form.cleaned_data.get('selected_add_ons'),
                event_type=form.cleaned_data.get('event_type'),
                preferred_event_date=form.cleaned_data.get('preferred_event_date'),
                preferred_start_time=form.cleaned_data.get('preferred_start_time'),
                expected_duration_hours=form.cleaned_data.get('expected_duration_hours'),
                number_of_guests=form.cleaned_data.get('number_of_guests'),
                occasion_title=form.cleaned_data.get('occasion_title'),
                occasion_note=form.cleaned_data.get('occasion_note'),
                special_requests=form.cleaned_data.get('special_requests'),
            )

            messages.success(
                request,
                "Your hosting experience booking has been prepared. Please review and confirm before going to payment."
            )

            return redirect(
                'expat_life:guest_host_booking_review',
                booking_id=booking.id
            )
    else:
        form = GuestHostBookingSelectionForm(venue=venue)

    event_packages = venue.event_packages.filter(
        is_active=True,
        listing_status=PublicListingStatus.APPROVED
    ).order_by('-is_featured', 'title')

    meal_plans = venue.meal_plans.filter(
        is_active=True,
        listing_status=PublicListingStatus.APPROVED
    ).order_by('-is_featured', 'title')

    add_on_services = venue.add_on_services.filter(
        is_active=True,
        listing_status=PublicListingStatus.APPROVED
    ).order_by('-is_featured', 'title')

    return render(request, 'expat_life/guest_host_booking_start.html', {
        'form': form,
        'venue': venue,
        'guest_profile': guest_profile,
        'event_packages': event_packages,
        'meal_plans': meal_plans,
        'add_on_services': add_on_services,
    })

@login_required
def guest_host_booking_review(request, booking_id):
    """
    Guest reviews prepared hosting booking before going to Payment Center.
    The payable item is already created/updated by the booking start view.
    """

    guest_profile = getattr(request.user, 'foreigner_profile', None)

    if not guest_profile:
        messages.error(
            request,
            "Only registered Guests can review hosting bookings from the Guest app."
        )
        return redirect('expat_life:home')

    booking = get_object_or_404(
        HostBookingRequest.objects.select_related(
            'venue',
            'host_profile',
            'selected_package',
            'selected_meal_plan',
            'payable_item',
            'guest_profile',
            'booked_by_user',
        ).prefetch_related(
            'selected_add_ons'
        ),
        id=booking_id,
        booked_by_user=request.user,
        guest_profile=guest_profile,
    )

    if booking.payment_status == HostBookingPaymentStatus.PAID:
        messages.info(
            request,
            "This hosting booking has already been paid and confirmed."
        )
        return redirect('expat_life:foreigner_payment_center')

    if request.method == 'POST':
        if booking.payable_item:
            messages.success(
                request,
                "Your hosting booking is ready for payment. Please complete payment from your Payment Center."
            )
            return redirect('expat_life:foreigner_payment_center')

        messages.error(
            request,
            "Unable to find the payable item for this booking. Please prepare the booking again."
        )
        return redirect(
            'expat_life:guest_host_booking_start',
            slug=booking.venue.slug
        )

    return render(request, 'expat_life/guest_host_booking_review.html', {
        'booking': booking,
        'venue': booking.venue,
        'guest_profile': guest_profile,
        'selected_add_ons': booking.selected_add_ons.all(),
    })

@login_required
def foreigner_host_event_booking_list(request):
    """
    Guest / Foreigner page to view their own host event bookings
    at any stage: payment due, paid, arranging, completed, cancelled, etc.
    """

    foreigner = getattr(request.user, 'foreigner_profile', None)

    if not foreigner:
        messages.error(request, "Guest profile not found.")
        return redirect('expat_life:home')

    status_filter = request.GET.get('status', '').strip()
    payment_status_filter = request.GET.get('payment_status', '').strip()

    bookings = (
        HostBookingRequest.objects
        .filter(booked_by_user=request.user)
        .select_related(
            'venue',
            'host_profile',
            'selected_package',
            'selected_meal_plan',
            'payable_item',
        )
        .prefetch_related('selected_add_ons')
        .order_by('-submitted_at')
    )

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

    if payment_status_filter:
        bookings = bookings.filter(payment_status=payment_status_filter)

    return render(request, 'expat_life/foreigner_host_event_booking_list.html', {
        'bookings': bookings,
        'profile': foreigner,
        'page_title': 'My Host Event Bookings',
        'status_filter': status_filter,
        'payment_status_filter': payment_status_filter,
        'booking_status_choices': HostBookingRequest._meta.get_field('status').choices,
        'payment_status_choices': HostBookingRequest._meta.get_field('payment_status').choices,
    })