from django.shortcuts import render, get_object_or_404
from .models import Property, PropertyGallery
from category.models import category
from location.models import Location
from django.contrib.admin.views.decorators import staff_member_required
from django.db.models import Count, Avg, Q, Sum
from django.utils.timezone import now, timedelta
from django.http import JsonResponse
import json
from django.contrib.admin import site

def comprar(request, location_slug=None):
    location = None
    properties = Property.objects.filter(purpose='sale', is_available=True)  # Filtro por tipo de transacción
    if location_slug:
        location = get_object_or_404(Location, slug=location_slug)
        properties = properties.filter(location=location)

    # Obtener ubicaciones únicas para filtros
    locations = Location.objects.filter(
        property__purpose='sale', 
        property__is_available=True
    ).distinct()

    property_count = properties.count()
    
    # Manejo seguro de precios
    precios = list(properties.values_list('price', flat=True))
    precio_maximo = max(precios) if precios else None
    precio_minimo = min(precios) if precios else None

    context = {
        'properties': properties,
        'locations': locations,
        'property_count': property_count,
        'precio_maximo': precio_maximo,
        'precio_minimo': precio_minimo,
    }
    
    return render(request, 'agency/comprar.html', context)

def rentar(request, location_slug=None):
    location = None
    properties = Property.objects.filter(purpose='rent', is_available=True)  # Filtro por tipo de transacción

    if location_slug:
        location = get_object_or_404(Location, slug=location_slug)
        properties = properties.filter(location=location)

    # Obtener ubicaciones únicas para filtros
    locations = Location.objects.filter(
        property__purpose='rent', 
        property__is_available=True
    ).distinct()

    property_count = properties.count()
    
    # Manejo seguro de precios
    precios = list(properties.values_list('price', flat=True))
    precio_maximo = max(precios) if precios else None
    precio_minimo = min(precios) if precios else None

    context = {
        'properties': properties,
        'locations': locations,
        'property_count': property_count,
        'precio_maximo': precio_maximo,
        'precio_minimo': precio_minimo,
    }
    return render(request, 'agency/rentar.html', context)

def property_detail(request, category_slug, property_slug):
    try:
        single_property=Property.objects.get(category__slug=category_slug,slug=property_slug)
    except Exception as e:
        raise e

    # get the property gallery
    property_gallery = PropertyGallery.objects.filter(property_id=single_property.id)
    precio=int_a_moneda_str(int(single_property.price))
    mensaje="'"+single_property.property_name.replace(" ", "%20")+"'%20por%20valor%20de%20$%20"+precio+"%20COP,%20por%20favor%20darme%20más%20información."
    context = {
        'single_property':single_property,
        'property_gallery':property_gallery,
        'mensaje':mensaje,
    }
    return render(request,'agency/property_detail.html',context)

def inicio(request):
    return render(request,'agency/inicio.html')

def int_a_moneda_str(numero):
    # Convierte el número a una cadena
    numero_str = str(numero)

    # Divide el número en grupos de tres dígitos desde la derecha
    grupos = []
    while numero_str:
        grupos.append(numero_str[-3:])
        numero_str = numero_str[:-3]

    # Invierte la lista de grupos y únela con puntos
    numero_formateado = '.'.join(reversed(grupos))

    return numero_formateado

@staff_member_required
def dashboard_stats(request):
    """Vista principal del dashboard de estadísticas"""
    
    # Métricas principales
    total_properties = Property.objects.count()
    available_properties = Property.objects.filter(is_available=True).count()
    featured_properties = Property.objects.filter(is_featured=True).count()
    verified_properties = Property.objects.filter(is_verified=True).count()
    
    # Propiedades por propósito
    rent_properties = Property.objects.filter(purpose='rent').count()
    sale_properties = Property.objects.filter(purpose='sale').count()
    
    # Promedios
    avg_price = Property.objects.aggregate(Avg('price'))['price__avg'] or 0
    avg_area = Property.objects.aggregate(Avg('area'))['area__avg'] or 0
    avg_bedrooms = Property.objects.aggregate(Avg('bedrooms'))['bedrooms__avg'] or 0
    avg_bathrooms = Property.objects.aggregate(Avg('bathrooms'))['bathrooms__avg'] or 0
    
    # Propiedades por categoría
    properties_by_category = category.objects.annotate(
        total_properties=Count('property'),
        available_properties=Count('property', filter=Q(property__is_available=True)),
        avg_price=Avg('property__price')
    ).order_by('-total_properties')
    
    # Propiedades por ubicación
    properties_by_location = Location.objects.annotate(
        total_properties=Count('property'),
        available_properties=Count('property', filter=Q(property__is_available=True)),
        avg_price=Avg('property__price')
    ).order_by('-total_properties')
    
    # Estadísticas temporales (últimos 30 días)
    thirty_days_ago = now() - timedelta(days=30)
    recent_properties = Property.objects.filter(created_date__gte=thirty_days_ago).count()
    recent_modifications = Property.objects.filter(modified_date__gte=thirty_days_ago).count()
    
    # Propiedades por características más comunes
    features_stats = {}
    services_stats = {}
    rules_stats = {}
    
    # Contar características
    features_stats = {}
    for feature_code, feature_name in Property.FEATURES:
        count = Property.objects.filter(
            Q(features__icontains=f'"{feature_code}"') |
            Q(features__icontains=f"'{feature_code}'")
        ).count()
        if count > 0:
            features_stats[str(feature_name)] = count
    
    # Contar servicios (adaptado para SQLite)
    services_stats = {}
    for service_code, service_name in Property.SERVICES:
        count = Property.objects.filter(
            Q(services__icontains=f'"{service_code}"') |  # Para formato JSON: ["code"]
            Q(services__icontains=f"'{service_code}'")    # Para formato alternativo: ['code']
        ).count()
        if count > 0:
            services_stats[str(service_name)] = count

    # Contar reglas (adaptado para SQLite)
    rules_stats = {}
    for rule_code, rule_name in Property.RULES:
        count = Property.objects.filter(
            Q(rules__icontains=f'"{rule_code}"') |  # Para formato JSON
            Q(rules__icontains=f"'{rule_code}'")    # Para formato alternativo
        ).count()
        if count > 0:
            rules_stats[str(rule_name)] = count
    
    # Propiedades amobladas vs no amobladas
    furnished_count = Property.objects.filter(is_furnished=True).count()
    unfurnished_count = Property.objects.filter(is_furnished=False).count()
    
    # Rangos de precios
    price_ranges = {
        'Menos de $500,000': Property.objects.filter(price__lt=500000).count(),
        '$500,000 - $1,000,000': Property.objects.filter(price__gte=500000, price__lt=1000000).count(),
        '$1,000,000 - $2,000,000': Property.objects.filter(price__gte=1000000, price__lt=2000000).count(),
        '$2,000,000 - $5,000,000': Property.objects.filter(price__gte=2000000, price__lt=5000000).count(),
        'Más de $5,000,000': Property.objects.filter(price__gte=5000000).count(),
    }
    
    # Rangos de área
    area_ranges = {
        'Menos de 50 m²': Property.objects.filter(area__lt=50).count(),
        '50-100 m²': Property.objects.filter(area__gte=50, area__lt=100).count(),
        '100-200 m²': Property.objects.filter(area__gte=100, area__lt=200).count(),
        '200-300 m²': Property.objects.filter(area__gte=200, area__lt=300).count(),
        'Más de 300 m²': Property.objects.filter(area__gte=300).count(),
    }
    
    # Total de imágenes en galería
    total_images = PropertyGallery.objects.count()
    properties_with_images = Property.objects.filter(images__isnull=False).distinct().count()
    
    admin_context = site.each_context(request)

    context = {
        # Métricas principales
        'total_properties': total_properties,
        'available_properties': available_properties,
        'featured_properties': featured_properties,
        'verified_properties': verified_properties,
        'rent_properties': rent_properties,
        'sale_properties': sale_properties,
        
        # Promedios
        'avg_price': round(avg_price, 0),
        'avg_area': round(avg_area, 1),
        'avg_bedrooms': round(avg_bedrooms, 1),
        'avg_bathrooms': round(avg_bathrooms, 1),
        
        # Distribuciones
        'properties_by_category': properties_by_category,
        'properties_by_location': properties_by_location,
        
        # Temporales
        'recent_properties': recent_properties,
        'recent_modifications': recent_modifications,
        
        # Características
        'features_stats': features_stats,
        'services_stats': services_stats,
        'rules_stats': rules_stats,
        
        # Amoblado
        'furnished_count': furnished_count,
        'unfurnished_count': unfurnished_count,
        
        # Rangos
        'price_ranges': price_ranges,
        'area_ranges': area_ranges,
        
        # Imágenes
        'total_images': total_images,
        'properties_with_images': properties_with_images,
        
        # Para gráficos JSON
        'categories_data': json.dumps([{
            'name': cat.category_name,
            'count': cat.total_properties
        } for cat in properties_by_category]),
        
        'locations_data': json.dumps([{
            'name': loc.location_name,
            'count': loc.total_properties
        } for loc in properties_by_location[:10]]),  # Top 10 ubicaciones
        
        'purpose_data': json.dumps([
            {'name': 'Venta', 'count': sale_properties},
            {'name': 'Renta', 'count': rent_properties}
        ]),
        
        'price_ranges_data': json.dumps([{
            'range': k,
            'count': v
        } for k, v in price_ranges.items() if v > 0]),
    }
    
    context.update(admin_context)
    
    return render(request, 'admin/dashboard_stats.html', context)

@staff_member_required
def api_chart_data(request):
    """API para datos de gráficos dinámicos"""
    chart_type = request.GET.get('type', '')
    
    if chart_type == 'monthly_properties':
        # Propiedades creadas por mes (últimos 12 meses)
        from django.db.models.functions import TruncMonth
        monthly_data = Property.objects.filter(
            created_date__gte=now() - timedelta(days=365)
        ).annotate(
            month=TruncMonth('created_date')
        ).values('month').annotate(
            count=Count('id')
        ).order_by('month')
        
        return JsonResponse({
            'data': list(monthly_data)
        })
    
    elif chart_type == 'price_by_location':
        # Precio promedio por ubicación
        location_prices = Location.objects.annotate(
            avg_price=Avg('property__price'),
            count=Count('property')
        ).filter(count__gt=0).order_by('-avg_price')[:10]
        
        return JsonResponse({
            'labels': [loc.location_name for loc in location_prices],
            'prices': [float(loc.avg_price or 0) for loc in location_prices]
        })
    
    return JsonResponse({'error': 'Invalid chart type'})