from django.http import FileResponse, Http404, HttpResponseNotAllowed
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.admin.models import LogEntry
from django.shortcuts import render
from django.db.models import Sum, Count
from django.utils import timezone
from django.conf import settings
from dateutil.relativedelta import relativedelta
from calendar import month_name
from datetime import datetime
import os
import mimetypes

from tenant.models import TenantRent, TenantRoom
from tenant.services import is_checkout_action
from paymentlog.models import PaymentLog
from room.models import Room
from room.services import get_room_occupancy
from meal.models import Meal



def serve_media_files(request, path):
    """
    View to serve media files in production.
    """
    if request.method != 'GET':
        return HttpResponseNotAllowed(['GET'])  # Only allow GET requests

    full_path = os.path.join(settings.MEDIA_ROOT, path)

    # Security check: VERY IMPORTANT
    if not full_path.startswith(settings.MEDIA_ROOT):
        raise Http404("File not found")

    if os.path.exists(full_path):
        try:
            # 1. Guess the content type
            content_type, _ = mimetypes.guess_type(full_path)

            # 2. Set a default content type if guessing fails
            if content_type is None:
                content_type = 'application/octet-stream'  # Default for downloads

            # 3. Use FileResponse with the correct content type
            return FileResponse(open(full_path, 'rb'), content_type=content_type)
        except FileNotFoundError:
            raise Http404("File not found")
    else:
        raise Http404("File not found")


@staff_member_required
def admin_dashboard(request):
    # Get current date
    today = timezone.now()
    total_revenue = 0
    # Calculate total revenue
    total_security_amount = TenantRent.objects.aggregate( # type: ignore
        total=Sum('security_amount')
    )['total'] or 0

    total_revenue = PaymentLog.objects.filter().aggregate( # type: ignore
        total=Sum('amount')
    )['total'] or 0

    paid_payments = PaymentLog.objects.filter(status="paid").aggregate( # type: ignore
        total=Sum('amount')
    )['total'] or 0

    pending_payments = PaymentLog.objects.filter(status="pending").aggregate( # type: ignore
        total=Sum('amount')
    )['total'] or 0


    # Get total number of tenants
    active_tenants = TenantRoom.objects.filter(is_active=True).count() # type: ignore

    most_popular_meal = Meal.objects.filter(price_per_month__gt=0).annotate( # type: ignore
        tenant_count=Count('tenant_meals')
    ).order_by('-tenant_count').first()

    # for meal popularity graph
    meal_stats = Meal.objects.annotate( # type: ignore
        tenant_count=Count('tenant_meals')
    ).order_by('-tenant_count')

    meal_labels = [meal.name for meal in meal_stats]
    meal_data = [meal.tenant_count for meal in meal_stats]


    # Get recent actions
    recent_activities = LogEntry.objects.select_related('content_type', 'user')[:10]

    # Format the actions for display
    formatted_activities = []
    for action in recent_activities:
        if action.action_flag != 3:
            obj = action.get_edited_object()

            if action.content_type.model == "tenant":
                formatted_activities.append({
                    'user': action.user.get_full_name() or action.user.username,
                    'action_type': action.get_action_flag_display(),
                    'object_name': action.object_repr,
                    'model': action.content_type.model,
                    'description': action.content_type.app_label,
                    'timestamp': action.action_time,
                    'object': obj,
                    'is_checkout_action': is_checkout_action(action)
                })
            else:
                formatted_activities.append({
                    'user': action.user.get_full_name() or action.user.username,
                    'action_type': action.get_action_flag_display(),
                    'object_name': action.object_repr,
                    'model': action.content_type.model,
                    'description': action.content_type.app_label,
                    'timestamp': action.action_time,
                    'object': obj,
                })
        else:
            formatted_activities.append({
                'user': action.user.get_full_name() or action.user.username,
                'action_type': action.get_action_flag_display(),
                'object_name': action.object_repr,
                'model': action.content_type.model,
                'description': action.content_type.app_label,
                'timestamp': action.action_time
            })

    # Get active rooms count
    rooms = Room.objects.all() # type: ignore
    active_rooms = 0
    rooms_occupied = 0
    for room in rooms:
        occupancy = get_room_occupancy(room.id)
        if room.is_bookable:
            active_rooms += 1
        if occupancy > 0:
            rooms_occupied += 1


    # Calculate current month's revenue
    current_month_revenue = PaymentLog.objects.filter( # type: ignore
        created_at__year=today.year,
        created_at__month=today.month,
        status="paid"
    ).aggregate(
        total=Sum('amount')
    )['total'] or 0

    # Calculate last 6 months revenue
    months = []
    monthly_revenue = []

    for i in range(5, -1, -1):
        date = today - relativedelta(months=i)
        month_revenue = PaymentLog.objects.filter( # type: ignore
            created_at__year=date.year,
            created_at__month=date.month,
            status="paid"
        ).aggregate(
            total=Sum('amount')
        )['total'] or 0

        months.append(month_name[date.month][:3])
        monthly_revenue.append(float(month_revenue))

    context = {
        'total_revenue': round(total_revenue, 2),
        'paid_payments': round(paid_payments, 2),
        'pending_payments': round(pending_payments, 2),
        'total_security_amount': round(total_security_amount, 2),

        'active_tenants': active_tenants,
        'total_rooms': len(rooms),
        'rooms_occupied': rooms_occupied,
        'most_popular_meal': most_popular_meal,
        'current_month_revenue': round(current_month_revenue, 2),

        # for monthley revenue chart
        'months': months,
        'monthly_revenue': monthly_revenue,

        # for meal popularity chart
        'meal_labels': meal_labels,
        'meal_data': meal_data,

        'recent_activities': formatted_activities
    }

    return render(request, 'utils/dashboard.html', context)
