from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import logout, authenticate, login, update_session_auth_hash
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
import json
from django.urls import reverse
from django.contrib.auth import get_user_model
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import *
from .models import *
from django.views.decorators.http import require_POST
from django.utils import timezone
from django.db import transaction
from django.db.models import Exists, OuterRef, Sum
from django.utils.dateparse import parse_date
from datetime import date, timedelta
from django.core.mail import send_mail
# Create your views here.
def home(request):
    # Get the 3 most recently created room types that have at least one room
    room_types = RoomType.objects.filter(total_rooms__gt=0).order_by('-created_at')[:3]
    recent_reviews = Review.objects.select_related('user', 'hotel').order_by('-created_at')[:6]
    context = {
        'room_types': room_types,
        'recent_reviews': recent_reviews
    }
    return render(request, 'janka_web_app/home.html', context)

def rooms(request):
    hotels = Hotel.objects.select_related('dzongkhag', 'gewog', 'village').all()
    dzongkhags = Dzongkhag.objects.all()
    room_choices = Hotel.room_choices

    # Apply Filters
    dzongkhag_id = request.GET.get('dzongkhag')
    gewog_id = request.GET.get('gewog')
    village_id = request.GET.get('village')
    room_type = request.GET.get('room_type')
    # 🔥 NEW: Filter by total_rooms
    min_rooms = request.GET.get('min_rooms')
    max_rooms = request.GET.get('max_rooms')
    if min_rooms:
        try:
            hotels = hotels.filter(total_rooms__gte=int(min_rooms))
        except ValueError:
            pass  # Invalid number, ignore
    if max_rooms:
        try:
            hotels = hotels.filter(total_rooms__lte=int(max_rooms))
        except ValueError:
            pass  # Invalid number, ignore

    if dzongkhag_id:
        hotels = hotels.filter(dzongkhag__dzo_id=dzongkhag_id)
    if gewog_id:
        hotels = hotels.filter(gewog__gewog_id=gewog_id)
    if village_id:
        hotels = hotels.filter(village__village_id=village_id)
    if room_type:
        hotels = hotels.filter(room_types=room_type)

    context = {
        'hotels': hotels,
        'dzongkhags': dzongkhags,
        'room_choices': room_choices,
    }
    return render(request, 'janka_web_app/rooms.html', context)

def room_details(request):
    context = {}
    return render(request, 'janka_web_app/room-detail.html')

def dining(request):
    context = {}
    return render(request, 'janka_web_app/dining.html')

def activities(request):
    context = {}
    return render(request, 'janka_web_app/activities.html')
def spa(request):
    return render(request, 'janka_web_app/spa.html')

def about_us(request):
    return render(request, 'janka_web_app/about-us.html')

def sign_in(request):
    if request.user.is_authenticated:
        return redirect('/dashboard')
    alert = None  # default no alert

    if request.method == "POST":
        username = request.POST.get('username')
        password = request.POST.get('password')

        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)
            alert = {'status': 'success', 'message': 'Login successful! Redirecting...'}
        else:
            alert = {'status': 'error', 'message': 'Invalid email or password!'}

    return render(request, 'janka_web_app/signin.html', {'alert': alert})

def sign_out(request):
    logout(request)
    return redirect('/')

@login_required
def notification_redirect(request, notif_id):
    """
    Mark notification as read and redirect to its action_url
    """
    notif = get_object_or_404(
        Notification, 
        id=notif_id, 
        recipient_user=request.user  # Only owner/admin can access
    )
    
    # ✅ Mark as viewed
    if not notif.is_viewed:
        notif.is_viewed = True
        notif.save(update_fields=['is_viewed'])  # Only save this field

    # ✅ Redirect to the target page
    return redirect(notif.action_url or 'home')  # Fallback to 'home' if no URL

@login_required(login_url='/sign_in/')
def dashboard(request):
    now = timezone.now()
    last_24 = now - timedelta(hours=24)

    context = {
        'user': request.user,
    }

    if request.user.user_role == 'admin':
        # Admin sees global stats
        total_bookings = Booking.objects.count()
        confirmed_bookings = Booking.objects.filter(status='confirmed').count()
        pending_bookings = Booking.objects.filter(status='pending').count()
        cancelled_bookings = Booking.objects.filter(status='cancelled').count()

        recent_24h_bookings = Booking.objects.filter(created_at__gte=last_24).select_related('user', 'hotel').order_by('-created_at')[:10]
        recent_bookings = Booking.objects.select_related('user', 'hotel').order_by('-created_at')[:5]
        recent_reviews = Review.objects.select_related('user', 'hotel').order_by('-created_at')[:5]

        context.update({
            'total_users': User.objects.count(),
            'total_hotels': Hotel.objects.count(),
            'total_bookings': total_bookings,
            'total_reviews': Review.objects.count(),
            'confirmed_bookings': confirmed_bookings,
            'pending_bookings': pending_bookings,
            'cancelled_bookings': cancelled_bookings,
            'recent_24h_bookings': recent_24h_bookings,
            'recent_bookings': recent_bookings,
            'recent_reviews': recent_reviews,
        })

    elif request.user.user_role == 'owner':
        owner_hotels = Hotel.objects.filter(user=request.user)
        owner_hotel_ids = owner_hotels.values_list('id', flat=True)
        
        owner_bookings = Booking.objects.filter(hotel__in=owner_hotel_ids)
        total_owner_bookings = owner_bookings.count()
        confirmed_owner_bookings = owner_bookings.filter(status='confirmed').count()
        pending_owner_bookings = owner_bookings.filter(status='pending').count()
        cancelled_owner_bookings = owner_bookings.filter(status='cancelled').count()

        recent_24h_owner_bookings = owner_bookings.filter(created_at__gte=last_24).select_related('user', 'hotel').order_by('-created_at')[:10]
        recent_owner_bookings = owner_bookings.select_related('user', 'hotel').order_by('-created_at')[:5]

        context.update({
            'total_hotels': owner_hotels.count(),
            'total_bookings': total_owner_bookings,
            'confirmed_bookings': confirmed_owner_bookings,
            'pending_bookings': pending_owner_bookings,
            'cancelled_bookings': cancelled_owner_bookings,
            'recent_24h_bookings': recent_24h_owner_bookings,
            'recent_bookings': recent_owner_bookings,
            'owner_hotels': owner_hotels,
        })

    elif request.user.user_role == 'user':
        # ✅ USER-SPECIFIC DATA
        user_bookings = Booking.objects.filter(user=request.user).select_related('hotel', 'room_selected').order_by('-created_at')
        user_reviews = Review.objects.filter(user=request.user).select_related('hotel').order_by('-created_at')
        recent_messages = Message.objects.filter(receiver=request.user).select_related('sender').order_by('-created_at')[:5]

        confirmed_bookings = user_bookings.filter(status='confirmed').count()
        pending_bookings = user_bookings.filter(status='pending').count()
        cancelled_bookings = user_bookings.filter(status='cancelled').count()

        # Unread messages count (for badge & stats)
        unread_messages_count = Message.objects.filter(receiver=request.user, read=False).count()

        context.update({
            'user_bookings': user_bookings,
            'user_reviews': user_reviews,
            'recent_messages': recent_messages,
            'unread_messages_count': unread_messages_count,
            'confirmed_bookings': confirmed_bookings,
            'pending_bookings': pending_bookings,
            'cancelled_bookings': cancelled_bookings,
        })

    return render(request, 'janka_web_app/dashboard/home.html', context)

@login_required(login_url='/sign_in/')
@csrf_exempt
def add_new_user(request):
    if request.method == "POST":
        try:
            creator = request.user
            # Get form data
            full_name = request.POST.get("full_name")
            username = request.POST.get("username")
            email = request.POST.get("email")
            password = request.POST.get("password")
            phone = request.POST.get("phone", "")
            address = request.POST.get("address", "")
            user_role = request.POST.get("user_role", "user")
            profile_picture = request.FILES.get("profile_picture")

            # Validation
            if User.objects.filter(username=username).exists():
                return JsonResponse({"success": False, "message": "Username already exists."}, status=400)

            if User.objects.filter(email=email).exists():
                return JsonResponse({"success": False, "message": "Email already exists."}, status=400)

            try:
                validate_password(password)
            except ValidationError as e:
                return JsonResponse({"success": False, "message": "Password: " + ", ".join(e.messages)}, status=400)

            # Create the user
            user = User.objects.create_user(
                username=username,
                email=email,
                password=password,
                full_name=full_name,
                phone=phone,
                address=address,
                user_role=user_role
            )

            # Save profile picture if provided
            if profile_picture:
                user.profile_picture = profile_picture
                user.save()
            else:
                user.save()

            # Send welcome email
            try:
                subject = "Welcome to Janka Resort Dashboard!"
                message = f"""
                    Hello {full_name},

                    Welcome! Your account has been successfully created on the Janka Resort Dashboard.

                    Here are your login details:
                    Username: {username}
                    Email: {email}
                    Password: {password}

                    You can now log in and start using your account.

                    Best regards,
                    Janka Resort Team
                                    """.strip()

                send_mail(
                    subject=subject,
                    message=message,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[email],
                    fail_silently=True  # Don't break if email fails
                )
            except:
                pass  # Ignore email errors
            # Create notification
            try:
                Notification.objects.create(
                    title="New User Created",
                    message=f"User '{user.username}' has been added by {creator.username}.",
                    category="user_event",
                    role_visibility="admin",
                    created_by=creator.username
                )
                print("✅ Notification created successfully!")  # Debug log
            except Exception as e:
                print(f"❌ Notification creation failed: {type(e).__name__}: {e}")
                return JsonResponse({
                    "success": False,
                    "message": f"DB Error: {type(e).__name__} - {str(e)[:100]}"
                }, status=500)
            # Return success response
            return JsonResponse({
                "success": True,
                "message": f"User '{user.username}' created successfully!",
                "redirect_url": reverse("registered_users")
            })

        except Exception as e:
            return JsonResponse({
                "success": False,
                "message": "An error occurred: " + str(e)
            }, status=500)

    return render(request, "janka_web_app/dashboard/user_management/add_new_user.html")

def registered_users(request):
    users = User.objects.all().order_by('-created_at')
    return render(request, 'janka_web_app/dashboard/user_management/registered_users.html', {
        'users': users
    })

@csrf_exempt
def delete_user(request, user_id):
    if request.method == "POST":
        user = get_object_or_404(User, id=user_id)
        user.delete()
        return JsonResponse({"success": True})
    return JsonResponse({"success": False, "error": "Invalid request"})

def update_user(request):
    if request.method == "POST":
        user_id = request.POST.get("user_id")
        user = get_object_or_404(User, id=user_id)

        user.full_name = request.POST.get("full_name")
        user.username = request.POST.get("username")
        user.email = request.POST.get("email")
        user.phone = request.POST.get("phone")
        user.address = request.POST.get("address")
        user.user_role = request.POST.get("user_role")

        if "profile_picture" in request.FILES:
            user.profile_picture = request.FILES["profile_picture"]

        user.save()
        messages.success(request, "User updated successfully!")
        return redirect("registered_users")
    
@login_required(login_url='/sign_in/')
def user_settings(request):
    user = request.user

    if request.method == 'POST':
        form = UserProfileForm(request.POST, request.FILES, instance=user)
        if form.is_valid():
            form.save()
            # Redirect with success flag in URL
            return redirect('/user-settings/?updated=true')
            # Or use: return redirect(reverse('user_settings') + '?updated=true')
    else:
        form = UserProfileForm(instance=user)

    context = {
        'form': form,
        'user': user
    }
    return render(request, 'janka_web_app/dashboard/user_management/user_settings.html', context)

@csrf_exempt
def change_password(request):
    if request.method == "POST":
        try:
            # Parse JSON body
            data = json.loads(request.body)
            old_password = data.get('old_password')
            new_password = data.get('new_password')
            confirm_new_password = data.get('confirm_new_password')

            user = request.user

            # 1. Check if old password is correct
            if not user.check_password(old_password):
                return JsonResponse({
                    'success': False,
                    'message': 'Old password is incorrect.'
                }, status=400)

            # 2. Check if new passwords match
            if new_password != confirm_new_password:
                return JsonResponse({
                    'success': False,
                    'message': 'New passwords do not match.'
                }, status=400)

            # 3. Validate new password (using Django's built-in validators)
            try:
                validate_password(new_password, user)
            except ValidationError as e:
                return JsonResponse({
                    'success': False,
                    'message': 'Password: ' + ', '.join(e.messages)
                }, status=400)

            # 4. Set new password
            user.set_password(new_password)
            user.save()

            # 5. Keep user logged in after password change
            update_session_auth_hash(request, user)

            return JsonResponse({
                'success': True,
                'message': 'Password changed successfully!',
                'redirect_url': reverse('user_settings') + '?updated=true'
            })

        except Exception as e:
            return JsonResponse({
                'success': False,
                'message': 'An error occurred: ' + str(e)
            }, status=500)

    return JsonResponse({'success': False, 'message': 'Invalid request method'}, status=405)

# views.py

@login_required(login_url='/sign_in/')
def add_edit_hotel(request):
    dzongkhags = Dzongkhag.objects.all()
    gewogs = Gewog.objects.select_related('dzongkhag').all()
    villages = Village.objects.select_related('gewog', 'dzongkhag').all()

    # 🔥 Check if the user is admin
    if request.user.user_role == 'admin':
        # Admin sees ALL hotels
        hotels = Hotel.objects.all().order_by('-created_at')
    else:
        # Regular users and owners see only their own hotels
        hotels = Hotel.objects.filter(user=request.user).order_by('-created_at')

    context = {
        'hotels': hotels,
        'dzongkhags': dzongkhags,
        'gewogs': gewogs,
        'villages': villages
    }
    return render(request, 'janka_web_app/dashboard/hotels/add_edit_hotel.html', context)

def create_hotel(request):
    if request.method == 'POST':
        try:
            # Get all form fields
            name = request.POST.get('name')
            location = request.POST.get('location')  # detailed physical location
            description = request.POST.get('description', '')
            contact_number = request.POST.get('contact_number')
            email = request.POST.get('email', '')
            total_rooms = request.POST.get('total_rooms', 0)
            available_rooms = request.POST.get('available_rooms', 0)
            hotel_owner = request.POST.get('hotel_owner', '')

            # Get hierarchy IDs
            dzongkhag_id = request.POST.get('dzongkhag_id')
            gewog_id = request.POST.get('gewog_id')
            village_id = request.POST.get('village_id')

            # Validate required fields
            if not all([name, location, contact_number, dzongkhag_id, gewog_id, village_id]):
                return JsonResponse({
                    'success': False,
                    'message': 'Please fill all required fields including Dzongkhag, Gewog, and Village.'
                })

            # Get related objects
            dzongkhag = get_object_or_404(Dzongkhag, dzo_id=dzongkhag_id)
            gewog = get_object_or_404(Gewog, gewog_id=gewog_id, dzongkhag=dzongkhag)
            village = get_object_or_404(Village, village_id=village_id, gewog=gewog, dzongkhag=dzongkhag)

            # Create hotel
            hotel = Hotel.objects.create(
                name=name,
                location=location,
                description=description,
                dzongkhag=dzongkhag,
                gewog=gewog,
                village=village,
                contact_number=contact_number,
                email=email,
                total_rooms=int(total_rooms),
                available_rooms=int(available_rooms),
                hotel_owner=hotel_owner,
                user=request.user,
            )

            # Handle optional image uploads
            if 'home_image' in request.FILES:
                hotel.home_image = request.FILES['home_image']
            if 'hotel_image1' in request.FILES:
                hotel.hotel_image1 = request.FILES['hotel_image1']
            if 'hotel_image2' in request.FILES:
                hotel.hotel_image2 = request.FILES['hotel_image2']
            if 'hotel_image3' in request.FILES:
                hotel.hotel_image3 = request.FILES['hotel_image3']

            hotel.save()

            return JsonResponse({
                'success': True,
                'message': f'Hotel "{hotel.name}" created successfully!',
                'hotel': {
                    'id': hotel.id,
                    'name': hotel.name,
                    'location': hotel.location,
                    'dzongkhag': hotel.dzongkhag.name,
                    'gewog': hotel.gewog.name,
                    'village': hotel.village.name,
                    'contact_number': hotel.contact_number,
                    'total_rooms': hotel.total_rooms,
                    'available_rooms': hotel.available_rooms,
                }
            })

        except Exception as e:
            return JsonResponse({
                'success': False,
                'message': f'Error creating hotel: {str(e)}'
            })

    return JsonResponse({'success': False, 'message': 'Invalid request method.'})

def update_hotel(request):
    if request.method == 'POST':
        try:
            hotel_id = request.POST.get('hotel_id')
            hotel = get_object_or_404(Hotel, id=hotel_id)

            # Get updated fields
            hotel.name = request.POST.get('name')
            hotel.location = request.POST.get('location')
            hotel.description = request.POST.get('description', '')
            hotel.contact_number = request.POST.get('contact_number')
            hotel.email = request.POST.get('email', '')
            hotel.total_rooms = int(request.POST.get('total_rooms', 0))
            hotel.available_rooms = int(request.POST.get('available_rooms', 0))
            hotel.hotel_owner = request.POST.get('hotel_owner', '')

            # Get hierarchy IDs
            dzongkhag_id = request.POST.get('dzongkhag_id')
            gewog_id = request.POST.get('gewog_id')
            village_id = request.POST.get('village_id')

            if not all([dzongkhag_id, gewog_id, village_id]):
                return JsonResponse({
                    'success': False,
                    'message': 'Dzongkhag, Gewog, and Village are required.'
                })

            # Validate and assign related objects
            dzongkhag = get_object_or_404(Dzongkhag, dzo_id=dzongkhag_id)
            gewog = get_object_or_404(Gewog, gewog_id=gewog_id, dzongkhag=dzongkhag)
            village = get_object_or_404(Village, village_id=village_id, gewog=gewog, dzongkhag=dzongkhag)

            hotel.dzongkhag = dzongkhag
            hotel.gewog = gewog
            hotel.village = village

            # Handle optional image uploads (only if new files are provided)
            if 'home_image' in request.FILES:
                hotel.home_image = request.FILES['home_image']
            if 'hotel_image1' in request.FILES:
                hotel.hotel_image1 = request.FILES['hotel_image1']
            if 'hotel_image2' in request.FILES:
                hotel.hotel_image2 = request.FILES['hotel_image2']
            if 'hotel_image3' in request.FILES:
                hotel.hotel_image3 = request.FILES['hotel_image3']

            hotel.save()

            return JsonResponse({
                'success': True,
                'message': f'Hotel "{hotel.name}" updated successfully!',
                'hotel': {
                    'id': hotel.id,
                    'name': hotel.name,
                    'location': hotel.location,
                    'dzongkhag': hotel.dzongkhag.name,
                    'gewog': hotel.gewog.name,
                    'village': hotel.village.name,
                    'contact_number': hotel.contact_number,
                    'total_rooms': hotel.total_rooms,
                    'available_rooms': hotel.available_rooms,
                }
            })

        except Exception as e:
            return JsonResponse({
                'success': False,
                'message': f'Error updating hotel: {str(e)}'
            })

    return JsonResponse({'success': False, 'message': 'Invalid request method.'})

@csrf_exempt
def delete_hotel(request, hotel_id):
    if request.method == "POST":
        try:
            hotel = Hotel.objects.get(id=hotel_id)
            hotel.delete()
            return JsonResponse({"success": True, "message": "Hotel deleted successfully!"})
        except Hotel.DoesNotExist:
            return JsonResponse({"success": False, "message": "Hotel not found."})
    return JsonResponse({"success": False, "message": "Invalid request."})

@login_required(login_url='/sign_in/')
def master_table(request):
    dzongkhags = Dzongkhag.objects.all().order_by('name')
    gewogs = Gewog.objects.all().order_by('name')
    villages = Village.objects.all().order_by('name')
    gallery_categories = GalleryCategory.objects.all().order_by('name')
    context = {'dzongkhags': dzongkhags, 'gewogs': gewogs, 'villages': villages, 'gallery_categories':gallery_categories}
    return render(request, 'janka_web_app/dashboard/master_table.html', context)

@require_POST
def save_dzongkhag(request):
    """
    Handles both Create and Edit Dzongkhag in one function
    """
    dzo_id = request.POST.get("dzo_id")  # If present => Edit
    name = request.POST.get("name")

    if dzo_id:  
        dzongkhag = get_object_or_404(Dzongkhag, pk=dzo_id)
        dzongkhag.name = name
        dzongkhag.save()
        status = "updated"
    else:  
        dzongkhag = Dzongkhag.objects.create(
            name=name,
            created_at=timezone.now()
        )
        status = "created"

    return JsonResponse({
        "success": True,
        "status": status,
        "dzongkhag": {
            "id": dzongkhag.dzo_id,
            "name": dzongkhag.name,
            "created_at": dzongkhag.created_at.strftime("%Y-%m-%d %H:%M")
        }
    })

@require_POST
def delete_dzongkhag(request):
    dzo_id = request.POST.get("dzo_id")
    dzongkhag = get_object_or_404(Dzongkhag, pk=dzo_id)
    print("Reaching here inside the dzonkhag!")
    dzongkhag.delete()

    return JsonResponse({
        "success": True,
        "status": "deleted",
        "dzo_id": dzo_id
    })

@csrf_exempt
def save_gewog(request):
    if request.method == "POST":
        gewog_id = request.POST.get("gewog_id")
        name = request.POST.get("name")
        dzongkhag_id = request.POST.get("dzongkhag_id")

        if not name or not dzongkhag_id:
            return JsonResponse({"success": False, "message": "All fields are required."})

        try:
            dzongkhag = Dzongkhag.objects.get(dzo_id=dzongkhag_id)
            if gewog_id:
                gewog = Gewog.objects.get(gewog_id=gewog_id)
                gewog.name = name
                gewog.dzongkhag = dzongkhag
                status = "updated"
            else:
                gewog = Gewog.objects.create(name=name, dzongkhag=dzongkhag)
                status = "added"
            gewog.save()
            return JsonResponse({
                "success": True,
                "status": status,
                "gewog": {"gewog_id": gewog.gewog_id, "name": gewog.name}
            })
        except Exception as e:
            return JsonResponse({"success": False, "message": str(e)})
    return JsonResponse({"success": False, "message": "Invalid request"})

@csrf_exempt
def delete_gewog(request):
    if request.method == "POST":
        gewog_id = request.POST.get("gewog_id")
        try:
            gewog = Gewog.objects.get(gewog_id=gewog_id)
            gewog.delete()
            return JsonResponse({"success": True})
        except Gewog.DoesNotExist:
            return JsonResponse({"success": False, "message": "Gewog not found."})
    return JsonResponse({"success": False, "message": "Invalid request"})

def get_gewogs_by_dzongkhag(request):
    dzongkhag_id = request.GET.get('dzongkhag_id')
    if not dzongkhag_id:
        return JsonResponse({"gewogs": []})
    gewogs = Gewog.objects.filter(dzongkhag_id=dzongkhag_id).values('gewog_id', 'name')
    return JsonResponse({"gewogs": list(gewogs)}, safe=False)

@csrf_exempt
def save_village(request):
    if request.method == "POST":
        village_id = request.POST.get("village_id")
        name = request.POST.get("name")
        dzongkhag_id = request.POST.get("dzongkhag_id")
        gewog_id = request.POST.get("gewog_id")

        if not all([name, dzongkhag_id, gewog_id]):
            return JsonResponse({"success": False, "message": "All fields are required."})

        try:
            dzongkhag = Dzongkhag.objects.get(dzo_id=dzongkhag_id)
            gewog = Gewog.objects.get(gewog_id=gewog_id)

            if village_id:
                village = Village.objects.get(village_id=village_id)
                village.name = name
                village.dzongkhag = dzongkhag
                village.gewog = gewog
                status = "updated"
            else:
                village = Village.objects.create(name=name, dzongkhag=dzongkhag, gewog=gewog)
                status = "added"
            village.save()
            return JsonResponse({
                "success": True,
                "status": status,
                "village": {
                    "village_id": village.village_id,
                    "name": village.name
                }
            })
        except Exception as e:
            return JsonResponse({"success": False, "message": str(e)})
    return JsonResponse({"success": False, "message": "Invalid request"})

@csrf_exempt
def delete_village(request):
    if request.method == "POST":
        village_id = request.POST.get("village_id")
        try:
            village = Village.objects.get(village_id=village_id)
            village.delete()
            return JsonResponse({"success": True})
        except Village.DoesNotExist:
            return JsonResponse({"success": False, "message": "Village not found."})
    return JsonResponse({"success": False, "message": "Invalid request"})

def get_villages_by_gewog(request):
    gewog_id = request.GET.get('gewog_id')
    if gewog_id:
        villages = Village.objects.filter(gewog_id=gewog_id).values('village_id', 'name')
        return JsonResponse({'villages': list(villages)})
    return JsonResponse({'villages': []})

@login_required(login_url='/sign_in/')
def add_edit_rooms(request):
    # 🔥 Filter hotels: all if admin, only user's if not
    if request.user.user_role == 'admin':
        hotels = Hotel.objects.all().prefetch_related("hotel_room_types")
        # Admin sees all room types
        room_types = RoomType.objects.all().select_related('hotel')
    else:
        # Regular user: only rooms from their hotels
        hotels = Hotel.objects.filter(user=request.user).prefetch_related("hotel_room_types")
        room_types = RoomType.objects.filter(hotel__user=request.user).select_related('hotel')

    form = RoomTypeForm()

    context = {
        "hotels": hotels,
        "room_types": room_types,
        "room_choices": RoomType.ROOM_CHOICES,
        "form": form,
    }
    return render(request, 'janka_web_app/dashboard/hotels/room_details.html', context)

@transaction.atomic
def delete_room_type(request, room_id):
    if request.method != 'POST':
        return JsonResponse({'success': False, 'message': 'Invalid request'}, status=400)

    room = get_object_or_404(RoomType, id=room_id)
    hotel = room.hotel
    room_count = room.total_rooms
    room_name = room.get_room_type_display()

    # Delete room
    room.delete()

    # 🔼 Return rooms back to available quota
    hotel.available_rooms += room_count
    hotel.total_rooms -= room_count
    hotel.save()

    return JsonResponse({
        'success': True,
        'message': f'{room_name} ({room_count} room(s)) deleted. {room_count} room(s) returned to quota.'
    })

@transaction.atomic
def save_room_type(request):
    if request.method != 'POST':
        return JsonResponse({'success': False, 'message': 'Invalid request method.'}, status=405)

    # ✅ Get logged-in user
    user = request.user

    # ✅ Handle room_id safely
    room_id = request.POST.get('room_id') or None
    if room_id:
        try:
            room_id = int(room_id)
        except (ValueError, TypeError):
            return JsonResponse({'success': False, 'message': 'Invalid room ID.'}, status=400)

    hotel_id = request.POST.get('hotel_id')
    room_type = request.POST.get('room_type')
    description = request.POST.get('description', '')

    try:
        price_per_night = float(request.POST.get('price_per_night', 0))
        new_total_rooms = int(request.POST.get('total_rooms', 0))
    except (ValueError, TypeError):
        return JsonResponse({
            'success': False,
            'message': 'Invalid price or room count.'
        }, status=400)

    if not hotel_id or not room_type or new_total_rooms < 1 or price_per_night < 0:
        return JsonResponse({
            'success': False,
            'message': 'All fields are required and values must be valid.'
        }, status=400)

    # 🔐 Get hotel + enforce ownership or admin access
    hotel = get_object_or_404(Hotel, id=hotel_id)

    if hotel.user != user and user.user_role != 'admin':
        return JsonResponse({
            'success': False,
            'message': 'Unauthorized: You do not own this hotel.'
        }, status=403)

    # 🔁 Recalculate available_rooms based on existing room types
    actual_used = hotel.hotel_room_types.aggregate(total=Sum('total_rooms'))['total'] or 0
    hotel.available_rooms = hotel.total_rooms - actual_used
    hotel.save(update_fields=['available_rooms'])

    # 🔒 Prevent duplicate room type in this hotel
    if RoomType.objects.filter(hotel=hotel, room_type=room_type).exclude(id=room_id).exists():
        return JsonResponse({
            'success': False,
            'message': f'{hotel.name} already has a {dict(RoomType.ROOM_CHOICES)[room_type]}.'
        }, status=400)

    # 🔍 Get old room count if editing
    old_room_count = 0
    if room_id:
        room = get_object_or_404(RoomType, id=room_id, hotel=hotel)
        old_room_count = room.total_rooms

    # ✅ Calculate delta (change in room count)
    delta = new_total_rooms - old_room_count  # Can be negative (reducing rooms)

    # ❌ Only block if trying to *increase* beyond available capacity
    if delta > 0 and delta > hotel.available_rooms:
        return JsonResponse({
            'success': False,
            'message': (
                f"You cannot increase rooms by {delta} because only "
                f"{hotel.available_rooms} rooms are available."
            )
        }, status=400)

    # ✅ All checks passed — proceed to create or update
    if room_id:
        # Update existing room
        room.total_rooms = new_total_rooms
        room.room_type = room_type
        room.description = description
        room.price_per_night = price_per_night
        if 'room_image' in request.FILES:
            room.room_image = request.FILES['room_image']
        room.save()

        msg = f'Updated {room.get_room_type_display()} from {old_room_count} to {new_total_rooms} rooms.'
    else:
        # Create new room
        room = RoomType.objects.create(
            hotel=hotel,
            room_type=room_type,
            description=description,
            price_per_night=price_per_night,
            total_rooms=new_total_rooms
        )
        if 'room_image' in request.FILES:
            room.room_image = request.FILES['room_image']
            room.save()  # Save again to ensure image is stored
        msg = f'Created {room.get_room_type_display()} with {new_total_rooms} rooms.'

    # ✅ Final: Update hotel's available_rooms
    hotel.available_rooms -= delta
    hotel.save(update_fields=['available_rooms'])

    return JsonResponse({
        'success': True,
        'message': msg
    })

@login_required(login_url='/sign_in/')
def manage_bookings(request):
    user = request.user

    # Base queryset with select_related
    base_qs = Booking.objects.select_related('user', 'hotel', 'room_selected')

    if user.user_role == 'admin':
        bookings = base_qs.all()
    
    elif user.user_role in ['owner', 'user']:
        if user.user_role == 'owner':
            bookings = base_qs.filter(hotel__user=user)
        else:
            bookings = base_qs.filter(user=user)
    else:
        bookings = Booking.objects.none()

    # ✅ ANNOTATE WHETHER USER HAS REVIEWED THIS BOOKING
    if user.user_role == 'user':
        bookings = bookings.annotate(
            has_reviewed=Exists(
                Review.objects.filter(
                    user=user,
                    booking=OuterRef('pk')  # links to each booking in the queryset
                )
            )
        )
    else:
        # For admin/owner, we don't need this annotation (optional)
        bookings = bookings.annotate(has_reviewed=models.Value(False, output_field=models.BooleanField()))

    context = {
        'bookings': bookings,
        'status_choices': Booking.status_choices,
    }
    return render(request, 'janka_web_app/dashboard/booking/booking.html', context)

@csrf_exempt
@login_required
def update_booking_status(request):
    if request.method == "POST":
        try:
            booking_id = request.POST.get('booking_id')
            status = request.POST.get('status')

            booking = get_object_or_404(Booking, id=booking_id)

            # Validate status
            valid_statuses = dict(Booking.status_choices)
            if status not in valid_statuses:
                return JsonResponse({'error': 'Invalid status'}, status=400)

            # Save old status before update
            old_status = booking.status
            booking.status = status
            booking.save()

            # --- ✅ Get user's name safely ---
            user = booking.user
            name = user.full_name.strip() if user.full_name else user.username

            # --- ✅ Get room type name safely ---
            room_type_display = (
                booking.room_selected.get_room_type_display()
                if booking.room_selected
                else "Not specified"
            )

            # --- Prepare email content ---
            subject = ""
            message = ""

            if status == 'confirmed' and old_status != 'confirmed':
                subject = "✅ Your Booking at Janka Resort is Confirmed!"
                message = f"""
                            Hello {name},

                            Great news! Your booking at Janka Resort has been confirmed 🎉

                            Booking Details:
                            - Hotel: {booking.hotel.name}
                            - Room Type: {room_type_display}
                            - Check-In: {booking.check_in.strftime('%d %b, %Y')}
                            - Check-Out: {booking.check_out.strftime('%d %b, %Y')}
                            - Rooms: {booking.number_of_rooms}
                            - Guests: {booking.number_of_guests}
                            - Booking ID: {booking.id}

                            We can't wait to welcome you!

                            Warm regards,
                            Janka Resort Team
                                            """.strip()

            elif status == 'cancelled' and old_status != 'cancelled':
                subject = "❌ Your Booking at Janka Resort has been Cancelled"
                message = f"""
                            Hello {name},

                            We're sorry, but your booking at Janka Resort has been cancelled.

                            Booking Details:
                            - Hotel: {booking.hotel.name}
                            - Room Type: {room_type_display}
                            - Check-In: {booking.check_in.strftime('%d %b, %Y')}
                            - Check-Out: {booking.check_out.strftime('%d %b, %Y')}
                            - Rooms: {booking.number_of_rooms}
                            - Guests: {booking.number_of_guests}
                            - Booking ID: {booking.id}

                            If you have any questions, feel free to contact our support team.

                            Sincerely,
                            Janka Resort Team
                                            """.strip()
            # --- Send email if message exists ---
            if message and subject:
                recipient_email = user.email
                from_email = "no-reply@jankaresort.com"

                try:
                    send_mail(
                        subject=subject,
                        message=message,
                        from_email=from_email,
                        recipient_list=[recipient_email],
                        fail_silently=False,
                    )
                    print(f"📧 Email sent to {recipient_email} | Subject: {subject}")
                except Exception as email_error:
                    print(f"❌ Failed to send email: {email_error}")

            # ✅ Return success
            return JsonResponse({
                'success': True,
                'message': f'Booking status updated to {valid_statuses[status]}'
            })

        except Exception as e:
            print(f"🚨 Error in update_booking_status: {e}")
            return JsonResponse({'error': 'An error occurred'}, status=500)

    return JsonResponse({'error': 'Invalid request'}, status=400)
@require_POST
@login_required
def delete_booking(request, booking_id):
    try:
        if not booking_id:
            return JsonResponse({'success': False, 'error': 'No booking ID provided.'})

        # 👉 Get booking by ID from URL
        booking = get_object_or_404(Booking, id=booking_id)

        # 🔐 PERMISSION LOGIC
        user = request.user
        user_role = getattr(user, 'user_role', 'user')

        if user_role == 'admin':
            pass  # allow
        elif user_role == 'owner':
            if booking.hotel.user != user:
                return JsonResponse({'success': False, 'error': 'You can only delete bookings for your own hotels.'})
        else:
            return JsonResponse({'success': False, 'error': 'You do not have permission to delete bookings.'})

        # 🗑️ DELETE
        booking.delete()
        return JsonResponse({'success': True, 'message': 'Booking deleted successfully.'})

    except Exception as e:
        return JsonResponse({'success': False, 'error': 'An error occurred: ' + str(e)})
    
def hotel_detail(request, hotel_id):
    hotel = get_object_or_404(Hotel, id=hotel_id)
    room_types = []

    # Get today's date
    today = timezone.now().date()

    for room_type in hotel.hotel_room_types.all():
        confirmed_bookings = Booking.objects.filter(
            room_selected=room_type,
            status='confirmed'
        ).aggregate(total=Sum('number_of_rooms'))['total'] or 0

        available = room_type.total_rooms - confirmed_bookings
        if available > 0:
            room_types.append({
                'room_type': room_type,
                'confirmed_bookings': confirmed_bookings,
                'available_rooms': available,
            })

    # ✅ FETCH REVIEWS FOR THIS HOTEL — ORDERED BY NEWEST FIRST
    reviews = Review.objects.filter(
        hotel=hotel
    ).select_related(
        'user', 'booking'
    ).order_by('-created_at')[:10]  # Limit to 10 latest

    context = {
        'hotel': hotel,
        'room_types': room_types,
        'reviews': reviews,  # 👈 Pass to template
    }
    return render(request, 'janka_web_app/room_details.html', context)

@login_required
def create_booking(request):
    if request.method != 'POST':
        return JsonResponse({'error': 'Invalid request method.'}, status=405)

    try:
        hotel_id = request.POST.get('hotel_id')
        room_type_id = request.POST.get('room_type_id')
        check_in_str = request.POST.get('check_in')
        check_out_str = request.POST.get('check_out')
        number_of_rooms = int(request.POST.get('number_of_rooms', 1))
        number_of_guests = int(request.POST.get('number_of_guests', 1))

        # Validate inputs
        if not all([hotel_id, room_type_id, check_in_str, check_out_str]):
            return JsonResponse({'error': 'Missing required fields.'}, status=400)

        hotel = get_object_or_404(Hotel, id=hotel_id)
        room_type = get_object_or_404(RoomType, id=room_type_id)

        check_in = parse_date(check_in_str)
        check_out = parse_date(check_out_str)

        if not check_in or not check_out:
            return JsonResponse({'error': 'Invalid date format.'}, status=400)

        if check_in >= check_out:
            return JsonResponse({'error': 'Check-out must be after check-in.'}, status=400)

        if check_in < date.today():
            return JsonResponse({'error': 'Check-in date cannot be in the past.'}, status=400)

        # Check availability
        overlapping_bookings = Booking.objects.filter(
            room_selected=room_type,
            status__in=['pending', 'confirmed'],
            check_in__lt=check_out,
            check_out__gt=check_in
        ).aggregate(total=models.Sum('number_of_rooms'))['total'] or 0

        available_rooms = room_type.total_rooms - overlapping_bookings

        if number_of_rooms > available_rooms:
            return JsonResponse({
                'error': f"Only {available_rooms} room(s) available for this period."
            }, status=400)

        # ✅ Create booking
        booking = Booking.objects.create(
            hotel=hotel,
            user=request.user,
            room_selected=room_type,
            check_in=check_in,
            check_out=check_out,
            number_of_rooms=number_of_rooms,
            number_of_guests=number_of_guests,
            status='pending'
        )
        # ✅ Create notification for the hotel owner only
        Notification.objects.create(
            title="New Booking Request",
            message=f"{request.user.username} has requested a booking for {room_type.get_room_type_display()} at {hotel.name}.",
            category="user_event",
            role_visibility="owner",
            created_by=request.user.username,
            recipient_user=hotel.user,
            action_url=f"/manage-bookings/"
        )
        return JsonResponse({
            'success': True,
            'message': f'Booking confirmed! We’ve saved your {booking.number_of_rooms} room(s) from {booking.check_in} to {booking.check_out}.'
        })

    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)
    
@login_required(login_url='/sign_in/')
def messages(request):
    # 🔥 Get all messages where user is sender OR receiver
    user_messages = Message.objects.filter(
        sender=request.user
    ) | Message.objects.filter(
        receiver=request.user
    )
    user_messages = user_messages.select_related('sender', 'receiver').order_by('-created_at')

    # Optional: Get all users (for reply dropdown)
    all_users = User.objects.exclude(id=request.user.id).order_by('username')

    context = {
        'user_messages': user_messages,
        'all_users': all_users,
    }
    return render(request, 'janka_web_app/dashboard/message/message.html', context)

@login_required
def send_message(request):
    if request.method != 'POST':
        return JsonResponse({'success': False, 'message': 'Invalid request method.'}, status=405)

    receiver_id = request.POST.get('receiver_id')
    subject = request.POST.get('subject', '').strip()
    message = request.POST.get('message', '').strip()
    original_message_id = request.POST.get('original_message_id')  # ✅ Get original message ID

    if not receiver_id or not message:
        return JsonResponse({
            'success': False,
            'message': 'Receiver and message are required.'
        }, status=400)

    try:
        receiver = User.objects.get(id=receiver_id)
    except User.DoesNotExist:
        return JsonResponse({'success': False, 'message': 'Receiver not found.'}, status=404)

    if receiver == request.user:
        return JsonResponse({'success': False, 'message': 'You cannot message yourself.'}, status=400)

    # ✅ Create the reply message
    Message.objects.create(
        sender=request.user,
        receiver=receiver,
        subject=subject,
        message=message
    )

    # ✅ Mark original message as read (if provided and belongs to current user)
    if original_message_id:
        try:
            original_message = Message.objects.get(id=original_message_id, receiver=request.user)
            if not original_message.read:
                original_message.read = True
                original_message.save(update_fields=['read'])
        except Message.DoesNotExist:
            # Ignore if not found or not owned
            pass

    # ✅ Send email notification
    email = receiver.email
    email_body = f"""
        Hello {receiver.username},

        You just received a message from {request.user.username} about: {subject}

        Message:
        {message}

        Best regards,
        Janka Resort Team
            """.strip()
    send_mail(
        subject=subject,
        message=email_body,
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[email],
        fail_silently=True
    )

    return JsonResponse({
        'success': True,
        'message': 'Message sent successfully!'
    })

def notifications_list(request):
    notifications = Notification.objects.filter(recipient_user=request.user).order_by('-created_at')
    context = {'notifications':notifications}
    return render(request, 'janka_web_app/dashboard/notification_list.html', context)

@login_required
def message_redirect(request, message_id):
    """
    Mark message as read and redirect to inbox or message detail
    """
    message = get_object_or_404(
        Message,
        id=message_id,
        receiver=request.user  # Only the receiver can access
    )

    # Mark as read if not already
    if not message.read:
        message.read = True
        message.save(update_fields=['read'])

    # Redirect to inbox or message detail page
    return redirect('messages')  # or your message detail page

@login_required
def review_page(request):
    # Get all reviews by current user, with related hotel, room, and booking
    reviews = Review.objects.filter(
        user=request.user
    ).select_related(
        'hotel', 
        'room_type', 
        'booking'
    ).order_by('-created_at')  # Newest first

    context = {
        'reviews': reviews,
    }
    return render(request, 'janka_web_app/dashboard/review.html', context)

@login_required
@csrf_exempt
def submit_review(request):
    if request.method == "POST":
        booking_id = request.POST.get("booking_id")
        rating = request.POST.get("rating")
        comment = request.POST.get("comment", "").strip()

        try:
            booking = Booking.objects.get(id=booking_id, user=request.user)

            # ✅ CHECK IF REVIEW ALREADY EXISTS
            if Review.objects.filter(user=request.user, booking=booking).exists():
                return JsonResponse({
                    "success": False,
                    "error": f"You’ve already reviewed this stay on {booking.check_in.strftime('%d %b %Y')}."
                })

            # ✅ CREATE REVIEW
            Review.objects.create(
                hotel=booking.hotel,
                room_type=booking.room_selected,
                user=request.user,
                booking=booking,  # 👈 link to booking
                rating=int(rating),
                comment=comment
            )
            return JsonResponse({"success": True, "message": "Review submitted successfully!"})

        except Booking.DoesNotExist:
            return JsonResponse({"success": False, "error": "Booking not found or unauthorized."})
        except Exception as e:
            return JsonResponse({"success": False, "error": str(e)})

    return JsonResponse({"success": False, "error": "Invalid request method."})

@login_required
def check_review_exists(request):
    if request.method == "GET":
        booking_id = request.GET.get("booking_id")
        try:
            booking = Booking.objects.get(id=booking_id, user=request.user)
            exists = Review.objects.filter(user=request.user, booking=booking).exists()
            if exists:
                review_date = booking.check_in.strftime('%d %b %Y')
                return JsonResponse({
                    "exists": True,
                    "message": f"You’ve already reviewed this stay on {review_date}."
                })
            else:
                return JsonResponse({"exists": False})
        except Booking.DoesNotExist:
            return JsonResponse({"exists": False})  # or error, but safer to let them proceed
    return JsonResponse({"error": "Invalid request"}, status=400)

def gallery(request):
    gallery_items = GalleryImage.objects.all().order_by('-uploaded_at')
    return render(request, 'janka_web_app/gallery.html', {
        'gallery_items': gallery_items
    })

@csrf_exempt
@login_required(login_url='/sign_in/')
def save_gallery_category(request):
    if request.method == 'POST':
        category_id = request.POST.get('category_id')
        name = request.POST.get('name', '').strip()
        description = request.POST.get('description', '').strip()

        if not name:
            return JsonResponse({'success': False, 'message': 'Name is required'})

        if category_id:
            # Edit existing
            try:
                category = GalleryCategory.objects.get(id=category_id)
                category.name = name
                category.description = description
                category.save()
                status = "updated"
            except GalleryCategory.DoesNotExist:
                return JsonResponse({'success': False, 'message': 'Category not found'})
        else:
            # Create new
            category = GalleryCategory.objects.create(
                name=name,
                description=description
            )
            status = "created"

        return JsonResponse({
            'success': True,
            'status': status,
            'category': {
                'id': category.id,
                'name': category.name,
                'slug': category.slug,
                'description': category.description
            }
        })
    return JsonResponse({'success': False, 'message': 'Invalid request'})

@csrf_exempt
@login_required(login_url='/sign_in/')
def delete_gallery_category(request):
    if request.method == 'POST':
        category_id = request.POST.get('category_id')
        if not category_id:
            return JsonResponse({'success': False, 'message': 'No category ID provided'})

        try:
            category = GalleryCategory.objects.get(id=category_id)
            category_name = category.name
            category.delete()
            return JsonResponse({
                'success': True,
                'message': f'Category "{category_name}" deleted successfully'
            })
        except GalleryCategory.DoesNotExist:
            return JsonResponse({'success': False, 'message': 'Category not found'})
    return JsonResponse({'success': False, 'message': 'Invalid request'})

def gallery_page_settings(request):
    gallery_images = GalleryImage.objects.all()
    categories = GalleryCategory.objects.all()
    context = {
        'gallery_images': gallery_images,
        'categories': categories
    }
    return render(request, 'janka_web_app/dashboard/page_settings/gallery.html', context)

from .forms import GalleryImageForm

# views.py

@login_required
def add_gallery_image(request):
    if request.method == 'POST':
        form = GalleryImageForm(request.POST, request.FILES)
        if form.is_valid():
            image = form.save()
            return JsonResponse({
                'success': True,
                'message': f'✅ Image "{image.title}" added successfully!'
            })
        else:
            return JsonResponse({
                'success': False,
                'error': 'Please check the form for errors.'
            })

@login_required
def update_gallery_image(request):
    if request.method == 'POST':
        image_id = request.POST.get('image_id')
        try:
            image = GalleryImage.objects.get(id=image_id)
            form = GalleryImageForm(request.POST, request.FILES, instance=image)
            if form.is_valid():
                form.save()
                return JsonResponse({
                    'success': True,
                    'message': f'✅ Image updated successfully!'
                })
            else:
                return JsonResponse({
                    'success': False,
                    'error': 'Please check the form for errors.'
                })
        except GalleryImage.DoesNotExist:
            return JsonResponse({
                'success': False,
                'error': 'Image not found.'
            })

def delete_gallery_image(request, pk):
    if request.method == 'POST':
        try:
            image = GalleryImage.objects.get(pk=pk)
            image.delete()
            return JsonResponse({'success': True})
        except GalleryImage.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Image not found'})