import random
import re
import string
from decimal import Decimal
from expat_life.email_services import send_host_signup_welcome_email
from django.contrib import messages
from django.contrib.auth import login, logout, update_session_auth_hash
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.db import transaction
from django.http import HttpResponseForbidden, JsonResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse_lazy
from django.urls import reverse

from .forms import (
    HostSignupForm,
    HostProfileForm,
    HostProfileImageForm,
    HostUsernameChangeForm,
    StyledHostPasswordChangeForm,
    HostPasswordResetForm,
    HostingClientPasswordResetForm,
    HostVenueForm, 
    HostVenueImageForm,
    HostEventPackageForm,
    HostMealPlanForm,
    HostAddOnServiceForm,
    HostBankingDetailsForm,
    HostingClientSignupForm,
    HostingClientProfileForm,
    HostingClientProfileImageForm,
    HostingClientUsernameChangeForm,
    StyledHostingClientPasswordChangeForm,
    
)

from django.contrib.auth.views import (
    LoginView,
    PasswordResetView,
    PasswordResetDoneView,
    PasswordResetConfirmView,
    PasswordResetCompleteView,
)

from .models import (
    HostProfile, 
    HostVenue, 
    HostVenueImage, 
    HostEventPackage,
    HostMealPlan,
    HostAddOnService,
    HostBankingDetails,
    HostBookingRequest,
    HostingClientProfile, 
    HostingPartnerGuidanceResource,
)


from .models import (
    PublicListingStatus, 
    ApprovalStatus, 
    VenueCategory, 
    HostBookingPaymentStatus, 
    BookingRequestStatus,
    HostingClientType,
)
from common.choices import SRI_LANKA_CITY_CHOICES, SRI_LANKA_DISTRICT_CHOICES

from django.views.decorators.http import require_POST
from expat_life.forms import ContactMessageForm
from expat_life.models import WalletAccount
from django.core.paginator import Paginator
from django.db.models import Q, Count, Sum
import stripe
import requests
from django.conf import settings
from django.utils import timezone
from expat_life.models import (
    UserPayableItem,
    WalletAccount,
    PaymentTransaction,
    PaymentTransactionItem,
)

from expat_life.utils import (
    update_hosting_partner_payable_items,
    mark_hosting_partner_featured_fee_paid,
    mark_hosting_partner_transaction_items_paid,
)

from .utils import (
    get_or_create_hosting_client_profile_for_user, 
    create_or_update_local_client_host_booking_order,
    mark_hosting_client_transaction_items_paid,
)

from common.payment_gateway_services import (
    get_paypal_access_token,
    get_paypal_base_url,
    get_paypal_approval_url,
    capture_paypal_order,
)

from expat_life.forms import GuestHostBookingSelectionForm
from expat_life.email_services import send_hosting_client_signup_welcome_email

@login_required
def switch_hosting_portal(request, portal):
    """
    Switch active hosting portal mode for users who have both host/client access.
    """

    if portal == 'host':
        if not hasattr(request.user, 'host_profile'):
            messages.error(request, "You do not have a Hosting Partner profile.")
            return redirect('hosting_app:home_hosting')

        request.session['active_hosting_portal'] = 'host'
        messages.success(request, "Switched to Hosting Partner portal.")
        return redirect('hosting_app:host_dashboard')

    if portal == 'client':
        if not hasattr(request.user, 'hosting_client_profile'):
            messages.error(request, "You do not have a Hosting Client profile.")
            return redirect('hosting_app:home_hosting')

        request.session['active_hosting_portal'] = 'client'
        messages.success(request, "Switched to Hosting Client portal.")
        return redirect('hosting_app:hosting_client_dashboard')

    messages.error(request, "Invalid hosting portal.")
    return redirect('hosting_app:home_hosting')

def get_logged_in_host_profile(request):
    """
    Returns the logged-in user's HostProfile or None.
    """
    if not request.user.is_authenticated:
        return None

    return getattr(request.user, 'host_profile', None)

def get_or_create_host_wallet(host_profile):
    wallet, created = WalletAccount.objects.get_or_create(
        user=host_profile.user,
        profile_type='hosting_partner',
        defaults={
            'balance_usd': 0,
            'is_active': True,
        }
    )

    return wallet

"""
WalletTransaction.objects.create(
    wallet=host_wallet,
    transaction_type='hosting_partner_income',
    status='completed',
    title='Hosting Partner Income',
    description='Income from completed hosting booking HOST-XXXX.',
    amount_usd=host_net_amount,
    is_credit=True,
    reference_code=order.order_code,
)
"""

def home_hosting(request):
    return render(request, 'hosting_app/home_hosting.html')

def about_us_hosting(request):
    return render(request, 'hosting_app/about_us_hosting.html')

def terms_conditions(request):
    return render(request, 'hosting_app/terms_conditions.html')

def faq(request):
    return render(request, 'hosting_app/faq.html')

def privacy_policy(request):
    return render(request, 'hosting_app/privacy_policy.html')

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

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

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

def contact_page(request):
    if request.method == 'POST':
        form = ContactMessageForm(request.POST)

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

            return redirect(
                reverse('hosting_app:success_page') +
                '?type=contact'
            )
    else:
        form = ContactMessageForm()

    return render(
        request,
        'hosting_app/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': 'hosting_app:home_hosting',
            'button_2_text': 'About Ensolanka',
            'button_2_url': 'hosting_app:about_us_hosting',
        },
        'signup': {
            'title': 'Signup Submitted',
            'heading': 'Your Hosting Partner Signup Has Been Submitted',
            'message': 'Thank you for sharing your details. We have received your information successfully and created your Hosting Partner account.',
            'button_1_text': 'Go to Home',
            'button_1_url': 'hosting_app:home_hosting',
            'button_2_text': 'My Host Dashboard',
            'button_2_url': 'hosting_app:host_dashboard',
        },
        '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': 'hosting_app:home_hosting',
            'button_2_text': 'Contact Us',
            'button_2_url': 'hosting_app:contact_page',
        },
    }

    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,
        'hosting_app/success_page.html',
        context
    )

# ============================================================
# Hosting Partner Password Reset
# ============================================================

class HostPasswordResetView(PasswordResetView):
    template_name = 'registration/host_password_reset.html'
    form_class = HostPasswordResetForm

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

    success_url = reverse_lazy('hosting_app:host_password_reset_done')
    from_email = "Host in Sri Lanka <dsjayathunge@gmail.com>"

    def get_extra_email_context(self):
        return {
            "site_url": self.request.build_absolute_uri("/"),
            "tagline": "Be the place couples choose.",
        }

    def form_valid(self, form):
        self.extra_email_context = self.get_extra_email_context()
        email = form.cleaned_data.get('email')

        user_exists_as_host = User.objects.filter(
            email__iexact=email,
            host_profile__isnull=False,
            is_active=True
        ).exists()

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

        return super().form_valid(form)


class HostPasswordResetDoneView(PasswordResetDoneView):
    template_name = 'registration/host_password_reset_done.html'


class HostPasswordResetConfirmView(PasswordResetConfirmView):
    template_name = 'registration/host_password_reset_confirm.html'
    success_url = reverse_lazy('hosting_app:host_password_reset_complete')


class HostPasswordResetCompleteView(PasswordResetCompleteView):
    template_name = 'registration/host_password_reset_complete.html'

#===========================================================
# Password reset Local Hosting Client
#=========================================================

class HostingClientPasswordResetView(PasswordResetView):
    template_name = 'registration/hosting_client_password_reset.html'
    form_class = HostingClientPasswordResetForm

    email_template_name = 'emails/hosting_app/client_password_reset_email.txt'
    html_email_template_name = 'emails/hosting_app/client_password_reset_email.html'
    subject_template_name = 'emails/hosting_app/client_password_reset_subject.txt'

    success_url = reverse_lazy('hosting_app:hosting_client_password_reset_done')
    from_email = "Host in Sri Lanka <dsjayathunge@gmail.com>"

    def get_extra_email_context(self):
        return {
            "site_url": self.request.build_absolute_uri("/"),
            "tagline": "Plan beautiful moments with trusted local hosts.",
            "account_role": "Hosting Client",
        }

    def form_valid(self, form):
        self.extra_email_context = self.get_extra_email_context()
        email = form.cleaned_data.get('email')

        user_exists_as_client = User.objects.filter(
            email__iexact=email,
            hosting_client_profile__isnull=False,
            is_active=True
        ).exists()

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

        return super().form_valid(form)


class HostingClientPasswordResetDoneView(PasswordResetDoneView):
    template_name = 'registration/hosting_client_password_reset_done.html'


class HostingClientPasswordResetConfirmView(PasswordResetConfirmView):
    template_name = 'registration/hosting_client_password_reset_confirm.html'
    success_url = reverse_lazy('hosting_app:hosting_client_password_reset_complete')


class HostingClientPasswordResetCompleteView(PasswordResetCompleteView):
    template_name = 'registration/hosting_client_password_reset_complete.html'

# ============================================================
# Username / Password Helpers
# ============================================================

def generate_host_username(contact_person_name):
    """
    Generate a unique username for hosting partners.
    Example:
    contact_person_name = 'Nimal Perera'
    username = 'host_nimalperera'
    """
    base_name = re.sub(r'[^a-zA-Z0-9]', '', contact_person_name.lower())

    if not base_name:
        base_name = 'partner'

    base = f"host_{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))


# ============================================================
# Host Signup
# ============================================================

@transaction.atomic
def host_signup(request):
    if request.method == 'POST':
        form = HostSignupForm(request.POST, request.FILES)

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

            email = form.cleaned_data['email'].strip().lower()
            contact_person_name = form.cleaned_data['contact_person_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_host_username(contact_person_name)
                password = generate_random_password()

                name_parts = contact_person_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
                )

                host_profile.user = user
                host_profile.email = email

                # Recommended for hosting app:
                # Host account is created, but approval remains pending.
                host_profile.status = 'pending'
                host_profile.is_active = True

                host_profile.save()

                transaction.on_commit(
                    lambda: send_host_signup_welcome_email(
                        user=user,
                        contact_person_name=contact_person_name,
                        email=email,
                        username=username,
                        temporary_password=password,
                        request=request,
                    )
                )

                login(request, user)
                request.session['active_hosting_portal'] = 'host'
                update_hosting_partner_payable_items(user)

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

                messages.success(
                    request,
                    "Your Hosting Partner account has been created successfully."
                )

                return redirect('hosting_app:host_dashboard')

        else:
            messages.error(
                request,
                "Please correct the errors below and try again."
            )

    else:
        form = HostSignupForm()

    return render(
        request,
        'hosting_app/host_signup.html',
        {
            'form': form
        }
    )


# ============================================================
# Host Dashboard
# ============================================================

@login_required
def host_dashboard(request):
    host = getattr(request.user, 'host_profile', None)

    if host is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Partner profile."
        )

    venues = host.venues.prefetch_related(
        'gallery_images',
        'event_packages',
        'meal_plans',
        'add_on_services',
    ).all()

    total_venues = venues.count()
    approved_venues = venues.filter(
        listing_status='approved'
    ).count()
    pending_venues = venues.filter(
        listing_status='pending_review'
    ).count()
    public_venues = venues.filter(
        is_public=True
    ).count()

    total_packages = sum(
        venue.event_packages.count()
        for venue in venues
    )

    approved_packages = sum(
        venue.event_packages.filter(
            listing_status='approved'
        ).count()
        for venue in venues
    )

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

    has_affiliate_profile = hasattr(
        request.user,
        'affiliate_profile'
    )

    has_property_manager_profile = hasattr(
        request.user,
        'property_manager_client_profile'
    )

    return render(
        request,
        'hosting_app/host_dashboard.html',
        {
            'host': host,
            'venues': venues,

            'total_venues': total_venues,
            'approved_venues': approved_venues,
            'pending_venues': pending_venues,
            'public_venues': public_venues,

            'total_packages': total_packages,
            'approved_packages': approved_packages,

            'default_profile_image': default_profile_image,

            'has_affiliate_profile': has_affiliate_profile,
            'has_property_manager_profile': has_property_manager_profile,

            '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),
        }
    )


# ============================================================
# Host Login View
# ============================================================

class HostLoginView(LoginView):
    template_name = 'registration/host_login.html'

    def get_form(self, form_class=None):
        form = super().get_form(form_class)

        form.fields['username'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Enter your username'
        })

        form.fields['password'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Enter your password'
        })

        return form

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

        host = getattr(user, 'host_profile', None)

        if host:
            return response

        messages.error(
            self.request,
            "This login is only for Hosting Partners. Please use the correct login page."
        )

        logout(self.request)

        return redirect('hosting_app:host_login')

    def get_success_url(self):
        return self.get_redirect_url() or reverse_lazy(
            'hosting_app:host_dashboard'
        )
    
# ============================================================
# Hosting Partner Profile Page
# ============================================================

@login_required
def host_profile_page(request):
    host = getattr(request.user, 'host_profile', None)

    if host is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Partner profile."
        )

    return render(
        request,
        'hosting_app/host_profile_page.html',
        {
            'host': host,
            'default_profile_image': 'expat_life/images/default-profile-neutral.png',
        }
    )


# ============================================================
# Edit Hosting Partner Profile
# ============================================================

@login_required
def edit_host_profile(request):
    host = getattr(request.user, 'host_profile', None)

    if host is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Partner profile."
        )

    if request.method == 'POST':
        form = HostProfileForm(request.POST, instance=host)

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

            # Sync contact person's name to the linked Django User
            contact_person_name = form.cleaned_data.get(
                'contact_person_name',
                ''
            ).strip()

            name_parts = contact_person_name.split()

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

            # Keep auth user email aligned with HostProfile email
            email = form.cleaned_data.get('email', '').strip().lower()
            request.user.email = email

            request.user.save()

            host_profile.email = email
            host_profile.save()

            messages.success(
                request,
                "Your Hosting Partner profile has been updated successfully."
            )

            return redirect('hosting_app:host_profile_page')

    else:
        form = HostProfileForm(instance=host)

    return render(
        request,
        'hosting_app/edit_host_profile.html',
        {
            'form': form,
            'host': host,
        }
    )


# ============================================================
# Upload Hosting Partner Profile Image
# ============================================================

@login_required
@require_POST
def upload_host_profile_image(request):
    host = getattr(request.user, 'host_profile', None)

    if host is None:
        return JsonResponse(
            {
                'success': False,
                'error': 'You do not have a Hosting Partner profile.'
            },
            status=403
        )

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

    form = HostProfileImageForm(
        request.POST,
        request.FILES,
        instance=host
    )

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

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

    error_list = []

    for field_errors in form.errors.values():
        error_list.extend(field_errors)

    return JsonResponse(
        {
            'success': False,
            'error': (
                ' '.join(error_list)
                if error_list
                else 'Image upload failed.'
            ),
        },
        status=400
    )


# ============================================================
# Change Hosting Partner Username
# ============================================================

@login_required
def change_host_username(request):
    host = getattr(request.user, 'host_profile', None)

    if host is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Partner profile."
        )

    if request.method == 'POST':
        form = HostUsernameChangeForm(
            request.user,
            request.POST
        )

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

            messages.success(
                request,
                "Your username has been updated successfully."
            )

            return redirect('hosting_app:host_profile_page')

    else:
        form = HostUsernameChangeForm(request.user)

    return render(
        request,
        'hosting_app/change_host_username.html',
        {
            'form': form,
        }
    )


# ============================================================
# Change Hosting Partner Password
# ============================================================

@login_required
def change_host_password(request):
    host = getattr(request.user, 'host_profile', None)

    if host is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Partner profile."
        )

    if request.method == 'POST':
        form = StyledHostPasswordChangeForm(
            request.user,
            request.POST
        )

        if form.is_valid():
            user = form.save()

            update_session_auth_hash(request, user)

            messages.success(
                request,
                "Your password has been updated successfully."
            )

            return redirect('hosting_app:host_profile_page')

    else:
        form = StyledHostPasswordChangeForm(request.user)

    return render(
        request,
        'hosting_app/change_host_password.html',
        {
            'form': form,
        }
    )

@login_required
def host_venue_list(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    venues = HostVenue.objects.filter(
        host_profile=host_profile
    ).order_by('-is_featured', '-created_at')

    public_count = venues.filter(is_public=True).count()
    featured_count = venues.filter(is_featured=True).count()

    gallery_ready_count = venues.filter(
        gallery_images__isnull=False
    ).distinct().count()

    return render(request, 'hosting_app/host_venue_list.html', {
        'host_profile': host_profile,
        'venues': venues,
        'public_count': public_count,
        'featured_count': featured_count,
        'gallery_ready_count': gallery_ready_count,
    })

@login_required
def host_venue_create(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    if request.method == 'POST':
        form = HostVenueForm(request.POST, request.FILES)

        if form.is_valid():
            venue = form.save(commit=False)
            venue.host_profile = host_profile
            venue.is_featured = host_profile.is_featured

            # If your model has listing_status, keep newly-created listings as draft/pending.
            if hasattr(venue, 'listing_status') and not venue.listing_status:
                venue.listing_status = PublicListingStatus.DRAFT

            venue.save()
            form.save_m2m()

            messages.success(
                request,
                "Your venue has been created successfully. You can now add gallery images or create event packages."
            )

            return redirect(
                'hosting_app:host_venue_detail',
                slug=venue.slug
            )
    else:
        form = HostVenueForm()

    return render(request, 'hosting_app/host_venue_form.html', {
        'form': form,
        'host_profile': host_profile,
        'page_title': 'Add New Venue',
        'submit_text': 'Create Venue',
        'is_update': False,
    })

@login_required
def host_venue_detail(request, slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    venue = get_object_or_404(
        HostVenue,
        slug=slug,
        host_profile=host_profile
    )

    gallery_images = venue.gallery_images.all()

    event_packages = getattr(
        venue,
        'event_packages',
        HostVenue.objects.none()
    )

    meal_plans = getattr(
        venue,
        'meal_plans',
        HostVenue.objects.none()
    )

    add_on_services = getattr(
        venue,
        'add_on_services',
        HostVenue.objects.none()
    )

    return render(request, 'hosting_app/host_venue_detail.html', {
        'host_profile': host_profile,
        'venue': venue,
        'gallery_images': gallery_images,
        'event_packages': event_packages.all() if hasattr(event_packages, 'all') else [],
        'meal_plans': meal_plans.all() if hasattr(meal_plans, 'all') else [],
        'add_on_services': add_on_services.all() if hasattr(add_on_services, 'all') else [],
    })

@login_required
def host_venue_update(request, slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    venue = get_object_or_404(
        HostVenue,
        slug=slug,
        host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostVenueForm(request.POST, request.FILES, instance=venue)

        if form.is_valid():
            venue = form.save(commit=False)
            venue.host_profile = host_profile

            # Optional: if the listing was already approved, you may want admin review again.
            # Keep this commented unless you want every edit to return to draft/review.
            #
            # if hasattr(venue, 'listing_status') and venue.listing_status == 'approved':
            #     venue.listing_status = 'draft'
            #     venue.approved_at = None

            venue.save()
            form.save_m2m()

            messages.success(
                request,
                "Your venue has been updated successfully."
            )

            return redirect(
                'hosting_app:host_venue_detail',
                slug=venue.slug
            )
    else:
        form = HostVenueForm(instance=venue)

    return render(request, 'hosting_app/host_venue_form.html', {
        'form': form,
        'host_profile': host_profile,
        'venue': venue,
        'page_title': 'Edit Venue',
        'submit_text': 'Save Venue',
        'is_update': True,
    })

@login_required
def host_venue_gallery_manage(request, slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    venue = get_object_or_404(
        HostVenue,
        slug=slug,
        host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostVenueImageForm(request.POST, request.FILES)

        if form.is_valid():
            gallery_image = form.save(commit=False)
            gallery_image.venue = venue
            gallery_image.save()

            messages.success(
                request,
                "Venue image has been added successfully."
            )

            return redirect(
                'hosting_app:host_venue_gallery_manage',
                slug=venue.slug
            )
    else:
        form = HostVenueImageForm()

    gallery_images = venue.gallery_images.all()

    return render(request, 'hosting_app/host_venue_gallery_manage.html', {
        'host_profile': host_profile,
        'venue': venue,
        'form': form,
        'gallery_images': gallery_images,
    })

@login_required
def host_venue_gallery_delete(request, pk):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    gallery_image = get_object_or_404(
        HostVenueImage,
        pk=pk,
        venue__host_profile=host_profile
    )

    venue = gallery_image.venue

    if request.method == 'POST':
        gallery_image.delete()

        messages.success(
            request,
            "Venue image has been deleted successfully."
        )

        return redirect(
            'hosting_app:host_venue_gallery_manage',
            slug=venue.slug
        )

    return render(request, 'hosting_app/host_venue_gallery_confirm_delete.html', {
        'host_profile': host_profile,
        'venue': venue,
        'gallery_image': gallery_image,
    })

def public_host_venue_list(request):
    venues = HostVenue.objects.filter(
        is_public=True,
        listing_status=PublicListingStatus.APPROVED,
        host_profile__status=ApprovalStatus.APPROVED,
        host_profile__is_active=True,
    ).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_experiences':
        venues = venues.filter(supports_honeymoon_experiences=True)
    elif event_type == 'private_dinners':
        venues = venues.filter(supports_private_dinners=True)
    elif event_type == 'engagement_events':
        venues = venues.filter(supports_engagement_events=True)
    elif event_type == 'small_weddings':
        venues = venues.filter(supports_small_weddings=True)
    elif event_type == 'custom_celebrations':
        venues = venues.filter(supports_custom_celebrations=True)

    paginator = Paginator(venues, 12)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    event_type_choices = [
        ('romantic_dates', 'Romantic Dates'),
        ('proposal_events', 'Proposal Events'),
        ('anniversaries', 'Anniversaries'),
        ('birthdays', 'Birthdays'),
        ('honeymoon_experiences', 'Honeymoon Experiences'),
        ('private_dinners', 'Private Dinners'),
        ('engagement_events', 'Engagement Events'),
        ('small_weddings', 'Small Weddings'),
        ('custom_celebrations', 'Custom Celebrations'),
    ]

    return render(request, 'hosting_app/public_host_venue_list.html', {
        'venues': page_obj,
        'page_obj': page_obj,
        'district': district,
        'city': city,
        'category': category,
        'event_type': event_type,
        'q': q,
        'event_type_choices': event_type_choices,
        'venue_category_choices': VenueCategory.choices,
        'district_choices': SRI_LANKA_DISTRICT_CHOICES,
        'city_choices': SRI_LANKA_CITY_CHOICES,
    })

def public_host_venue_detail(request, slug):
    venue = get_object_or_404(
        HostVenue.objects.select_related('host_profile'),
        slug=slug,
        is_public=True,
        listing_status=PublicListingStatus.APPROVED,
        host_profile__status=ApprovalStatus.APPROVED,
        host_profile__is_active=True,
    )

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

    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, 'hosting_app/public_host_venue_detail.html', {
        'venue': venue,
        'gallery_images': gallery_images,
        'event_packages': event_packages,
        'meal_plans': meal_plans,
        'add_on_services': add_on_services,
    })

@login_required
def host_event_package_list(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    packages = HostEventPackage.objects.filter(
        venue__host_profile=host_profile
    ).select_related(
        'venue'
    ).order_by('-is_featured', '-created_at')

    total_count = packages.count()
    active_count = packages.filter(is_active=True).count()
    featured_count = packages.filter(is_featured=True).count()
    public_ready_count = packages.filter(
        listing_status=PublicListingStatus.APPROVED,
        is_active=True,
    ).count()

    return render(request, 'hosting_app/host_event_package_list.html', {
        'host_profile': host_profile,
        'packages': packages,
        'total_count': total_count,
        'active_count': active_count,
        'featured_count': featured_count,
        'public_ready_count': public_ready_count,
    })

@login_required
def host_event_package_create(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    host_venues = HostVenue.objects.filter(host_profile=host_profile)

    if not host_venues.exists():
        messages.warning(
            request,
            "Please create a venue before creating an event package."
        )
        return redirect('hosting_app:host_venue_create')

    if request.method == 'POST':
        form = HostEventPackageForm(
            request.POST,
            request.FILES,
            host_profile=host_profile
        )

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

            # Safety check: prevent creating package for another host's venue.
            if event_package.venue.host_profile != host_profile:
                return HttpResponseForbidden("You cannot create a package for this venue.")

            event_package.save()
            form.save_m2m()

            messages.success(
                request,
                "Your event package has been created successfully."
            )

            return redirect(
                'hosting_app:host_event_package_detail',
                slug=event_package.slug
            )
    else:
        form = HostEventPackageForm(host_profile=host_profile)

    return render(request, 'hosting_app/host_event_package_form.html', {
        'form': form,
        'host_profile': host_profile,
        'page_title': 'Create Event Package',
        'submit_text': 'Create Package',
        'is_update': False,
        'selected_venue': None,
    })

@login_required
def host_event_package_create_for_venue(request, venue_slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    venue = get_object_or_404(
        HostVenue,
        slug=venue_slug,
        host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostEventPackageForm(
            request.POST,
            request.FILES,
            host_profile=host_profile,
            selected_venue=venue
        )

        if form.is_valid():
            event_package = form.save(commit=False)
            event_package.venue = venue
            event_package.save()
            form.save_m2m()

            messages.success(
                request,
                f"Your event package for {venue.venue_name} has been created successfully."
            )

            return redirect(
                'hosting_app:host_event_package_detail',
                slug=event_package.slug
            )
    else:
        form = HostEventPackageForm(
            host_profile=host_profile,
            selected_venue=venue
        )

    return render(request, 'hosting_app/host_event_package_form.html', {
        'form': form,
        'host_profile': host_profile,
        'venue': venue,
        'selected_venue': venue,
        'page_title': f'Create Package for {venue.venue_name}',
        'submit_text': 'Create Package',
        'is_update': False,
    })

@login_required
def host_event_package_detail(request, slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    event_package = get_object_or_404(
        HostEventPackage.objects.select_related('venue'),
        slug=slug,
        venue__host_profile=host_profile
    )

    return render(request, 'hosting_app/host_event_package_detail.html', {
        'host_profile': host_profile,
        'event_package': event_package,
        'venue': event_package.venue,
    })

@login_required
def host_event_package_update(request, slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    event_package = get_object_or_404(
        HostEventPackage.objects.select_related('venue'),
        slug=slug,
        venue__host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostEventPackageForm(
            request.POST,
            request.FILES,
            instance=event_package,
            host_profile=host_profile
        )

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

            # Safety check
            if updated_package.venue.host_profile != host_profile:
                return HttpResponseForbidden("You cannot move this package to another host's venue.")

            updated_package.save()
            form.save_m2m()

            messages.success(
                request,
                "Your event package has been updated successfully."
            )

            return redirect(
                'hosting_app:host_event_package_detail',
                slug=updated_package.slug
            )
    else:
        form = HostEventPackageForm(
            instance=event_package,
            host_profile=host_profile
        )

    return render(request, 'hosting_app/host_event_package_form.html', {
        'form': form,
        'host_profile': host_profile,
        'event_package': event_package,
        'venue': event_package.venue,
        'selected_venue': event_package.venue,
        'page_title': 'Edit Event Package',
        'submit_text': 'Save Package',
        'is_update': True,
    })

@login_required
def host_meal_plan_list(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    meal_plans = HostMealPlan.objects.filter(
        venue__host_profile=host_profile
    ).select_related(
        'venue'
    ).order_by('-is_featured', 'title')

    total_count = meal_plans.count()
    active_count = meal_plans.filter(is_active=True).count()
    featured_count = meal_plans.filter(is_featured=True).count()
    public_ready_count = meal_plans.filter(
        listing_status=PublicListingStatus.APPROVED,
        is_active=True,
    ).count()

    return render(request, 'hosting_app/host_meal_plan_list.html', {
        'host_profile': host_profile,
        'meal_plans': meal_plans,
        'total_count': total_count,
        'active_count': active_count,
        'featured_count': featured_count,
        'public_ready_count': public_ready_count,
    })

@login_required
def host_meal_plan_create(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    host_venues = HostVenue.objects.filter(host_profile=host_profile)

    if not host_venues.exists():
        messages.warning(
            request,
            "Please create a venue before adding a meal plan."
        )
        return redirect('hosting_app:host_venue_create')

    if request.method == 'POST':
        form = HostMealPlanForm(
            request.POST,
            request.FILES,
            host_profile=host_profile
        )

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

            if meal_plan.venue.host_profile != host_profile:
                return HttpResponseForbidden("You cannot create a meal plan for this venue.")

            meal_plan.save()
            form.save_m2m()

            messages.success(
                request,
                "Your meal plan has been created successfully."
            )

            return redirect(
                'hosting_app:host_meal_plan_detail',
                pk=meal_plan.pk
            )
    else:
        form = HostMealPlanForm(host_profile=host_profile)

    return render(request, 'hosting_app/host_meal_plan_form.html', {
        'form': form,
        'host_profile': host_profile,
        'page_title': 'Create Meal Plan',
        'submit_text': 'Create Meal Plan',
        'is_update': False,
        'selected_venue': None,
    })

@login_required
def host_meal_plan_create_for_venue(request, venue_slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    venue = get_object_or_404(
        HostVenue,
        slug=venue_slug,
        host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostMealPlanForm(
            request.POST,
            request.FILES,
            host_profile=host_profile,
            selected_venue=venue
        )

        if form.is_valid():
            meal_plan = form.save(commit=False)
            meal_plan.venue = venue
            meal_plan.save()
            form.save_m2m()

            messages.success(
                request,
                f"Your meal plan for {venue.venue_name} has been created successfully."
            )

            return redirect(
                'hosting_app:host_meal_plan_detail',
                pk=meal_plan.pk
            )
    else:
        form = HostMealPlanForm(
            host_profile=host_profile,
            selected_venue=venue
        )

    return render(request, 'hosting_app/host_meal_plan_form.html', {
        'form': form,
        'host_profile': host_profile,
        'venue': venue,
        'selected_venue': venue,
        'page_title': f'Create Meal Plan for {venue.venue_name}',
        'submit_text': 'Create Meal Plan',
        'is_update': False,
    })

@login_required
def host_meal_plan_detail(request, pk):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    meal_plan = get_object_or_404(
        HostMealPlan.objects.select_related('venue'),
        pk=pk,
        venue__host_profile=host_profile
    )

    
    minimum_total_usd = (
        meal_plan.price_per_person_usd * meal_plan.minimum_people
    )

    return render(request, 'hosting_app/host_meal_plan_detail.html', {
        'host_profile': host_profile,
        'meal_plan': meal_plan,
        'venue': meal_plan.venue,
        'minimum_total_usd': minimum_total_usd,
    })

@login_required
def host_meal_plan_update(request, pk):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    meal_plan = get_object_or_404(
        HostMealPlan.objects.select_related('venue'),
        pk=pk,
        venue__host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostMealPlanForm(
            request.POST,
            request.FILES,
            instance=meal_plan,
            host_profile=host_profile
        )

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

            if updated_meal_plan.venue.host_profile != host_profile:
                return HttpResponseForbidden("You cannot move this meal plan to another host's venue.")

            updated_meal_plan.save()
            form.save_m2m()

            messages.success(
                request,
                "Your meal plan has been updated successfully."
            )

            return redirect(
                'hosting_app:host_meal_plan_detail',
                pk=updated_meal_plan.pk
            )
    else:
        form = HostMealPlanForm(
            instance=meal_plan,
            host_profile=host_profile
        )

    return render(request, 'hosting_app/host_meal_plan_form.html', {
        'form': form,
        'host_profile': host_profile,
        'meal_plan': meal_plan,
        'venue': meal_plan.venue,
        'selected_venue': meal_plan.venue,
        'page_title': 'Edit Meal Plan',
        'submit_text': 'Save Meal Plan',
        'is_update': True,
    })


# ============================================================
# Host Add-on Service Management
# ============================================================

@login_required
def host_add_on_service_list(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    add_on_services = HostAddOnService.objects.filter(
        venue__host_profile=host_profile
    ).select_related(
        'venue'
    ).order_by('-is_featured', 'title')

    total_count = add_on_services.count()
    active_count = add_on_services.filter(is_active=True).count()
    featured_count = add_on_services.filter(is_featured=True).count()
    public_ready_count = add_on_services.filter(
        listing_status=PublicListingStatus.APPROVED,
        is_active=True,
    ).count()

    return render(request, 'hosting_app/host_add_on_service_list.html', {
        'host_profile': host_profile,
        'add_on_services': add_on_services,
        'total_count': total_count,
        'active_count': active_count,
        'featured_count': featured_count,
        'public_ready_count': public_ready_count,
    })


@login_required
def host_add_on_service_create(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    host_venues = HostVenue.objects.filter(host_profile=host_profile)

    if not host_venues.exists():
        messages.warning(
            request,
            "Please create a venue before adding an add-on service."
        )
        return redirect('hosting_app:host_venue_create')

    if request.method == 'POST':
        form = HostAddOnServiceForm(
            request.POST,
            request.FILES,
            host_profile=host_profile
        )

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

            if add_on_service.venue.host_profile != host_profile:
                return HttpResponseForbidden("You cannot create an add-on service for this venue.")

            add_on_service.save()
            form.save_m2m()

            messages.success(
                request,
                "Your add-on service has been created successfully."
            )

            return redirect(
                'hosting_app:host_add_on_service_detail',
                pk=add_on_service.pk
            )
    else:
        form = HostAddOnServiceForm(host_profile=host_profile)

    return render(request, 'hosting_app/host_add_on_service_form.html', {
        'form': form,
        'host_profile': host_profile,
        'page_title': 'Create Add-on Service',
        'submit_text': 'Create Add-on Service',
        'is_update': False,
        'selected_venue': None,
    })


@login_required
def host_add_on_service_create_for_venue(request, venue_slug):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    venue = get_object_or_404(
        HostVenue,
        slug=venue_slug,
        host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostAddOnServiceForm(
            request.POST,
            request.FILES,
            host_profile=host_profile,
            selected_venue=venue
        )

        if form.is_valid():
            add_on_service = form.save(commit=False)
            add_on_service.venue = venue
            add_on_service.save()
            form.save_m2m()

            messages.success(
                request,
                f"Your add-on service for {venue.venue_name} has been created successfully."
            )

            return redirect(
                'hosting_app:host_add_on_service_detail',
                pk=add_on_service.pk
            )
    else:
        form = HostAddOnServiceForm(
            host_profile=host_profile,
            selected_venue=venue
        )

    return render(request, 'hosting_app/host_add_on_service_form.html', {
        'form': form,
        'host_profile': host_profile,
        'venue': venue,
        'selected_venue': venue,
        'page_title': f'Create Add-on Service for {venue.venue_name}',
        'submit_text': 'Create Add-on Service',
        'is_update': False,
    })


@login_required
def host_add_on_service_detail(request, pk):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    add_on_service = get_object_or_404(
        HostAddOnService.objects.select_related('venue'),
        pk=pk,
        venue__host_profile=host_profile
    )

    return render(request, 'hosting_app/host_add_on_service_detail.html', {
        'host_profile': host_profile,
        'add_on_service': add_on_service,
        'venue': add_on_service.venue,
    })


@login_required
def host_add_on_service_update(request, pk):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    add_on_service = get_object_or_404(
        HostAddOnService.objects.select_related('venue'),
        pk=pk,
        venue__host_profile=host_profile
    )

    if request.method == 'POST':
        form = HostAddOnServiceForm(
            request.POST,
            request.FILES,
            instance=add_on_service,
            host_profile=host_profile
        )

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

            if updated_service.venue.host_profile != host_profile:
                return HttpResponseForbidden("You cannot move this add-on service to another host's venue.")

            updated_service.save()
            form.save_m2m()

            messages.success(
                request,
                "Your add-on service has been updated successfully."
            )

            return redirect(
                'hosting_app:host_add_on_service_detail',
                pk=updated_service.pk
            )
    else:
        form = HostAddOnServiceForm(
            instance=add_on_service,
            host_profile=host_profile
        )

    return render(request, 'hosting_app/host_add_on_service_form.html', {
        'form': form,
        'host_profile': host_profile,
        'add_on_service': add_on_service,
        'venue': add_on_service.venue,
        'selected_venue': add_on_service.venue,
        'page_title': 'Edit Add-on Service',
        'submit_text': 'Save Add-on Service',
        'is_update': True,
    })

@login_required
def host_banking_details(request):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

    banking_details, created = HostBankingDetails.objects.get_or_create(
        host_profile=host_profile,
        defaults={
            'account_holder_name': host_profile.business_name or '',
            'bank_name': '',
            'branch_name': '',
            'account_number': '',
            'iban': '',
            'swift_code': '',
            'bank_country': 'Sri Lanka',
            'bank_address': '',
            'payment_notes': '',
        }
    )

    if request.method == 'POST':
        form = HostBankingDetailsForm(
            request.POST,
            instance=banking_details
        )

        if form.is_valid():
            form.save()
            messages.success(
                request,
                "Your banking details have been updated successfully."
            )
            return redirect('hosting_app:host_banking_details')
    else:
        form = HostBankingDetailsForm(instance=banking_details)

    return render(request, 'hosting_app/host_banking_details.html', {
        'host_profile': host_profile,
        'banking_details': banking_details,
        'form': form,
    })

@login_required
def host_payment_center(request):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

    # Ensure featured fee payable item exists / refresh unpaid item
    update_hosting_partner_payable_items(request.user)

    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='hosting_partner',
        defaults={
            'balance_usd': Decimal('0.00'),
            'is_active': True,
        }
    )

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

    payment_order = {
        'hosting_partner_featured': 1,
        'host_event_booking': 2,
        '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'))

    venues = host_profile.venues.all()

    total_venues = venues.count()
    public_venues_count = venues.filter(is_public=True).count()
    featured_venues_count = venues.filter(is_featured=True).count()

    total_event_packages = 0
    total_meal_plans = 0
    total_add_on_services = 0

    for venue in venues:
        total_event_packages += venue.event_packages.count()
        total_meal_plans += venue.meal_plans.count()
        total_add_on_services += venue.add_on_services.count()

    context = {
        'host_profile': host_profile,
        'wallet': wallet,

        '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,

        'total_venues': total_venues,
        'public_venues_count': public_venues_count,
        'featured_venues_count': featured_venues_count,
        'total_event_packages': total_event_packages,
        'total_meal_plans': total_meal_plans,
        'total_add_on_services': total_add_on_services,
    }

    return render(request, 'hosting_app/host_payment_center.html', context)

@login_required
def host_payment_checkout(request):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='hosting_partner',
        defaults={
            'balance_usd': Decimal('0.00'),
            'is_active': True,
        }
    )

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

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

    payable_items = list(
        UserPayableItem.objects.filter(
            id__in=selected_ids,
            user=request.user,
            profile_type='hosting_partner',
            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('hosting_app:host_payment_center')

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

    context = {
        'host_profile': host_profile,
        'wallet': wallet,
        'payable_items': payable_items,
        'selected_ids': [str(item.id) for item in payable_items],
        'total_amount': total_amount,
    }

    return render(request, 'hosting_app/host_payment_checkout.html', context)

@login_required
def host_payment_checkout_pay(request):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

    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('hosting_app:host_payment_center')

    payable_items = list(
        UserPayableItem.objects.filter(
            id__in=selected_ids,
            user=request.user,
            profile_type='hosting_partner',
            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('hosting_app:host_payment_center')

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

    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='hosting_partner',
        defaults={
            'balance_usd': Decimal('0.00'),
            'is_active': True,
        }
    )

    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).quantize(Decimal('0.01'))
        amount_to_charge = (total_amount - wallet_deduction).quantize(Decimal('0.01'))

    # ---------------------------------------------------------
    # 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('hosting_app:host_payment_center')

            payment_transaction = PaymentTransaction.objects.create(
                user=request.user,
                profile_type='hosting_partner',
                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_hosting_partner_transaction_items_paid(
                payment_transaction=payment_transaction,
                notes=f"Paid using wallet. Transaction #{payment_transaction.id}",
            )

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

                messages.error(
                    request,
                    "Payment could not be fully completed. Please contact support."
                )

                return redirect(
                    'hosting_app:host_payment_failed',
                    transaction_id=payment_transaction.id
                )

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

        request.session.pop('hosting_partner_payment_transaction_id', None)
        request.session.pop('hosting_partner_checkout_item_ids', None)
        request.session.pop('hosting_partner_checkout_total', None)
        request.session.pop('hosting_partner_checkout_profile_type', None)
        request.session.pop('hosting_partner_use_wallet', None)
        request.session.pop('hosting_partner_wallet_deduction', None)

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

        return redirect(
            'hosting_app:host_payment_success',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # Gateway payment
    # ---------------------------------------------------------
    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 select a valid payment method.")
        return redirect('hosting_app:host_payment_center')

    with transaction.atomic():
        payment_transaction = PaymentTransaction.objects.create(
            user=request.user,
            profile_type='hosting_partner',
            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,
            )

    request.session['hosting_partner_payment_transaction_id'] = payment_transaction.id
    request.session['hosting_partner_checkout_item_ids'] = [
        item.id for item in payable_items
    ]
    request.session['hosting_partner_checkout_total'] = str(amount_to_charge)
    request.session['hosting_partner_checkout_profile_type'] = 'hosting_partner'
    request.session['hosting_partner_use_wallet'] = use_wallet
    request.session['hosting_partner_wallet_deduction'] = str(wallet_deduction)

    if payment_method == 'stripe':
        return redirect('hosting_app:start_hosting_partner_stripe_checkout')

    if payment_method == 'paypal':
        return redirect('hosting_app:start_hosting_partner_paypal_checkout')

    messages.error(request, "Please select a valid payment method.")
    return redirect('hosting_app:host_payment_center')

@login_required
def start_hosting_partner_stripe_checkout(request):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

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

    if payment_transaction.gateway_amount_usd <= Decimal('0.00'):
        messages.error(request, "Invalid Stripe payment amount.")
        return redirect('hosting_app:host_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('hosting_app:host_payment_center')

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

    stripe.api_key = settings.STRIPE_SECRET_KEY

    try:
        line_items = []

        # If wallet is partially used, Stripe should charge only the remaining 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'Hosting Partner 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 'Hosting Partner payment item'
                            ),
                        },
                        'unit_amount': stripe_amount_cents,
                    },
                    'quantity': 1,
                })

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

        cancel_url = request.build_absolute_uri(
            reverse(
                'hosting_app:host_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': 'hosting_partner',
                '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('hosting_app:host_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('hosting_app:host_payment_center')

@login_required
def hosting_partner_stripe_payment_success(request, transaction_id):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

    # Prevent duplicate wallet deduction / duplicate item marking.
    if payment_transaction.status == 'paid':
        messages.success(request, "This payment has already been completed.")
        return redirect(
            'hosting_app:host_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(
            'hosting_app:host_payment_failed',
            transaction_id=payment_transaction.id
        )

    if not settings.STRIPE_SECRET_KEY:
        messages.error(request, "Stripe payment is not configured.")
        return redirect(
            'hosting_app:host_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(
            'hosting_app:host_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 2. Verify 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(
            'hosting_app:host_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(
            'hosting_app:host_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 4. Verify Stripe 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(
            'hosting_app:host_payment_failed',
            transaction_id=payment_transaction.id
        )

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

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

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

            # Deduct wallet only for mixed Stripe + wallet payments.
            if wallet_deduction > Decimal('0.00'):
                wallet = WalletAccount.objects.select_for_update().get(
                    user=request.user,
                    profile_type='hosting_partner',
                )

                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(
                        'hosting_app:host_payment_failed',
                        transaction_id=locked_transaction.id
                    )

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

            # Mark selected Hosting Partner payable items as paid.
            mark_result = mark_hosting_partner_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(
                    'hosting_app:host_payment_failed',
                    transaction_id=locked_transaction.id
                )

            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(
            'hosting_app:host_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 6. Clear checkout session data
    # ---------------------------------------------------------
    request.session.pop('hosting_partner_payment_transaction_id', None)
    request.session.pop('hosting_partner_checkout_item_ids', None)
    request.session.pop('hosting_partner_checkout_total', None)
    request.session.pop('hosting_partner_checkout_profile_type', None)
    request.session.pop('hosting_partner_use_wallet', None)
    request.session.pop('hosting_partner_wallet_deduction', None)

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

    return redirect(
        'hosting_app:host_payment_success',
        transaction_id=payment_transaction.id
    )

@login_required
def host_payment_success(request, transaction_id):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

    return render(request, 'hosting_app/host_payment_success.html', {
        'host_profile': host_profile,
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Successful',
    })

@login_required
def host_payment_cancelled(request, transaction_id):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

    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, 'hosting_app/host_payment_cancelled.html', {
        'host_profile': host_profile,
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Cancelled',
    })

@login_required
def host_payment_failed(request, transaction_id):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

    return render(request, 'hosting_app/host_payment_failed.html', {
        'host_profile': host_profile,
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Failed',
    })

#Hosting partner Paypal

@login_required
def start_hosting_partner_paypal_checkout(request):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

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

    if payment_transaction.gateway_amount_usd <= Decimal('0.00'):
        messages.error(request, "Invalid PayPal payment amount.")
        return redirect('hosting_app:host_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('hosting_app:host_payment_center')

    try:
        order_data = create_hosting_partner_paypal_order(
            payment_transaction=payment_transaction,
            request=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('hosting_app:host_payment_center')

def create_hosting_partner_paypal_order(payment_transaction, request):
    """
    Creates a PayPal order for Hosting Partner payable item checkout.
    """

    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(
            'hosting_app:hosting_partner_paypal_payment_success',
            kwargs={'transaction_id': payment_transaction.id}
        )
    )

    cancel_url = request.build_absolute_uri(
        reverse(
            'hosting_app:host_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'Hosting Partner Payment - Transaction #{payment_transaction.id}',
                'custom_id': str(payment_transaction.id),
                'amount': {
                    'currency_code': 'USD',
                    'value': str(amount_value),
                },
            }
        ],
        'application_context': {
            'brand_name': 'Ensolanka Host 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'hosting-partner-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()

@login_required
def hosting_partner_paypal_payment_success(request, transaction_id):
    host_profile = getattr(request.user, 'host_profile', None)

    if not host_profile:
        messages.error(request, "Hosting Partner profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

    if payment_transaction.status == 'paid':
        messages.success(request, "This payment has already been completed.")
        return redirect(
            'hosting_app:host_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(
            'hosting_app:host_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(
            'hosting_app:host_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(
            'hosting_app:host_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(
            'hosting_app:host_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(
                'hosting_app:host_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(
            'hosting_app:host_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='hosting_partner',
            )

            if locked_transaction.status == 'paid':
                messages.success(request, "This payment has already been completed.")
                return redirect(
                    'hosting_app:host_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='hosting_partner',
                )

                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(
                        'hosting_app:host_payment_failed',
                        transaction_id=locked_transaction.id
                    )

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

            mark_result = mark_hosting_partner_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(
                    'hosting_app:host_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(
            'hosting_app:host_payment_failed',
            transaction_id=payment_transaction.id
        )

    request.session.pop('hosting_partner_payment_transaction_id', None)
    request.session.pop('hosting_partner_checkout_item_ids', None)
    request.session.pop('hosting_partner_checkout_total', None)
    request.session.pop('hosting_partner_checkout_profile_type', None)
    request.session.pop('hosting_partner_use_wallet', None)
    request.session.pop('hosting_partner_wallet_deduction', None)

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

    return redirect(
        'hosting_app:host_payment_success',
        transaction_id=payment_transaction.id
    )



#==============================================================

@login_required
def host_booking_list(request):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

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

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

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

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

    total_bookings = bookings.count()

    paid_count = bookings.filter(
        payment_status=HostBookingPaymentStatus.PAID
    ).count()

    due_count = bookings.filter(
        payment_status__in=[
            HostBookingPaymentStatus.UNPAID,
            HostBookingPaymentStatus.DUE,
        ]
    ).count()

    completed_count = bookings.filter(
        status=BookingRequestStatus.COMPLETED
    ).count()

    total_paid_value = bookings.filter(
        payment_status=HostBookingPaymentStatus.PAID
    ).aggregate(
        total=Sum('total_amount_usd')
    )['total'] or 0

    total_host_net = bookings.filter(
        payment_status=HostBookingPaymentStatus.PAID
    ).aggregate(
        total=Sum('host_net_amount_usd')
    )['total'] or 0

    return render(request, 'hosting_app/host_booking_list.html', {
        'host_profile': host_profile,
        'bookings': bookings,
        'status': status,
        'payment_status': payment_status,
        'total_bookings': total_bookings,
        'paid_count': paid_count,
        'due_count': due_count,
        'completed_count': completed_count,
        'total_paid_value': total_paid_value,
        'total_host_net': total_host_net,
        'booking_status_choices': BookingRequestStatus.choices,
        'payment_status_choices': HostBookingPaymentStatus.choices,
    })

@login_required
def host_booking_detail(request, pk):
    host_profile = get_logged_in_host_profile(request)

    if host_profile is None:
        return HttpResponseForbidden("You do not have a Hosting Partner profile.")

    booking = get_object_or_404(
        HostBookingRequest.objects.select_related(
            'venue',
            'host_profile',
            'guest_profile',
            'hosting_client_profile',
            'booked_by_user',
            'selected_package',
            'selected_meal_plan',
            'payable_item',
        ).prefetch_related(
            'selected_add_ons'
        ),
        pk=pk,
        host_profile=host_profile
    )

    return render(request, 'hosting_app/host_booking_detail.html', {
        'host_profile': host_profile,
        'booking': booking,
        'selected_add_ons': booking.selected_add_ons.all(),
    })

#=========================================================
# Local Client
#=========================================================

class HostingClientLoginView(LoginView):
    template_name = 'registration/hosting_client_login.html'

    def get_form(self, form_class=None):
        form = super().get_form(form_class)

        form.fields['username'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Enter your username'
        })

        form.fields['password'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Enter your password'
        })

        return form

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

        hosting_client = getattr(user, 'hosting_client_profile', None)

        if hosting_client:
            self.request.session['active_hosting_portal'] = 'client'
            return response

        messages.error(
            self.request,
            "This login is only for Hosting Clients. Please use the correct login page."
        )

        logout(self.request)

        return redirect('hosting_app:hosting_client_login')

    def get_success_url(self):
        return self.get_redirect_url() or reverse_lazy(
            'hosting_app:hosting_client_dashboard'
        )


def local_client_booking_entry(request, venue_slug):
    """
    Entry point for public/local client booking.

    - If Foreigner/Guest: redirect to expat_life booking flow.
    - If logged-in non-guest: create HostingClientProfile if missing and continue.
    - If not logged in: send to local client signup.
    """

    venue = get_object_or_404(
        HostVenue,
        slug=venue_slug,
        is_public=True,
        listing_status=PublicListingStatus.APPROVED
    )

    request.session['local_host_booking_venue_slug'] = venue.slug

    if request.user.is_authenticated:
        if hasattr(request.user, 'foreigner_profile'):
            return redirect(
                'expat_life:guest_host_booking_start',
                slug=venue.slug
            )

        get_or_create_hosting_client_profile_for_user(request.user)

        request.session['active_hosting_portal'] = 'client'

        return redirect(
            'hosting_app:local_client_booking_start',
            venue_slug=venue.slug
        )

    return redirect(
        'hosting_app:local_client_signup',
        venue_slug=venue.slug
    )

@transaction.atomic
def local_client_signup(request, venue_slug):
    """
    Signup minimum local client account and redirect to selected venue booking page.
    """

    venue = get_object_or_404(
        HostVenue,
        slug=venue_slug,
        is_public=True,
        listing_status=PublicListingStatus.APPROVED
    )

    if request.user.is_authenticated:
        return redirect(
            'hosting_app:local_client_booking_entry',
            venue_slug=venue.slug
        )

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

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

            existing_user = User.objects.filter(email__iexact=email).first()

            if existing_user:
                messages.error(
                    request,
                    "An account already exists with this email. Please login and continue booking."
                )
                return redirect('hosting_app:host_login')

            username = generate_host_username(full_name)
            password = generate_random_password()

            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,
            )

            HostingClientProfile.objects.create(
                user=user,
                client_type=HostingClientType.HOSTING_CLIENT,
                full_name=full_name,
                email=email,
                phone_number=form.cleaned_data['phone_number'],
                whatsapp_number=form.cleaned_data.get('whatsapp_number', ''),
                country=form.cleaned_data.get('country', 'Sri Lanka'),
                city=form.cleaned_data.get('city', ''),
            )

            # Send welcome email only for newly created external client account
            try:
                send_hosting_client_signup_welcome_email(
                    user=user,
                    full_name=full_name,
                    email=email,
                    username=username,
                    temporary_password=password,
                    venue=venue,
                    request=request,
                )
            except Exception as e:
                print(f"Hosting client welcome email failed: {e}")

            request.session['new_account_username'] = username
            request.session['new_account_password'] = password
            request.session['new_account_email'] = email
            request.session['account_role'] = 'Hosting Client'

            login(request, user)
            request.session['active_hosting_portal'] = 'client'

            messages.success(
                request,
                "Your Hosting Client account has been created. Please continue your booking."
            )

            return redirect(
                'hosting_app:local_client_booking_start',
                venue_slug=venue.slug
            )
    else:
        form = HostingClientSignupForm()

    return render(request, 'hosting_app/local_client_signup.html', {
        'form': form,
        'venue': venue,
    })

@login_required
def local_client_booking_start(request, venue_slug):
    """
    Local hosting client booking selection page.
    Creates/updates HostBookingRequest and UserPayableItem with profile_type='hosting_client'.
    """

    if hasattr(request.user, 'foreigner_profile'):
        return redirect(
            'expat_life:guest_host_booking_start',
            slug=venue_slug
        )

    hosting_client_profile = get_or_create_hosting_client_profile_for_user(request.user)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile could not be prepared.")
        return redirect('hosting_app:home_hosting')

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

    # ---------------------------------------------------------
    # Prevent editing/replacing a paid booking for this venue
    # ---------------------------------------------------------
    existing_paid_booking = HostBookingRequest.objects.filter(
        booked_by_user=request.user,
        hosting_client_profile=hosting_client_profile,
        venue=venue,
        payment_status=HostBookingPaymentStatus.PAID,
    ).first()

    if existing_paid_booking:
        messages.warning(
            request,
            "This booking has already been paid. Editing is disabled for confirmed paid bookings."
        )
        return redirect(
            'hosting_app:local_client_booking_review',
            booking_id=existing_paid_booking.id
        )

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

        if form.is_valid():
            booking = create_or_update_local_client_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 it before payment."
            )

            return redirect(
                'hosting_app:local_client_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, 'hosting_app/local_client_booking_start.html', {
        'form': form,
        'venue': venue,
        'hosting_client_profile': hosting_client_profile,
        'event_packages': event_packages,
        'meal_plans': meal_plans,
        'add_on_services': add_on_services,
    })

@login_required
def local_client_booking_review(request, booking_id):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

    return render(request, 'hosting_app/local_client_booking_review.html', {
        'booking': booking,
        'venue': booking.venue,
        'hosting_client_profile': hosting_client_profile,
        'selected_add_ons': booking.selected_add_ons.all(),
    })

@login_required
def hosting_client_dashboard(request):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

    bookings = HostBookingRequest.objects.filter(
        booked_by_user=request.user,
        hosting_client_profile=hosting_client_profile,
    ).select_related(
        'venue',
        'payable_item',
    ).order_by('-submitted_at')[:10]

    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)

    return render(request, 'hosting_app/hosting_client_dashboard.html', {
        'hosting_client_profile': hosting_client_profile,
        'bookings': bookings,
        'username': username,
        'password': password,
        'new_account_email': new_account_email,
        'account_role': account_role,
    })

@login_required
def hosting_client_payment_center(request):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

    payable_items = UserPayableItem.objects.filter(
        user=request.user,
        profile_type='hosting_client',
        is_active=True,
    ).order_by('-created_at')

    due_items = payable_items.filter(payment_status='due')
    paid_items = payable_items.filter(payment_status='paid')

    bookings = HostBookingRequest.objects.filter(
        booked_by_user=request.user,
        hosting_client_profile=hosting_client_profile,
    ).select_related(
        'venue',
        'payable_item',
    ).order_by('-submitted_at')

    due_total = sum(
        (item.amount_usd for item in due_items),
        Decimal('0.00')
    )

    paid_total = sum(
        (item.amount_usd for item in paid_items),
        Decimal('0.00')
    )

    return render(request, 'hosting_app/hosting_client_payment_center.html', {
        'hosting_client_profile': hosting_client_profile,
        'payable_items': payable_items,
        'due_items': due_items,
        'paid_items': paid_items,
        'bookings': bookings,
        'due_total': due_total,
        'paid_total': paid_total,
    })


#Hosting client payments

@login_required
def hosting_client_payment_checkout(request):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

    wallet, created = WalletAccount.objects.get_or_create(
        user=request.user,
        profile_type='hosting_client',
        defaults={
            'balance_usd': Decimal('0.00'),
            'is_active': True,
        }
    )

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

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

    payable_items = list(
        UserPayableItem.objects.filter(
            id__in=selected_ids,
            user=request.user,
            profile_type='hosting_client',
            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('hosting_app:hosting_client_payment_center')

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

    context = {
        'hosting_client_profile': hosting_client_profile,
        'wallet': wallet,
        'payable_items': payable_items,
        'selected_ids': [str(item.id) for item in payable_items],
        'total_amount': total_amount,
    }

    return render(
        request,
        'hosting_app/hosting_client_payment_checkout.html',
        context
    )

@login_required
def hosting_client_payment_checkout_pay(request):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

    if request.method != 'POST':
        messages.error(request, "Invalid payment request.")
        return redirect('hosting_app:hosting_client_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('hosting_app:hosting_client_payment_center')

    payable_items = list(
        UserPayableItem.objects.filter(
            id__in=selected_ids,
            user=request.user,
            profile_type='hosting_client',
            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('hosting_app:hosting_client_payment_center')

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

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

    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).quantize(Decimal('0.01'))
        amount_to_charge = (total_amount - wallet_deduction).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('hosting_app:hosting_client_payment_center')

            payment_transaction = PaymentTransaction.objects.create(
                user=request.user,
                profile_type='hosting_client',
                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_hosting_client_transaction_items_paid(
                payment_transaction=payment_transaction,
                notes=f"Paid using wallet. Transaction #{payment_transaction.id}",
                credit_host_wallet=False,
            )

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

                messages.error(
                    request,
                    "Payment could not be fully completed. Please contact support."
                )

                return redirect(
                    'hosting_app:hosting_client_payment_failed',
                    transaction_id=payment_transaction.id
                )

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

        # Clear session data
        request.session.pop('hosting_client_payment_transaction_id', None)
        request.session.pop('hosting_client_checkout_item_ids', None)
        request.session.pop('hosting_client_checkout_total', None)
        request.session.pop('hosting_client_checkout_profile_type', None)
        request.session.pop('hosting_client_use_wallet', None)
        request.session.pop('hosting_client_wallet_deduction', None)

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

        return redirect(
            'hosting_app:hosting_client_payment_success',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 4. Gateway payment method validation
    # ---------------------------------------------------------
    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 select a valid payment method.")
        return redirect('hosting_app:hosting_client_payment_center')

    # ---------------------------------------------------------
    # 5. Create pending PaymentTransaction
    # ---------------------------------------------------------
    with transaction.atomic():
        payment_transaction = PaymentTransaction.objects.create(
            user=request.user,
            profile_type='hosting_client',
            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
    # ---------------------------------------------------------
    request.session['hosting_client_payment_transaction_id'] = payment_transaction.id
    request.session['hosting_client_checkout_item_ids'] = [
        item.id for item in payable_items
    ]
    request.session['hosting_client_checkout_total'] = str(amount_to_charge)
    request.session['hosting_client_checkout_profile_type'] = 'hosting_client'
    request.session['hosting_client_use_wallet'] = use_wallet
    request.session['hosting_client_wallet_deduction'] = str(wallet_deduction)

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

    if payment_method == 'paypal':
        return redirect('hosting_app:start_hosting_client_paypal_checkout')

    messages.error(request, "Please select a valid payment method.")
    return redirect('hosting_app:hosting_client_payment_center')

@login_required
def start_hosting_client_stripe_checkout(request):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

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

    if payment_transaction.gateway_amount_usd <= Decimal('0.00'):
        messages.error(request, "Invalid Stripe payment amount.")
        return redirect('hosting_app:hosting_client_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('hosting_app:hosting_client_payment_center')

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

    stripe.api_key = settings.STRIPE_SECRET_KEY

    try:
        line_items = []

        # If wallet is partially used, Stripe should charge only the remaining 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'Hosting Client Event 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 'Hosting client event booking payment'
                            ),
                        },
                        'unit_amount': stripe_amount_cents,
                    },
                    'quantity': 1,
                })

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

        cancel_url = request.build_absolute_uri(
            reverse(
                'hosting_app:hosting_client_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': 'hosting_client',
                'payment_purpose': 'payable_items',
                'client_payment_for': 'host_event_booking',
            },
        )

        if not checkout_session.url:
            messages.error(
                request,
                "Stripe checkout session was created, but no checkout URL was returned."
            )
            return redirect('hosting_app:hosting_client_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('hosting_app:hosting_client_payment_center')


@login_required
def hosting_client_stripe_payment_success(request, transaction_id):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

    # Prevent duplicate wallet deduction / duplicate item marking.
    if payment_transaction.status == 'paid':
        messages.success(request, "This payment has already been completed.")
        return redirect(
            'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_payment_failed',
            transaction_id=payment_transaction.id
        )

    if not settings.STRIPE_SECRET_KEY:
        messages.error(request, "Stripe payment is not configured.")
        return redirect(
            'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 2. Verify 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(
            'hosting_app:hosting_client_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 3. Verify 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(
            'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_payment_failed',
            transaction_id=payment_transaction.id
        )

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

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

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

            # Deduct wallet only for mixed Stripe + wallet payments.
            if wallet_deduction > Decimal('0.00'):
                wallet = WalletAccount.objects.select_for_update().get(
                    user=request.user,
                    profile_type='hosting_client',
                )

                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(
                        'hosting_app:hosting_client_payment_failed',
                        transaction_id=locked_transaction.id
                    )

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

            # Mark selected Hosting Client payable items as paid.
            # credit_host_wallet=False means host wallet is NOT credited immediately.
            mark_result = mark_hosting_client_transaction_items_paid(
                payment_transaction=locked_transaction,
                notes=f"Paid by Stripe. Transaction #{locked_transaction.id}",
                credit_host_wallet=False,
            )

            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(
                    'hosting_app:hosting_client_payment_failed',
                    transaction_id=locked_transaction.id
                )

            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(
            'hosting_app:hosting_client_payment_failed',
            transaction_id=payment_transaction.id
        )

    # ---------------------------------------------------------
    # 6. Clear checkout session data
    # ---------------------------------------------------------
    request.session.pop('hosting_client_payment_transaction_id', None)
    request.session.pop('hosting_client_checkout_item_ids', None)
    request.session.pop('hosting_client_checkout_total', None)
    request.session.pop('hosting_client_checkout_profile_type', None)
    request.session.pop('hosting_client_use_wallet', None)
    request.session.pop('hosting_client_wallet_deduction', None)

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

    return redirect(
        'hosting_app:hosting_client_payment_success',
        transaction_id=payment_transaction.id
    )

#==========================================================

@login_required
def hosting_client_payment_success(request, transaction_id):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

    return render(request, 'hosting_app/hosting_client_payment_success.html', {
        'hosting_client_profile': hosting_client_profile,
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Successful',
    })

@login_required
def hosting_client_payment_cancelled(request, transaction_id):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

    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, 'hosting_app/hosting_client_payment_cancelled.html', {
        'hosting_client_profile': hosting_client_profile,
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Cancelled',
    })

@login_required
def hosting_client_payment_failed(request, transaction_id):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

    return render(request, 'hosting_app/hosting_client_payment_failed.html', {
        'hosting_client_profile': hosting_client_profile,
        'payment_transaction': payment_transaction,
        'page_title': 'Payment Failed',
    })




#=====================================================================
@login_required
def start_hosting_client_paypal_checkout(request):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

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

    if payment_transaction.gateway_amount_usd <= Decimal('0.00'):
        messages.error(request, "Invalid PayPal payment amount.")
        return redirect('hosting_app:hosting_client_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('hosting_app:hosting_client_payment_center')

    try:
        order_data = create_hosting_client_paypal_order(
            payment_transaction=payment_transaction,
            request=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('hosting_app:hosting_client_payment_center')


def create_hosting_client_paypal_order(payment_transaction, request):
    """
    Creates a PayPal order for Hosting Client event booking payments.
    """

    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(
            'hosting_app:hosting_client_paypal_payment_success',
            kwargs={'transaction_id': payment_transaction.id}
        )
    )

    cancel_url = request.build_absolute_uri(
        reverse(
            'hosting_app:hosting_client_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'Hosting Client Event Payment - Transaction #{payment_transaction.id}',
                'custom_id': str(payment_transaction.id),
                'amount': {
                    'currency_code': 'USD',
                    'value': str(amount_value),
                },
            }
        ],
        'application_context': {
            'brand_name': 'Ensolanka Host 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'hosting-client-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()

@login_required
def hosting_client_paypal_payment_success(request, transaction_id):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

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

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

    if payment_transaction.status == 'paid':
        messages.success(request, "This payment has already been completed.")
        return redirect(
            'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_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(
                'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_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='hosting_client',
            )

            if locked_transaction.status == 'paid':
                messages.success(request, "This payment has already been completed.")
                return redirect(
                    'hosting_app:hosting_client_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='hosting_client',
                )

                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(
                        'hosting_app:hosting_client_payment_failed',
                        transaction_id=locked_transaction.id
                    )

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

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

            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(
                    'hosting_app:hosting_client_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(
            'hosting_app:hosting_client_payment_failed',
            transaction_id=payment_transaction.id
        )

    request.session.pop('hosting_client_payment_transaction_id', None)
    request.session.pop('hosting_client_checkout_item_ids', None)
    request.session.pop('hosting_client_checkout_total', None)
    request.session.pop('hosting_client_checkout_profile_type', None)
    request.session.pop('hosting_client_use_wallet', None)
    request.session.pop('hosting_client_wallet_deduction', None)

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

    return redirect(
        'hosting_app:hosting_client_payment_success',
        transaction_id=payment_transaction.id
    )

# ============================================================
# Hosting Client Profile Page
# ============================================================

@login_required
def hosting_client_profile_page(request):
    client = getattr(request.user, 'hosting_client_profile', None)

    if client is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Client profile."
        )

    return render(
        request,
        'hosting_app/hosting_client_profile_page.html',
        {
            'client': client,
            'default_profile_image': 'expat_life/images/default-profile-neutral.png',
        }
    )

@login_required
def hosting_client_booking_list(request):
    hosting_client_profile = getattr(request.user, 'hosting_client_profile', None)

    if not hosting_client_profile:
        messages.error(request, "Hosting client profile not found.")
        return redirect('hosting_app:home_hosting')

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

    bookings = (
        HostBookingRequest.objects
        .filter(
            hosting_client_profile=hosting_client_profile,
            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, 'hosting_app/hosting_client_booking_list.html', {
        'hosting_client_profile': hosting_client_profile,
        'bookings': bookings,
        'status_filter': status_filter,
        'payment_status_filter': payment_status_filter,
        'booking_status_choices': BookingRequestStatus.choices,
        'payment_status_choices': HostBookingPaymentStatus.choices,
        'page_title': 'My Hosting Bookings',
    })
# ============================================================
# Edit Hosting Client Profile
# ============================================================

@login_required
def edit_hosting_client_profile(request):
    client = getattr(request.user, 'hosting_client_profile', None)

    if client is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Client profile."
        )

    if request.method == 'POST':
        form = HostingClientProfileForm(request.POST, instance=client)

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

            # Sync full name to linked Django User
            full_name = form.cleaned_data.get('full_name', '').strip()
            name_parts = full_name.split()

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

            # Keep auth user email aligned with HostingClientProfile email
            email = form.cleaned_data.get('email', '').strip().lower()
            request.user.email = email
            request.user.save()

            client_profile.email = email
            client_profile.save()

            messages.success(
                request,
                "Your Hosting Client profile has been updated successfully."
            )

            return redirect('hosting_app:hosting_client_profile_page')

    else:
        form = HostingClientProfileForm(instance=client)

    return render(
        request,
        'hosting_app/edit_hosting_client_profile.html',
        {
            'form': form,
            'client': client,
        }
    )


# ============================================================
# Upload Hosting Client Profile Image
# ============================================================

@login_required
@require_POST
def upload_hosting_client_profile_image(request):
    client = getattr(request.user, 'hosting_client_profile', None)

    if client is None:
        return JsonResponse(
            {
                'success': False,
                'error': 'You do not have a Hosting Client profile.'
            },
            status=403
        )

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

    form = HostingClientProfileImageForm(
        request.POST,
        request.FILES,
        instance=client
    )

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

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

    error_list = []

    for field_errors in form.errors.values():
        error_list.extend(field_errors)

    return JsonResponse(
        {
            'success': False,
            'error': (
                ' '.join(error_list)
                if error_list
                else 'Image upload failed.'
            ),
        },
        status=400
    )


# ============================================================
# Change Hosting Client Username
# ============================================================

@login_required
def change_hosting_client_username(request):
    client = getattr(request.user, 'hosting_client_profile', None)

    if client is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Client profile."
        )

    if request.method == 'POST':
        form = HostingClientUsernameChangeForm(
            request.user,
            request.POST
        )

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

            messages.success(
                request,
                "Your username has been updated successfully."
            )

            return redirect('hosting_app:hosting_client_profile_page')

    else:
        form = HostingClientUsernameChangeForm(request.user)

    return render(
        request,
        'hosting_app/change_hosting_client_username.html',
        {
            'form': form,
            'client': client,
        }
    )


# ============================================================
# Change Hosting Client Password
# ============================================================

@login_required
def change_hosting_client_password(request):
    client = getattr(request.user, 'hosting_client_profile', None)

    if client is None:
        return HttpResponseForbidden(
            "You do not have a Hosting Client profile."
        )

    if request.method == 'POST':
        form = StyledHostingClientPasswordChangeForm(
            request.user,
            request.POST
        )

        if form.is_valid():
            user = form.save()

            update_session_auth_hash(request, user)

            messages.success(
                request,
                "Your password has been updated successfully."
            )

            return redirect('hosting_app:hosting_client_profile_page')

    else:
        form = StyledHostingClientPasswordChangeForm(request.user)

    return render(
        request,
        'hosting_app/change_hosting_client_password.html',
        {
            'form': form,
            'client': client,
        }
    )

def hosting_partner_information_center(request):
    selected_language = request.GET.get('lang', 'en')

    allowed_languages = ['en', 'si', 'ta']

    if selected_language not in allowed_languages:
        selected_language = 'en'

    guidance_resources = HostingPartnerGuidanceResource.objects.filter(
        is_active=True
    ).order_by('language')

    available_languages = list(
        guidance_resources.values_list('language', flat=True)
    )

    # If requested language is not available, fallback safely.
    if selected_language not in available_languages and available_languages:
        if 'en' in available_languages:
            selected_language = 'en'
        else:
            selected_language = available_languages[0]

    selected_resource = guidance_resources.filter(
        language=selected_language
    ).first()

    context = {
        'guidance_resources': guidance_resources,
        'selected_resource': selected_resource,
        'selected_language': selected_language,
    }

    return render(
        request,
        'hosting_app/hosting_partner_information_center.html',
        context
    )