# views.py optimizado
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.views.decorators.http import require_GET
from functools import wraps
from django.utils import timezone
from django.utils.text import slugify
from django.utils.crypto import get_random_string
from decimal import Decimal
from django.db.models import Max, Count, Sum
from django.urls import reverse
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.db.models import Q, Count, Case, When, IntegerField
from .models import LogisticaKit, Inscripcion, Grupo, InventarioGlobal 
# En las primeras líneas de views.py, agrega:
from django.core.paginator import Paginator
# Agrega estas importaciones si no las tienes:
from django.core.paginator import Paginator
from django.db.models import Q, Count, Case, When, IntegerField, F
from django.http import JsonResponse
import json
from django.utils import timezone

from .models import (
    Publicacion, Noticia, Grupo, Inscripcion, Usuario,
    LogisticaKit, InventarioGlobal, Actividad, Notificacion,
    Iglesia, Union, Reaccion, Comentario, HistorialPuntos
)

# Importación de formularios
from .forms import (
    PublicacionForm, InscripcionForm, GrupoForm, ActividadForm,
    NoticiaForm, IglesiaForm, UnionForm, InventarioForm,
    UsuarioCrearForm, UsuarioEditarForm, HistorialPuntosForm,
    InscripcionUnificadoForm
)

# Importación de utilidades
from .utils import asignar_grupo_automatico

# ============ DECORADORES DE PERMISOS ============
def require_role(*roles):
    """Decorador para restricción de acceso por rol"""
    def decorator(view_func):
        @wraps(view_func)
        def wrapper(request, *args, **kwargs):
            if not request.user.is_authenticated:
                messages.warning(request, 'Debes iniciar sesión para acceder a esta página.')
                return redirect('login')
            
            # Admin tiene acceso a todo
            if request.user.rol == 'admin':
                return view_func(request, *args, **kwargs)
            
            # Verificar si el usuario tiene uno de los roles requeridos
            if request.user.rol not in roles:
                messages.error(request, 'No tienes permiso para acceder a esta página.')
                return redirect('muro')
            
            return view_func(request, *args, **kwargs)
        return wrapper
    return decorator

# ============ VISTAS DE AUTENTICACIÓN ============
def home_view(request):
    """Vista de inicio con botón de login"""
    if request.user.is_authenticated:
        if request.user.rol == 'admin':
            return redirect('dashboard')
        else:
            return redirect('muro')
    
    return render(request, 'principal/home.html')

def login_view(request):
    """Vista de login"""
    if request.user.is_authenticated:
        if request.user.rol == 'admin':
            return redirect('dashboard')
        else:
            return redirect('muro')
    
    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)
            messages.success(request, f'Bienvenido {user.first_name or user.username}')
            
            if user.rol == 'admin':
                return redirect('dashboard')
            else:
                return redirect('muro')
        else:
            messages.error(request, 'Usuario o contraseña incorrectos.')
    
    return render(request, 'principal/login.html')

def logout_view(request):
    """Vista de logout"""
    logout(request)
    messages.success(request, 'Has cerrado sesión correctamente.')
    return redirect('home')

# ============ VISTAS PRINCIPALES ============
@require_role('admin')
def dashboard(request):
    """Dashboard solo para administradores"""
    user = request.user
    
    contexto = {
        'user': user,
        'rol_display': dict(user.ROLES).get(user.rol, user.rol),
        'notificaciones_no_leidas': user.notificaciones.filter(leida=False).count(),
        'total_inscritos': Inscripcion.objects.count(),
        'total_grupos': Grupo.objects.count(),
        'total_actividades': Actividad.objects.count(),
        'total_noticias': Noticia.objects.count(),
        'grupos': Grupo.objects.all().order_by('-puntos_totales'),
        'actividades': Actividad.objects.all().order_by('hora_inicio'),
        'noticias': Noticia.objects.all().order_by('-fecha_publicacion'),
        'publicaciones': Publicacion.objects.all().order_by('-fecha_creacion')[:10],
    }
    
    return render(request, 'principal/dashboard.html', contexto)

@require_role('campamentista', 'inscripcion', 'director', 'admin', 'lider', 'pastor')
def muro_social(request):
    """Muro social con publicaciones y noticias"""
    if request.method == 'POST' and request.user.is_authenticated:
        form = PublicacionForm(request.POST, request.FILES)
        if form.is_valid():
            post = form.save(commit=False)
            post.usuario = request.user
            post.save()
            messages.success(request, 'Publicación creada correctamente.')
            return redirect('muro')
    
    # Obtener likes del usuario actual
    user_likes = []
    if request.user.is_authenticated:
        user_likes = Reaccion.objects.filter(
            usuario=request.user, 
            tipo='like'
        ).values_list('publicacion_id', flat=True)
    
    notificaciones_no_leidas = 0
    if request.user.is_authenticated:
        notificaciones_no_leidas = request.user.notificaciones.filter(leida=False).count()
    
    contexto = {
        'publicaciones': Publicacion.objects.all().order_by('-fecha_creacion'),
        'noticias': Noticia.objects.all().order_by('-fecha_publicacion'),
        'grupos': Grupo.objects.all().order_by('-puntos_totales'),
        'form': PublicacionForm(),
        'user_likes': user_likes,
        'notificaciones_no_leidas': notificaciones_no_leidas,
    }
    return render(request, 'principal/muro.html', contexto)


@login_required
def editar_publicacion(request, publicacion_id):
    """Permite al autor o al admin editar una publicación."""
    publicacion = get_object_or_404(Publicacion, id=publicacion_id)
    # Permiso: autor o admin
    if request.user != publicacion.usuario and request.user.rol != 'admin':
        messages.error(request, 'No tienes permiso para editar esta publicación.')
        return redirect('muro')

    if request.method == 'POST':
        form = PublicacionForm(request.POST, request.FILES, instance=publicacion)
        if form.is_valid():
            form.save()
            messages.success(request, 'Publicación actualizada correctamente.')
            return redirect('muro')
    else:
        form = PublicacionForm(instance=publicacion)

    return render(request, 'principal/publicacion_editar.html', {
        'form': form,
        'publicacion': publicacion,
    })


@login_required
def eliminar_publicacion(request, publicacion_id):
    """Permite al autor o al admin eliminar una publicación."""
    publicacion = get_object_or_404(Publicacion, id=publicacion_id)
    if request.method != 'POST':
        messages.error(request, 'Método no permitido.')
        return redirect('muro')

    if request.user != publicacion.usuario and request.user.rol != 'admin':
        messages.error(request, 'No tienes permiso para eliminar esta publicación.')
        return redirect('muro')

    publicacion.delete()
    messages.success(request, 'Publicación eliminada.')
    return redirect('muro')

@require_role('campamentista', 'inscripcion', 'director', 'admin', 'lider')
def ranking_grupos(request):
    """Vista detallada del ranking de competencia"""
    grupos = Grupo.objects.all().order_by('-puntos_totales')
    notificaciones_no_leidas = 0
    if request.user.is_authenticated:
        notificaciones_no_leidas = request.user.notificaciones.filter(leida=False).count()
    
    return render(request, 'principal/ranking.html', {
        'grupos': grupos,
        'notificaciones_no_leidas': notificaciones_no_leidas,
    })

def detalle_grupo(request, grupo_id):
    """Vista de integrantes e historial de un grupo específico"""
    grupo = get_object_or_404(Grupo, id=grupo_id)
    miembros = grupo.miembros.all().order_by('nombre_persona')
    historial = HistorialPuntos.objects.filter(grupo=grupo).order_by('-fecha')
    return render(request, 'principal/detalle_grupo.html', {
        'grupo': grupo, 
        'miembros': miembros,
        'historial': historial
    })

def pantalla_ruleta(request):
    """Vista para la pantalla de ruleta con grupos reales"""
    grupos = Grupo.objects.all()
    contexto = {
        'grupos_json': list(grupos.values('nombre', 'color_hex', 'color_nombre', 'puntos_totales'))
    }
    return render(request, 'principal/pantalla_ruleta.html', contexto)

# ============ VISTAS DE INSCRIPCIONES (MODIFICADAS) ============

# views.py - Función lista_inscritos completa
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.utils import timezone
from decimal import Decimal
from django.db.models import Max, Count, Sum, Q
from django.db import transaction, IntegrityError
import json

@require_role('inscripcion', 'admin')
def lista_inscritos(request):
    """
    Vista principal para listar y crear inscripciones usando formulario unificado
    Gestiona tanto inscripciones como entrega de kits en la misma página
    """
    
    # ============ PROCESAR FORMULARIOS (POST) ============
    if request.method == 'POST':
        form_type = request.POST.get('form_type')
        
        # ============ FORMULARIO DE ENTREGA DE KIT ============
        if form_type == 'kit_delivery':
            inscripcion_id = request.POST.get('inscripcion_id')
            inscripcion = get_object_or_404(Inscripcion, id=inscripcion_id)
            
            # Obtener o crear el kit
            kit, created = LogisticaKit.objects.get_or_create(
                inscripcion=inscripcion,
                defaults={
                    'pañoleta_color': inscripcion.grupo.color_hex if inscripcion.grupo else '#000000',
                    'manilla_color': inscripcion.grupo.color_hex if inscripcion.grupo else '#000000',
                }
            )
            
            # Helper: obtener siguiente número libre para un color (rellena huecos)
            def siguiente_numero_libre(color_hex, inicio=None, color_nombre=None):
                if not color_hex:
                    return None

                # Obtener todos los números usados para ese color
                usados_qs = LogisticaKit.objects.filter(
                    pañoleta_color__iexact=color_hex,
                    polera_numero_id__isnull=False
                ).values_list('polera_numero_id', flat=True)
                usados = set(int(x) for x in usados_qs if x is not None)

                # Determinar punto de inicio
                if inicio is not None:
                    try:
                        candidato = int(inicio)
                    except Exception:
                        candidato = 1
                else:
                    # si el color tiene nombre "NARANJA" empezamos en 8
                    if color_nombre and str(color_nombre).upper() == 'NARANJA':
                        candidato = 8
                    else:
                        candidato = 1

                # Buscar el menor entero positivo disponible >= candidato
                while candidato in usados:
                    candidato += 1
                return candidato

            # Procesar polera (si se especifica)
            polera_talla = request.POST.get('polera_talla_1')
            polera_numero = request.POST.get('polera_numero_1')

            # Guardar número previo (asignado al inscribirse)
            numero_previo = kit.polera_numero_id

            if polera_talla:
                kit.polera_talla = polera_talla

            # Solo cambiar número si el usuario lo especifica explícitamente en el formulario
            if polera_numero:
                try:
                    nuevo_numero = int(polera_numero)
                    # Si es diferente al anterior, verificar conflicto
                    if nuevo_numero != numero_previo:
                        if LogisticaKit.objects.filter(polera_numero_id=nuevo_numero, pañoleta_color__iexact=(inscripcion.grupo.color_hex if inscripcion.grupo else None)).exclude(id=kit.id).exists():
                            messages.warning(request, f'El número {nuevo_numero} ya está asignado. Se mantiene el número {numero_previo}.')
                            # No cambiar el número, mantener el anterior
                        else:
                            kit.polera_numero_id = nuevo_numero
                except (ValueError, TypeError):
                    # Mantener número previo si hay error
                    pass
            # Si no hay número previo Y se va a entregar polera, asignar uno
            elif (not numero_previo) and polera_talla:
                color_grupo = inscripcion.grupo.color_hex if inscripcion.grupo else None
                color_nombre = inscripcion.grupo.color_nombre if inscripcion.grupo else None
                kit.polera_numero_id = siguiente_numero_libre(color_grupo, color_nombre=color_nombre)

            # Estado previo de entregas (para poder incrementar stock si se devuelve)
            prev_polera_entregada = bool(kit.polera_entregada)
            prev_panoleta_entregada = bool(kit.pañoleta_entregada)
            prev_credencial_entregada = bool(kit.credencial_entregada)
            prev_manilla_entregada = bool(kit.manilla_entregada)

            # Determinar color y nombre del grupo
            color_grupo = inscripcion.grupo.color_hex if inscripcion.grupo else None
            color_nombre = inscripcion.grupo.color_nombre if inscripcion.grupo else None

            # Determinar nuevos estados a partir del formulario
            new_polera_entregada = bool(polera_talla) or kit.polera_entregada
            new_panoleta_entregada = 'pañoleta_1' in request.POST
            new_credencial_entregada = 'credencial_1' in request.POST
            new_manilla_entregada = 'manilla_1' in request.POST

            kit.polera_entregada = new_polera_entregada
            kit.pañoleta_entregada = new_panoleta_entregada
            kit.credencial_entregada = new_credencial_entregada
            kit.manilla_entregada = new_manilla_entregada

            # Manejar transición de estados: si se pasa de False->True restar stock, si True->False sumar stock
            # Polera
            if not prev_polera_entregada and kit.polera_entregada:
                if color_grupo:
                    polera_inv = InventarioGlobal.objects.filter(
                        articulo='polera',
                        talla=polera_talla,
                        color_hex__iexact=color_grupo
                    ).first()
                    if polera_inv and polera_inv.stock_actual > 0:
                        polera_inv.stock_actual -= 1
                        polera_inv.save()
                        messages.info(request, f'✅ Polera {polera_talla} entregada')
            elif prev_polera_entregada and not kit.polera_entregada:
                # se devolvió la polera
                if color_grupo:
                    polera_inv = InventarioGlobal.objects.filter(
                        articulo='polera',
                        talla=polera_talla,
                        color_hex__iexact=color_grupo
                    ).first()
                    if polera_inv:
                        polera_inv.stock_actual += 1
                        polera_inv.save()
                        kit.polera_numero_id = None
                        messages.info(request, f'↩️ Polera {polera_talla} devuelta y stock actualizado')

            # Pañoleta
            if not prev_panoleta_entregada and kit.pañoleta_entregada:
                if color_grupo:
                    panoleta_inv = InventarioGlobal.objects.filter(
                        articulo='pañoleta',
                        color_hex__iexact=color_grupo
                    ).first()
                    if panoleta_inv and panoleta_inv.stock_actual > 0:
                        panoleta_inv.stock_actual -= 1
                        panoleta_inv.save()
                        messages.info(request, f'✅ Pañoleta entregada')
            elif prev_panoleta_entregada and not kit.pañoleta_entregada:
                if color_grupo:
                    panoleta_inv = InventarioGlobal.objects.filter(
                        articulo='pañoleta',
                        color_hex__iexact=color_grupo
                    ).first()
                    if panoleta_inv:
                        panoleta_inv.stock_actual += 1
                        panoleta_inv.save()
                        messages.info(request, f'↩️ Pañoleta devuelta y stock actualizado')

            # Credencial (global)
            if not prev_credencial_entregada and kit.credencial_entregada:
                credencial_inv = InventarioGlobal.objects.filter(articulo='credencial').first()
                if credencial_inv and credencial_inv.stock_actual > 0:
                    credencial_inv.stock_actual -= 1
                    credencial_inv.save()
                    messages.info(request, f'✅ Credencial entregada')
            elif prev_credencial_entregada and not kit.credencial_entregada:
                credencial_inv = InventarioGlobal.objects.filter(articulo='credencial').first()
                if credencial_inv:
                    credencial_inv.stock_actual += 1
                    credencial_inv.save()
                    messages.info(request, f'↩️ Credencial devuelta y stock actualizado')

            # Manilla
            if not prev_manilla_entregada and kit.manilla_entregada:
                if color_grupo:
                    manilla_inv = InventarioGlobal.objects.filter(
                        articulo='manilla',
                        color_hex__iexact=color_grupo
                    ).first()
                    if manilla_inv and manilla_inv.stock_actual > 0:
                        manilla_inv.stock_actual -= 1
                        manilla_inv.save()
                        messages.info(request, f'✅ Manilla entregada')
            elif prev_manilla_entregada and not kit.manilla_entregada:
                if color_grupo:
                    manilla_inv = InventarioGlobal.objects.filter(
                        articulo='manilla',
                        color_hex__iexact=color_grupo
                    ).first()
                    if manilla_inv:
                        manilla_inv.stock_actual += 1
                        manilla_inv.save()
                        messages.info(request, f'↩️ Manilla devuelta y stock actualizado')
            
            # Guardar cambios (intentar y manejar posibles colisiones)
            kit.fecha_entrega = timezone.now()
            kit.entregado_por = request.user
            try:
                with transaction.atomic():
                    kit.save()
            except IntegrityError:
                # intentar resolver conflicto recalculando número y reintentando
                if color_grupo and kit.polera_numero_id:
                    kit.polera_numero_id = siguiente_numero_libre(color_grupo, inicio=kit.polera_numero_id+1, color_nombre=color_nombre)
                with transaction.atomic():
                    kit.save()

            messages.success(request, f'✅ Kit actualizado para {inscripcion.nombre_persona}')
            # Si hay una segunda inscripción en el formulario, procesarla también
            inscripcion_id_2 = request.POST.get('inscripcion_id_2')
            if inscripcion_id_2:
                try:
                    insc2 = Inscripcion.objects.get(id=inscripcion_id_2)
                    kit2, created2 = LogisticaKit.objects.get_or_create(
                        inscripcion=insc2,
                        defaults={
                            'pañoleta_color': insc2.grupo.color_hex if insc2.grupo else '#000000',
                            'manilla_color': insc2.grupo.color_hex if insc2.grupo else '#000000',
                        }
                    )

                    polera_talla_2 = request.POST.get('polera_talla_2')
                    polera_numero_2 = request.POST.get('polera_numero_2')

                    # Guardar número previo (asignado al inscribirse)
                    numero_previo_2 = kit2.polera_numero_id

                    if polera_talla_2:
                        kit2.polera_talla = polera_talla_2

                    # Solo cambiar número si el usuario lo especifica explícitamente en el formulario
                    if polera_numero_2:
                        try:
                            nuevo_numero_2 = int(polera_numero_2)
                            # Si es diferente al anterior, verificar conflicto
                            if nuevo_numero_2 != numero_previo_2:
                                if LogisticaKit.objects.filter(polera_numero_id=nuevo_numero_2, pañoleta_color__iexact=(insc2.grupo.color_hex if insc2.grupo else None)).exclude(id=kit2.id).exists():
                                    messages.warning(request, f'El número {nuevo_numero_2} ya está asignado. Se mantiene el número {numero_previo_2}.')
                                    # No cambiar el número, mantener el anterior
                                else:
                                    kit2.polera_numero_id = nuevo_numero_2
                        except (ValueError, TypeError):
                            # Mantener número previo si hay error
                            pass
                    # Si no hay número previo Y se va a entregar polera, asignar uno
                    elif (not numero_previo_2) and polera_talla_2:
                        color_grupo2 = insc2.grupo.color_hex if insc2.grupo else None
                        color_nombre2 = insc2.grupo.color_nombre if insc2.grupo else None
                        kit2.polera_numero_id = siguiente_numero_libre(color_grupo2, color_nombre=color_nombre2)

                    color_grupo2 = insc2.grupo.color_hex if insc2.grupo else None
                    color_nombre2 = insc2.grupo.color_nombre if insc2.grupo else None

                    # Estado previo
                    prev_polera_entregada2 = bool(kit2.polera_entregada)
                    prev_panoleta_entregada2 = bool(kit2.pañoleta_entregada)
                    prev_credencial_entregada2 = bool(kit2.credencial_entregada)
                    prev_manilla_entregada2 = bool(kit2.manilla_entregada)

                    # Determinar nuevos estados a partir del formulario
                    new_polera_entregada2 = bool(polera_talla_2) or kit2.polera_entregada
                    new_panoleta_entregada2 = 'pañoleta_2' in request.POST
                    new_credencial_entregada2 = 'credencial_2' in request.POST
                    new_manilla_entregada2 = 'manilla_2' in request.POST

                    kit2.polera_entregada = new_polera_entregada2
                    kit2.pañoleta_entregada = new_panoleta_entregada2
                    kit2.credencial_entregada = new_credencial_entregada2
                    kit2.manilla_entregada = new_manilla_entregada2

                    # Polera
                    if not prev_polera_entregada2 and kit2.polera_entregada:
                        if color_grupo2:
                            polera_inv2 = InventarioGlobal.objects.filter(
                                articulo='polera',
                                talla=polera_talla_2,
                                color_hex__iexact=color_grupo2
                            ).first()
                            if polera_inv2 and polera_inv2.stock_actual > 0:
                                polera_inv2.stock_actual -= 1
                                polera_inv2.save()
                                messages.info(request, f'✅ Polera {polera_talla_2} entregada a {insc2.nombre_persona}')
                    elif prev_polera_entregada2 and not kit2.polera_entregada:
                        if color_grupo2:
                            polera_inv2 = InventarioGlobal.objects.filter(
                                articulo='polera',
                                talla=polera_talla_2,
                                color_hex__iexact=color_grupo2
                            ).first()
                            if polera_inv2:
                                polera_inv2.stock_actual += 1
                                polera_inv2.save()
                                kit2.polera_numero_id = None
                                messages.info(request, f'↩️ Polera {polera_talla_2} devuelta y stock actualizado')

                    # Pañoleta
                    if not prev_panoleta_entregada2 and kit2.pañoleta_entregada:
                        if color_grupo2:
                            pa2 = InventarioGlobal.objects.filter(
                                articulo='pañoleta',
                                color_hex__iexact=color_grupo2
                            ).first()
                            if pa2 and pa2.stock_actual > 0:
                                pa2.stock_actual -= 1
                                pa2.save()
                                messages.info(request, f'✅ Pañoleta entregada a {insc2.nombre_persona}')
                    elif prev_panoleta_entregada2 and not kit2.pañoleta_entregada:
                        if color_grupo2:
                            pa2 = InventarioGlobal.objects.filter(
                                articulo='pañoleta',
                                color_hex__iexact=color_grupo2
                            ).first()
                            if pa2:
                                pa2.stock_actual += 1
                                pa2.save()
                                messages.info(request, f'↩️ Pañoleta devuelta y stock actualizado para {insc2.nombre_persona}')

                    # Credencial (global)
                    if not prev_credencial_entregada2 and kit2.credencial_entregada:
                        cr2 = InventarioGlobal.objects.filter(articulo='credencial').first()
                        if cr2 and cr2.stock_actual > 0:
                            cr2.stock_actual -= 1
                            cr2.save()
                            messages.info(request, f'✅ Credencial entregada a {insc2.nombre_persona}')
                    elif prev_credencial_entregada2 and not kit2.credencial_entregada:
                        cr2 = InventarioGlobal.objects.filter(articulo='credencial').first()
                        if cr2:
                            cr2.stock_actual += 1
                            cr2.save()
                            messages.info(request, f'↩️ Credencial devuelta y stock actualizado para {insc2.nombre_persona}')

                    # Manilla
                    if not prev_manilla_entregada2 and kit2.manilla_entregada:
                        if color_grupo2:
                            m2 = InventarioGlobal.objects.filter(
                                articulo='manilla',
                                color_hex__iexact=color_grupo2
                            ).first()
                            if m2 and m2.stock_actual > 0:
                                m2.stock_actual -= 1
                                m2.save()
                                messages.info(request, f'✅ Manilla entregada a {insc2.nombre_persona}')
                    elif prev_manilla_entregada2 and not kit2.manilla_entregada:
                        if color_grupo2:
                            m2 = InventarioGlobal.objects.filter(
                                articulo='manilla',
                                color_hex__iexact=color_grupo2
                            ).first()
                            if m2:
                                m2.stock_actual += 1
                                m2.save()
                                messages.info(request, f'↩️ Manilla devuelta y stock actualizado para {insc2.nombre_persona}')

                    # Guardar kit2 con manejo de IntegrityError
                    kit2.fecha_entrega = timezone.now()
                    kit2.entregado_por = request.user
                    try:
                        with transaction.atomic():
                            kit2.save()
                    except IntegrityError:
                        if color_grupo2 and kit2.polera_numero_id:
                            kit2.polera_numero_id = siguiente_numero_libre(color_grupo2, inicio=kit2.polera_numero_id+1, color_nombre=color_nombre2)
                        with transaction.atomic():
                            kit2.save()
                except Inscripcion.DoesNotExist:
                    messages.error(request, 'La segunda inscripción no existe')

            return redirect(f'{reverse("lista_inscritos")}?last={inscripcion_id}')
        
        # ============ FORMULARIO DE INSCRIPCIÓN (SIMPLE O DOBLE) ============
        else:
            form = InscripcionUnificadoForm(request.POST)
            
            if form.is_valid():
                tipo_inscripcion = form.cleaned_data['inscripcion_tipo']
                
                if tipo_inscripcion == 'simple':
                    return procesar_inscripcion_simple(request, form)
                else:
                    return procesar_inscripcion_doble_completa(request, form)
            else:
                for field, errors in form.errors.items():
                    for error in errors:
                        messages.error(request, f'{field}: {error}')
    
    # ============ PROCESAR SOLICITUD GET ============
    else:
        form = InscripcionUnificadoForm()
    
    # ============ OBTENER DATOS PARA EL TEMPLATE ============
    
    # 1. Obtener credenciales de la sesión (si existen) para mostrar en modal
    credenciales_nuevo_usuario = request.session.pop('credenciales_nuevo_usuario', None)
    
    # 2. Obtener todas las inscripciones
    inscritos = Inscripcion.objects.all().select_related(
        'user', 'grupo', 'iglesia', 'union'
    ).prefetch_related('logisticakit').order_by('-id')
    
    # 2. Estadísticas de inventario
    poleras_stock = InventarioGlobal.objects.filter(articulo='polera')
    total_poleras = sum(p.stock_actual for p in poleras_stock) if poleras_stock else 0
    
    tallas_disponibles = poleras_stock.filter(
        stock_actual__gt=0
    ).values_list('talla', flat=True).distinct()
    
    # 3. Última inscripción (si viene por GET)
    last_id = request.GET.get('last')
    companion_id = request.GET.get('companion')
    last = None
    es_inscripcion_doble = False
    last2 = None
    poleras_asignadas_color = []
    proximo_numero_polera = 0
    
    if last_id:
        last = Inscripcion.objects.filter(id=last_id).select_related(
            'grupo', 'user', 'iglesia', 'union'
        ).first()
        
        if last:
            # Si hay un companion_id, es una inscripción doble
            if companion_id:
                try:
                    last2 = Inscripcion.objects.filter(id=companion_id).select_related(
                        'grupo', 'user', 'iglesia', 'union'
                    ).first()
                    if last2:
                        es_inscripcion_doble = True
                except Exception:
                    es_inscripcion_doble = False
                    last2 = None
            
            # Calcular poleras asignadas para este color
            color_grupo = last.grupo.color_hex if last.grupo else None
            color_nombre = last.grupo.color_nombre if last.grupo else None
            
            if color_grupo:
                poleras_asignadas_color = LogisticaKit.objects.filter(
                    pañoleta_color__iexact=color_grupo,
                    polera_numero_id__isnull=False
                ).select_related('inscripcion').order_by('polera_numero_id')

                # Determinar el menor número disponible (rellenar huecos), respetando inicio para NARANJA
                usados_qs = poleras_asignadas_color.values_list('polera_numero_id', flat=True)
                usados = set(int(x) for x in usados_qs if x is not None)
                if color_nombre and color_nombre.upper() == 'NARANJA':
                    candidato = 8
                else:
                    candidato = 1
                while candidato in usados:
                    candidato += 1
                proximo_numero_polera = candidato
    
    # Si no hay last, calcular el próximo número general
    if not last or not last.grupo:
        ultimo_numero = LogisticaKit.objects.aggregate(Max('polera_numero_id'))['polera_numero_id__max']
        proximo_numero_polera = (ultimo_numero or 0) + 1
    
    # 4. Preparar datos de poleras asignadas para la plantilla
    poleras_asignadas_para_template = []
    for kit in poleras_asignadas_color:
        poleras_asignadas_para_template.append({
            'numero': kit.polera_numero_id,
            'talla': kit.polera_talla,
            'nombre': kit.inscripcion.nombre_persona if kit.inscripcion else '',
            'iglesia': kit.inscripcion.iglesia.nombre if kit.inscripcion and kit.inscripcion.iglesia else ''
        })
    
    # 5. Calcular estadísticas de kits
    total_inscritos = inscritos.count()
    
    # Contar kits por estado
    kits_completos = 0
    kits_parciales = 0
    kits_pendientes = 0
    
    for inscrito in inscritos:
        kit = getattr(inscrito, 'logisticakit', None)
        if kit:
            if kit.polera_entregada and kit.pañoleta_entregada and kit.credencial_entregada and kit.manilla_entregada:
                kits_completos += 1
            elif kit.polera_entregada or kit.pañoleta_entregada or kit.credencial_entregada or kit.manilla_entregada:
                kits_parciales += 1
        else:
            kits_pendientes += 1
    
    # 6. Estadísticas por grupo
    grupos_con_estadisticas = []
    for grupo in Grupo.objects.all():
        miembros_grupo = inscritos.filter(grupo=grupo)
        total_grupo = miembros_grupo.count()
        
        # Contar kits por grupo
        kits_grupo = LogisticaKit.objects.filter(inscripcion__grupo=grupo)
        completos_grupo = kits_grupo.filter(
            polera_entregada=True,
            pañoleta_entregada=True,
            credencial_entregada=True,
            manilla_entregada=True
        ).count()
        
        parciales_grupo = kits_grupo.exclude(
            polera_entregada=False,
            pañoleta_entregada=False,
            credencial_entregada=False,
            manilla_entregada=False
        ).exclude(
            polera_entregada=True,
            pañoleta_entregada=True,
            credencial_entregada=True,
            manilla_entregada=True
        ).count()
        
        pendientes_grupo = total_grupo - kits_grupo.count()
        
        grupos_con_estadisticas.append({
            'id': grupo.id,
            'nombre': grupo.nombre,
            'color_hex': grupo.color_hex,
            'color_nombre': grupo.color_nombre,
            'total_inscritos': total_grupo,
            'kits_completos': completos_grupo,
            'kits_parciales': parciales_grupo,
            'kits_pendientes': pendientes_grupo
        })
    
    # 7. Obtener inventario para la sección de entrega
    if last and last.grupo:
        color_grupo = last.grupo.color_hex
        pañoletas_disponibles = InventarioGlobal.objects.filter(
            articulo='pañoleta',
            color_hex__iexact=color_grupo,
            stock_actual__gt=0
        ).first()
        
        credenciales_disponibles = InventarioGlobal.objects.filter(
            articulo='credencial',
            stock_actual__gt=0
        ).first()
        
        manillas_disponibles = InventarioGlobal.objects.filter(
            articulo='manilla',
            color_hex__iexact=color_grupo,
            stock_actual__gt=0
        ).first()
    else:
        pañoletas_disponibles = None
        credenciales_disponibles = None
        manillas_disponibles = None
    
    # 8. Obtener kit si existe
    kit = None
    kit2 = None
    if last:
        kit = getattr(last, 'logisticakit', None)
        if last2:
            kit2 = getattr(last2, 'logisticakit', None)
        
        # Calcular precio_final y saldo
        try:
            # Envolver la operación completa en una transacción para evitar condiciones de carrera
            with transaction.atomic():
                precio_base = last.costo_total or Decimal('0')
                descuento = last.descuento or Decimal('0')
                precio_final = (precio_base * (Decimal('1') - (descuento / Decimal('100')))).quantize(Decimal('0.01'))
                paga = last.paga or Decimal('0')
                saldo = max(Decimal('0'), precio_final - paga)
        except Exception:
            precio_final = Decimal('0')
            saldo = Decimal('0')
    else:
        precio_final = Decimal('0')
        saldo = Decimal('0')
    
    # preparar número siguiente para persona 2 si aplica
    proximo_numero_polera_2 = None
    try:
        if last2:
            proximo_numero_polera_2 = (proximo_numero_polera or 0) + 1
    except Exception:
        proximo_numero_polera_2 = None

    # ============ PREPARAR CONTEXTO FINAL ============
    contexto = {
        # Formularios
        'form': form,
        
        # Credenciales de nuevo usuario (modal)
        'credenciales_nuevo_usuario': credenciales_nuevo_usuario,
        
        # Lista de inscritos
        'lista_inscritos': inscritos,
        
        # Última inscripción procesada
        'last': last,
        'last2': last2,
        'es_inscripcion_doble': es_inscripcion_doble,
        
        # Información de kit
        'kit': kit,
        'precio_final': precio_final,
        'saldo': saldo,
        
        # Inventario de poleras
        'total_poleras': total_poleras,
        'tallas_disponibles': tallas_disponibles,
        'proximo_numero_polera': proximo_numero_polera,
        'proximo_numero_polera_2': proximo_numero_polera_2,
        'kit2': kit2,
        'poleras_stock': poleras_stock,
        'poleras_asignadas_color': poleras_asignadas_para_template,
        
        # Inventario para entrega de kit
        'pañoletas_disponibles': pañoletas_disponibles,
        'credenciales_disponibles': credenciales_disponibles,
        'manillas_disponibles': manillas_disponibles,
        
        # Estadísticas
        'total_inscritos': total_inscritos,
        'kits_completos': kits_completos,
        'kits_parciales': kits_parciales,
        'kits_pendientes': kits_pendientes,
        'grupos_con_estadisticas': grupos_con_estadisticas,
        
        # Datos generales
        'grupos': Grupo.objects.all().order_by('nombre'),
        'iglesias': Iglesia.objects.all().order_by('nombre'),
        'uniones': Union.objects.all().order_by('nombre'),
    }
    
    return render(request, 'principal/lista_inscritos.html', contexto)


@require_role('inscripcion', 'admin')
def editar_inscripcion(request, insc_id):
    """Editar datos de una inscripción existente"""
    insc = get_object_or_404(Inscripcion, id=insc_id)
    if request.method == 'POST':
        form = InscripcionForm(request.POST, instance=insc)
        if form.is_valid():
            form.save()
            messages.success(request, f'Inscripción {insc.nombre_persona} actualizada correctamente.')
            return redirect('lista_inscritos')
    else:
        form = InscripcionForm(instance=insc)

    return render(request, 'principal/inscripcion_editar.html', {'form': form, 'insc': insc})


@require_role('inscripcion', 'admin')
def eliminar_inscripcion(request, insc_id):
    """Eliminar una inscripción con manejo cuidadoso de kits/números asignados.
    El número asignado se devuelve al pool disponible sin ser eliminado definitivamente.
    """
    insc = get_object_or_404(Inscripcion, id=insc_id)
    # intentar obtener el kit asociado
    kit = None
    try:
        kit = insc.logisticakit
    except Exception:
        kit = None

    if request.method == 'POST':
        action = request.POST.get('action', 'return')

        # Si se fuerza devolución al inventario
        if action == 'force' and kit and kit.polera_numero_id:
            try:
                inv = InventarioGlobal.objects.get(
                    articulo='polera',
                    talla=kit.polera_talla,
                    color_hex__iexact=(insc.grupo.color_hex if insc.grupo else '')
                )
                # Incrementar stock para que el número sea reutilizable
                inv.stock_actual = (inv.stock_actual or 0) + 1
                # No quitar el número de numeros_asignados; solo incrementamos stock
                # para que el número sea reutilizable en futuras inscripciones
                inv.save()
                messages.success(request, f'Inventario: polera #{kit.polera_numero_id} devuelta al stock (número reutilizable).')
            except InventarioGlobal.DoesNotExist:
                messages.warning(request, 'No se encontró inventario para devolver la polera; se eliminará la inscripción sin ajustar stock.')

        nombre = insc.nombre_persona
        insc.delete()
        messages.success(request, f'Inscripción {nombre} eliminada correctamente.')
        return redirect('lista_inscritos')

    return render(request, 'principal/inscripcion_eliminar.html', {'insc': insc, 'kit': kit})


# ============ FUNCIONES AUXILIARES PARA INSCRIPCIONES ============

def crear_usuario_automatico(nombre_completo):
    """Crea un usuario Django automáticamente con username 'vida' + número"""
    
    # Generar username en formato "vida" + número
    numero = 1
    username = f"vida{numero}"
    
    # Encontrar el próximo número disponible
    while Usuario.objects.filter(username=username).exists():
        numero += 1
        username = f"vida{numero}"
    
    password = f"vida{numero}"
    user = Usuario.objects.create_user(username=username, password=password)
    
    if ' ' in nombre_completo:
        user.first_name = nombre_completo.split()[0]
    user.save()
    
    # Devolver usuario, contraseña y nombre completo
    return {
        'user': user,
        'username': username,
        'password': password,
        'nombre': nombre_completo
    }

def procesar_inscripcion_simple(request, form):
    """Procesa una inscripción simple"""
    datos = form.cleaned_data
    
    try:
        # Convertir bautizado de string a booleano
        bautizado_value = datos.get('bautizado', 'false')
        bautizado = bautizado_value in ('true', True)
        
        # Crear usuario (devuelve dict con usuario, username y password)
        usuario_data = crear_usuario_automatico(datos['nombre_persona'])
        user = usuario_data['user']
        username = usuario_data['username']
        password = usuario_data['password']
        
        # Asignar grupo
        grupo = asignar_grupo_automatico(
            int(datos['edad']),
            datos['sexo'],
            datos.get('union')
        )
        
        # Asignar polera
        polera_info = asignar_polera_automatica(
            grupo.color_hex if grupo else None,
            datos.get('talla_polera')
        )
        
        # Calcular precios
        precio_base = datos['costo_total'] or Decimal('0')
        descuento = datos['descuento'] or Decimal('0')
        paga = datos['paga'] or Decimal('0')
        precio_final = (precio_base * (Decimal('1') - (descuento / Decimal('100')))).quantize(Decimal('0.01'))
        cambio = (paga - precio_final).quantize(Decimal('0.01'))
        
        # Crear inscripción CON LOS CAMPOS CORRECTOS
        inscripcion = Inscripcion.objects.create(
            user=user,
            nombre_persona=datos['nombre_persona'],
            iglesia=datos['iglesia'],
            union=datos['union'],
            sexo=datos['sexo'],
            edad=datos['edad'],
            grupo=grupo,
            costo_total=precio_base,
            descuento=descuento,
            paga=paga,
            cambio=cambio,
            monto_pagado=precio_final,  # ✅ Este campo SÍ existe
            registrado_por=request.user,
            bautizado=bautizado
        )
        
        # Crear kit
        LogisticaKit.objects.create(
            inscripcion=inscripcion,
            polera_numero_id=polera_info['numero'],
            polera_talla=polera_info['talla'],
            polera_entregada=False,
            pañoleta_color=grupo.color_hex if grupo else polera_info['color_hex'],
            manilla_color=grupo.color_hex if grupo else polera_info['color_hex'],
            pañoleta_entregada=False,
            credencial_entregada=False,
            manilla_entregada=False
        )
        
        # Guardar credenciales en la sesión para mostrar en modal
        request.session['credenciales_nuevo_usuario'] = {
            'nombre': datos['nombre_persona'],
            'username': username,
            'password': password
        }
        
        # Mensaje de éxito
        mensaje = f'✅ <strong>{datos["nombre_persona"]}</strong> registrado(a) exitosamente.<br>'
        if polera_info['numero'] > 0:
            mensaje += f'👕 <strong>Polera asignada:</strong> #{polera_info["numero"]} (Talla: {polera_info["talla"]})<br>'
        
        if grupo:
            mensaje += f'🎯 <strong>Equipo:</strong> {grupo.nombre} ({grupo.color_nombre})<br>'
            mensaje += f'🎨 <strong>Color:</strong> {grupo.color_hex}'
        
        if polera_info.get('sin_stock'):
            mensaje += '<br>⚠️ <strong>Atención:</strong> Número asignado sin stock físico disponible'
        
        messages.success(request, mensaje)
        return redirect(f"/inscripcion/lista/?last={inscripcion.id}")
        
    except Exception as e:
        messages.error(request, f'❌ Error al procesar inscripción: {str(e)}')
        import traceback
        print(traceback.format_exc())
        return redirect('lista_inscritos')

def procesar_inscripcion_doble_completa(request, form):
    """Procesa una inscripción doble"""
    datos = form.cleaned_data
    
    try:
        # Extraer datos de persona 1
        nombre_p1 = datos['nombre_persona']
        datos_p1 = {
            'nombre_persona': nombre_p1,
            'iglesia': datos['iglesia'],
            'union': datos['union'],
            'edad': datos['edad'],
            'sexo': datos['sexo'],
            'bautizado': datos.get('bautizado') in ('true', True),
            'costo_total': datos['costo_total'],
            'descuento': datos['descuento'],
            'paga': datos['paga'],
            'talla_polera': datos.get('talla_polera')
        }
        
        # Extraer datos de persona 2
        nombre_p2 = datos['nombre_persona_2']
        datos_p2 = {
            'nombre_persona': nombre_p2,
            'iglesia': datos['iglesia_2'],
            'union': datos['union_2'],
            'edad': datos['edad_2'],
            'sexo': datos['sexo_2'],
            'bautizado': datos.get('bautizado_2') in ('true', True),
            'costo_total': datos['costo_total_2'],
            'descuento': datos['descuento_2'],
            'paga': datos['paga_2'],
            'talla_polera': datos.get('talla_polera_2')
        }
        
        # Validar datos obligatorios
        if not nombre_p1 or not nombre_p2:
            messages.error(request, '❌ Ambas personas deben tener nombre completo')
            return redirect('lista_inscritos')
        
        # Asignar grupo (mismo para ambos)
        grupo = asignar_grupo_automatico(
            int(datos['edad']),
            datos['sexo'],
            datos.get('union')
        )
        
        # Asignar poleras correlativas
        polera_info_p1 = asignar_polera_automatica_con_numero(
            grupo.color_hex if grupo else None,
            datos.get('talla_polera')
        )
        
        polera_info_p2 = asignar_polera_automatica_con_numero(
            grupo.color_hex if grupo else None,
            datos.get('talla_polera_2'),
            polera_info_p1['numero'] + 1  # Número siguiente
        )
        
        # Procesar persona 1
        usuario_data_p1 = crear_usuario_automatico(nombre_p1)
        user_p1 = usuario_data_p1['user']
        inscripcion_p1 = crear_inscripcion_completa(user_p1, datos_p1, grupo, polera_info_p1, registrado_por=request.user)
        
        # Procesar persona 2
        usuario_data_p2 = crear_usuario_automatico(nombre_p2)
        user_p2 = usuario_data_p2['user']
        inscripcion_p2 = crear_inscripcion_completa(user_p2, datos_p2, grupo, polera_info_p2, registrado_por=request.user)
        
        # Guardar credenciales de ambas personas en la sesión (mostrar primero p1)
        request.session['credenciales_nuevo_usuario'] = {
            'nombre': nombre_p1,
            'username': usuario_data_p1['username'],
            'password': usuario_data_p1['password'],
            'es_doble': True,
            'nombre_p2': nombre_p2,
            'username_p2': usuario_data_p2['username'],
            'password_p2': usuario_data_p2['password']
        }
        
        # Mensaje de éxito
        mensaje = f'✅ <strong>Inscripción Doble Exitosa</strong><br><br>'
        mensaje += f'👤 <strong>Persona 1:</strong> {nombre_p1}<br>'
        if polera_info_p1['numero'] > 0:
            mensaje += f'&nbsp;&nbsp;&nbsp;👕 Polera #{polera_info_p1["numero"]} (Talla: {polera_info_p1["talla"]})<br><br>'
        mensaje += f'👤 <strong>Persona 2:</strong> {nombre_p2}<br>'
        if polera_info_p2['numero'] > 0:
            mensaje += f'&nbsp;&nbsp;&nbsp;👕 Polera #{polera_info_p2["numero"]} (Talla: {polera_info_p2["talla"]})<br><br>'
        
        if grupo:
            mensaje += f'🎯 <strong>Equipo (ambos):</strong> {grupo.nombre}<br>'
            mensaje += f'🎨 <strong>Color:</strong> {grupo.color_nombre or grupo.color_hex}'
        
        messages.success(request, mensaje)
        return redirect(f"/inscripcion/lista/?last={inscripcion_p2.id}&companion={inscripcion_p1.id}")
        
    except Exception as e:
        messages.error(request, f'❌ Error al procesar inscripción doble: {str(e)}')
        import traceback
        print(traceback.format_exc())
        return redirect('lista_inscritos')

def crear_inscripcion_completa(user, datos, grupo, polera_info, registrado_por=None):
    """Crea una inscripción completa"""
    # Calcular precios
    precio_base = datos['costo_total'] or Decimal('0')
    descuento = datos['descuento'] or Decimal('0')
    paga = datos['paga'] or Decimal('0')
    precio_final = (precio_base * (Decimal('1') - (descuento / Decimal('100')))).quantize(Decimal('0.01'))
    cambio = (paga - precio_final).quantize(Decimal('0.01'))
    
    # Crear inscripción SOLO con los campos que EXISTEN en tu modelo
    inscripcion = Inscripcion.objects.create(
        user=user,
        nombre_persona=datos['nombre_persona'],
        iglesia=datos['iglesia'],
        union=datos['union'],
        sexo=datos['sexo'],
        edad=datos['edad'],
        grupo=grupo,
        costo_total=precio_base,
        descuento=descuento,
        paga=paga,
        cambio=cambio,
        monto_pagado=precio_final,  # ✅ Este campo SÍ existe en tu modelo
        registrado_por=registrado_por,
        bautizado=datos.get('bautizado', False)
    )
    
    # Crear kit
    LogisticaKit.objects.create(
        inscripcion=inscripcion,
        polera_numero_id=polera_info['numero'],
        polera_talla=polera_info['talla'],
        polera_entregada=False,
        pañoleta_color=grupo.color_hex if grupo else polera_info['color_hex'],
        manilla_color=grupo.color_hex if grupo else polera_info['color_hex'],
        pañoleta_entregada=False,
        credencial_entregada=False,
        manilla_entregada=False
    )
    
    return inscripcion

def asignar_polera_automatica(grupo_color_hex=None, talla_preferida=None):
    """Asigna automáticamente una polera considerando el color del grupo"""
    try:
        if not grupo_color_hex:
            inventario_disponible = InventarioGlobal.objects.filter(
                articulo='polera',
                stock_actual__gt=0
            ).first()
            
            if not inventario_disponible:
                return {
                    'numero': 0,
                    'talla': talla_preferida or 'M',
                    'color_hex': '#000000',
                    'sin_stock': True,
                    'mensaje': 'No hay stock de poleras disponible'
                }
            
            grupo_color_hex = inventario_disponible.color_hex
        
        query = InventarioGlobal.objects.filter(
            articulo='polera',
            color_hex__iexact=grupo_color_hex,
            stock_actual__gt=0
        )
        
        if talla_preferida:
            query = query.filter(talla=talla_preferida)
        
        if not query.exists() and talla_preferida:
            query = InventarioGlobal.objects.filter(
                articulo='polera',
                color_hex__iexact=grupo_color_hex,
                stock_actual__gt=0
            )
        
        inventario_disponible = query.first()
        
        if not inventario_disponible:
            inventario_disponible = InventarioGlobal.objects.filter(
                articulo='polera',
                stock_actual__gt=0
            ).first()
            
            if not inventario_disponible:
                return {
                    'numero': 0,
                    'talla': talla_preferida or 'M',
                    'color_hex': grupo_color_hex or '#000000',
                    'sin_stock': True,
                    'mensaje': 'No hay stock de poleras disponible'
                }
        
        ultimo_numero_color = LogisticaKit.objects.filter(
            pañoleta_color__iexact=inventario_disponible.color_hex
        ).aggregate(Max('polera_numero_id'))['polera_numero_id__max']
        
        proximo_numero = (ultimo_numero_color or 0) + 1
        
        while LogisticaKit.objects.filter(
            polera_numero_id=proximo_numero,
            pañoleta_color__iexact=inventario_disponible.color_hex
        ).exists():
            proximo_numero += 1
        
        # Reducir stock si hay disponible
        inventario_disponible.stock_actual -= 1
        inventario_disponible.save()
        
        return {
            'numero': proximo_numero,
            'talla': inventario_disponible.talla,
            'color_hex': inventario_disponible.color_hex,
            'color_nombre': inventario_disponible.color_nombre,
            'sin_stock': False,
            'mensaje': f'Polera asignada: #{proximo_numero} ({inventario_disponible.color_nombre})'
        }
        
    except Exception as e:
        return {
            'numero': 0,
            'talla': talla_preferida or 'M',
            'color_hex': grupo_color_hex or '#000000',
            'sin_stock': True,
            'mensaje': f'Error al asignar polera: {str(e)}'
        }

def asignar_polera_automatica_con_numero(grupo_color_hex=None, talla_preferida=None, numero_forzado=None):
    """Versión modificada que acepta número forzado para inscripciones correlativas"""
    try:
        # Si se especifica número forzado (inscripción doble)
        if numero_forzado:
            numero = numero_forzado
        else:
            ultimo_numero_color = LogisticaKit.objects.filter(
                pañoleta_color__iexact=grupo_color_hex
            ).aggregate(Max('polera_numero_id'))['polera_numero_id__max']
            
            numero = (ultimo_numero_color or 0) + 1
            
            while LogisticaKit.objects.filter(
                polera_numero_id=numero,
                pañoleta_color__iexact=grupo_color_hex
            ).exists():
                numero += 1
        
        # Buscar polera en inventario
        if not grupo_color_hex:
            inventario_disponible = InventarioGlobal.objects.filter(
                articulo='polera',
                stock_actual__gt=0
            ).first()
            
            if not inventario_disponible:
                return {
                    'numero': numero,
                    'talla': talla_preferida or 'M',
                    'color_hex': '#000000',
                    'sin_stock': True
                }
            
            grupo_color_hex = inventario_disponible.color_hex
        
        query = InventarioGlobal.objects.filter(
            articulo='polera',
            color_hex__iexact=grupo_color_hex,
            stock_actual__gt=0
        )
        
        if talla_preferida:
            query = query.filter(talla=talla_preferida)
        
        if not query.exists() and talla_preferida:
            query = InventarioGlobal.objects.filter(
                articulo='polera',
                color_hex__iexact=grupo_color_hex,
                stock_actual__gt=0
            )
        
        inventario_disponible = query.first()
        
        if not inventario_disponible:
            inventario_disponible = InventarioGlobal.objects.filter(
                articulo='polera',
                stock_actual__gt=0
            ).first()
            
            if not inventario_disponible:
                return {
                    'numero': numero,
                    'talla': talla_preferida or 'M',
                    'color_hex': grupo_color_hex or '#000000',
                    'sin_stock': True
                }
        
        # Reducir stock
        inventario_disponible.stock_actual -= 1
        inventario_disponible.save()
        
        return {
            'numero': numero,
            'talla': inventario_disponible.talla,
            'color_hex': inventario_disponible.color_hex,
            'color_nombre': inventario_disponible.color_nombre,
            'sin_stock': False
        }
        
    except Exception as e:
        return {
            'numero': numero if 'numero' in locals() else 0,
            'talla': talla_preferida or 'M',
            'color_hex': grupo_color_hex or '#000000',
            'sin_stock': True
        }

# ============ FUNCIONES API/AJAX ============
from django.http import JsonResponse
from .models import Inscripcion

def ultima_inscripcion_ajax(request):
    """API para obtener la última inscripción en tiempo real con soporte para 2 personas"""
    try:
        # Traemos la última inscripción
        last = Inscripcion.objects.select_related('grupo', 'iglesia').latest('id')
        
        # Juntamos los nombres si existe la segunda persona
        nombre_display = last.nombre_persona
        # Verifica si el campo nombre_persona2 tiene contenido
        if hasattr(last, 'nombre_persona2') and last.nombre_persona2:
            nombre_display = f"{last.nombre_persona} y {last.nombre_persona2}"
        
        data = {
            'id': last.id,
            'nombre': nombre_display, # <--- Aquí viajan ambos nombres
            'equipo': last.grupo.nombre if last.grupo else 'Sin equipo',
            'color': last.grupo.color_hex if last.grupo else '#10B981',
            'iglesia': last.iglesia.nombre if last.iglesia else 'General',
        }
        return JsonResponse(data)
    except Inscripcion.DoesNotExist:
        return JsonResponse({'error': 'No hay inscripciones'}, status=404)
    
@require_GET
def api_colores_existentes(request):
    """API para obtener colores existentes por artículo y talla"""
    articulo = request.GET.get('articulo')
    talla = request.GET.get('talla')
    
    if not articulo or not talla:
        return JsonResponse({
            'success': False,
            'error': 'Faltan parámetros: articulo y talla son requeridos'
        }, status=400)
    
    try:
        articulos_validos = [choice[0] for choice in InventarioGlobal.ARTICULOS]
        if articulo not in articulos_validos:
            return JsonResponse({
                'success': False,
                'error': f'Artículo inválido. Opciones válidas: {", ".join(articulos_validos)}'
            }, status=400)
        
        colores = InventarioGlobal.objects.filter(
            articulo=articulo,
            talla=talla
        ).exclude(
            color_hex__isnull=True
        ).exclude(
            color_hex=''
        ).order_by('color_nombre', 'color_hex')
        
        colores_unicos = []
        colores_vistos = set()
        
        for item in colores:
            key = (item.color_hex, item.color_nombre or '')
            if key not in colores_vistos:
                colores_vistos.add(key)
                colores_unicos.append({
                    'id': item.id,
                    'hex': item.color_hex,
                    'nombre': item.color_nombre or item.color_hex,
                    'stock_actual': item.stock_actual,
                    'texto': f"{item.color_nombre or item.color_hex} ({item.color_hex}) - Stock: {item.stock_actual}"
                })
        
        return JsonResponse({
            'success': True,
            'colores': colores_unicos,
            'count': len(colores_unicos),
            'articulo': articulo,
            'talla': talla,
            'articulo_display': dict(InventarioGlobal.ARTICULOS).get(articulo, articulo)
        })
        
    except Exception as e:
        import traceback
        return JsonResponse({
            'success': False,
            'error': str(e),
            'traceback': traceback.format_exc()
        }, status=500)

def tallas_disponibles_api(request):
    """API para obtener tallas disponibles de poleras"""
    try:
        tallas = InventarioGlobal.objects.filter(
            articulo='polera',
            stock_actual__gt=0
        ).values('talla').distinct()
        
        tallas_list = [item['talla'] for item in tallas if item['talla']]
        
        return JsonResponse({
            'success': True,
            'tallas': tallas_list,
            'count': len(tallas_list)
        })
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e),
            'tallas': []
        })

# ============ VISTAS DE KITS E INVENTARIO ============
def entregar_kit(request, insc_id):
    """Vista para entregar kit con control de inventario POR COLOR"""
    from django.utils import timezone
    
    insc = get_object_or_404(Inscripcion, id=insc_id)
    kit = getattr(insc, 'logisticakit', None)
    
    if not kit:
        messages.error(request, 'No se encontró kit para esta inscripción.')
        return redirect('lista_inscritos')
    
    color_grupo = insc.grupo.color_hex if insc.grupo else None
    color_nombre = insc.grupo.color_nombre if insc.grupo else None
    
    # ========== CALCULAR PRÓXIMO NÚMERO PARA ESTE COLOR ==========
    proximo_numero = 0
    poleras_asignadas_color = []
    
    if color_grupo:
        # Buscar poleras ya asignadas de este color
        poleras_asignadas_color = LogisticaKit.objects.filter(
            pañoleta_color__iexact=color_grupo,
            polera_numero_id__isnull=False
        ).exclude(id=kit.id).order_by('polera_numero_id')
        
        # Contar poleras asignadas
        conteo_poleras_color = poleras_asignadas_color.count()
        
        # Ajustar para Naranja
        if color_nombre and color_nombre.upper() == "NARANJA":
            proximo_numero = 8 + conteo_poleras_color
        else:
            proximo_numero = conteo_poleras_color
        
        # Verificar que el número no esté usado
        while LogisticaKit.objects.filter(
            polera_numero_id=proximo_numero,
            pañoleta_color__iexact=color_grupo
        ).exclude(id=kit.id).exists():
            proximo_numero += 1
    
    if request.method == 'POST':
        polera_talla = request.POST.get('polera_talla')
        polera_num = request.POST.get('polera_numero_id')
        pañoleta = request.POST.get('pañoleta_entregada') == 'on'
        credencial = request.POST.get('credencial_entregada') == 'on'
        manilla = request.POST.get('manilla_entregada') == 'on'

        # ========== VALIDAR QUE AL MENOS UN ELEMENTO SEA MARCADO ==========
        elementos_entregados = []
        elementos_nuevos = 0
        
        # Verificar si hay elementos nuevos por entregar
        if polera_talla and not kit.polera_entregada:
            elementos_nuevos += 1
        if pañoleta and not kit.pañoleta_entregada:
            elementos_nuevos += 1
        if credencial and not kit.credencial_entregada:
            elementos_nuevos += 1
        if manilla and not kit.manilla_entregada:
            elementos_nuevos += 1
        
        # Si no hay elementos nuevos para entregar, mostrar error
        if elementos_nuevos == 0:
            messages.error(request, '⚠️ Por favor, marca al menos un elemento del kit como entregado.')
            return redirect('entregar_kit', insc_id=insc_id)
        
        # ========== PROCESAR LA POLERA ==========
        if polera_talla:
            kit.polera_talla = polera_talla
        
        if polera_num:
            try:
                requested = int(polera_num)
                conflict = LogisticaKit.objects.filter(
                    polera_numero_id=requested,
                    pañoleta_color__iexact=color_grupo
                ).exclude(id=kit.id).first()
                
                if conflict:
                    # Encontrar próximo número disponible
                    candidate = proximo_numero
                    while LogisticaKit.objects.filter(
                        polera_numero_id=candidate,
                        pañoleta_color__iexact=color_grupo
                    ).exclude(id=kit.id).exists():
                        candidate += 1
                    
                    kit.polera_numero_id = candidate
                    messages.warning(request, f'Número {requested} ya asignado en color {color_nombre or color_grupo}; se usó {candidate}.')
                else:
                    kit.polera_numero_id = requested
            except ValueError:
                # Si no se especifica número, usar el calculado
                kit.polera_numero_id = proximo_numero
        else:
            # Asignar número calculado automáticamente
            kit.polera_numero_id = proximo_numero
        
        delivered = []
        errors = []
        
        # ========== ENTREGAR POLERA ==========
        if polera_talla and not kit.polera_entregada:
            polera_inv = InventarioGlobal.objects.filter(
                articulo='polera',
                talla=polera_talla,
                color_hex__iexact=color_grupo,
                stock_actual__gt=0
            ).first()
            
            if polera_inv:
                kit.polera_entregada = True
                delivered.append('polera')
                polera_inv.stock_actual -= 1
                polera_inv.save()
                messages.info(request, f'✅ Polera {color_nombre or color_grupo} talla {polera_talla} entregada.')
            else:
                errors.append(f'❌ No hay stock de polera {color_nombre or color_grupo} talla {polera_talla}.')
        
        # ========== ENTREGAR PAÑOLETA ==========
        if pañoleta and not kit.pañoleta_entregada:
            pañoleta_inv = InventarioGlobal.objects.filter(
                articulo='pañoleta',
                talla='unica',
                color_hex__iexact=color_grupo,
                stock_actual__gt=0
            ).first()
            
            if pañoleta_inv:
                kit.pañoleta_entregada = True
                kit.pañoleta_color = color_grupo
                delivered.append('pañoleta')
                pañoleta_inv.stock_actual -= 1
                pañoleta_inv.save()
                messages.info(request, f'✅ Pañoleta {color_nombre or color_grupo} entregada.')
            else:
                errors.append(f'❌ No hay stock de pañoleta {color_nombre or color_grupo}.')
        
        # ========== ENTREGAR CREDENCIAL ==========
        if credencial and not kit.credencial_entregada:
            credencial_inv = InventarioGlobal.objects.filter(
                articulo='credencial',
                stock_actual__gt=0
            ).first()
            
            if credencial_inv:
                kit.credencial_entregada = True
                delivered.append('credencial')
                credencial_inv.stock_actual -= 1
                credencial_inv.save()
                messages.info(request, '✅ Credencial entregada.')
            else:
                errors.append('❌ No hay stock de credenciales.')
        
        # ========== ENTREGAR MANILLA ==========
        if manilla and not kit.manilla_entregada:
            manilla_inv = InventarioGlobal.objects.filter(
                articulo='manilla',
                talla='unica',
                color_hex__iexact=color_grupo,
                stock_actual__gt=0
            ).first()
            
            if manilla_inv:
                kit.manilla_entregada = True
                kit.manilla_color = color_grupo
                delivered.append('manilla')
                manilla_inv.stock_actual -= 1
                manilla_inv.save()
                messages.info(request, f'✅ Manilla {color_nombre or color_grupo} entregada.')
            else:
                errors.append(f'❌ No hay stock de manilla {color_nombre or color_grupo}.')
        
        # ========== GUARDAR CAMBIOS ==========
        if delivered or errors:
            kit.entregado_por = request.user if request.user.is_authenticated else None
            kit.fecha_entrega = timezone.now()
            kit.save()

        if delivered:
            messages.success(request, f'🎉 Kit actualizado para {insc.nombre_persona}. Elementos entregados: {", ".join(delivered)}')
        
        if errors:
            for error in errors:
                messages.error(request, error)
        
        return redirect('lista_inscritos')
    
    # Preparar datos para el template (GET request)
    poleras_disponibles = InventarioGlobal.objects.filter(
        articulo='polera',
        color_hex__iexact=color_grupo,
        stock_actual__gt=0
    ).order_by('talla') if color_grupo else []
    
    pañoletas_disponibles = InventarioGlobal.objects.filter(
        articulo='pañoleta',
        color_hex__iexact=color_grupo,
        stock_actual__gt=0
    ).first() if color_grupo else None
    
    credenciales_disponibles = InventarioGlobal.objects.filter(
        articulo='credencial',
        stock_actual__gt=0
    ).first()
    
    manillas_disponibles = InventarioGlobal.objects.filter(
        articulo='manilla',
        color_hex__iexact=color_grupo,
        stock_actual__gt=0
    ).first() if color_grupo else None
    
    tallas_polera = []
    if color_grupo:
        tallas_polera = poleras_disponibles.values_list('talla', flat=True).distinct()
    
    # Preparar lista de poleras asignadas para mostrar
    poleras_asignadas_para_template = []
    for polera_kit in poleras_asignadas_color:
        poleras_asignadas_para_template.append({
            'numero': polera_kit.polera_numero_id,
            'talla': polera_kit.polera_talla,
            'nombre': polera_kit.inscripcion.nombre_persona if polera_kit.inscripcion else ''
        })
    
    return render(request, 'principal/entregar_kit.html', {
        'insc': insc,
        'kit': kit,
        'color_grupo': color_grupo,
        'color_nombre': color_nombre,
        'proximo_numero_polera': proximo_numero,
        'poleras_disponibles': poleras_disponibles,
        'pañoletas_disponibles': pañoletas_disponibles,
        'credenciales_disponibles': credenciales_disponibles,
        'manillas_disponibles': manillas_disponibles,
        'tallas_polera': list(tallas_polera),
        'poleras_asignadas_color': poleras_asignadas_para_template,
        'hay_stock_polera': poleras_disponibles.exists() if hasattr(poleras_disponibles, 'exists') else False,
        'hay_stock_pañoleta': pañoletas_disponibles is not None,
        'hay_stock_credencial': credenciales_disponibles is not None,
        'hay_stock_manilla': manillas_disponibles is not None,
    })

@require_role('admin', 'director')
def gestionar_poleras(request):
    """Vista para gestionar inventario de poleras"""
    if request.method == 'POST':
        form = InventarioForm(request.POST)
        if form.is_valid():
            item = form.save(commit=False)
            item.articulo = 'polera'
            item.autor = request.user
            item.stock_total = item.stock_actual
            item.save()
            messages.success(request, f'Polera {item.color_nombre} talla {item.talla} agregada al inventario')
            return redirect('gestionar_poleras')
    else:
        form = InventarioForm(initial={'articulo': 'polera'})
    
    # Estadísticas
    poleras = InventarioGlobal.objects.filter(articulo='polera').order_by('color_nombre', 'talla')
    total_stock = sum(p.stock_actual for p in poleras)
    total_asignadas = sum(len(p.numeros_asignados.split(',')) for p in poleras if p.numeros_asignados)
    
    return render(request, 'principal/gestionar_poleras.html', {
        'form': form,
        'poleras': poleras,
        'total_stock': total_stock,
        'total_asignadas': total_asignadas,
        'disponibles': total_stock - total_asignadas,
    })

# ============ VISTAS DE PUNTOS Y COMPETENCIA (FINAL) ============

from django.core.paginator import Paginator
from django.db import transaction

@require_role('director', 'admin')
def agregar_puntos(request):
    """Vista para agregar puntos a un grupo individual con historial integrado"""
    if request.method == 'POST':
        form = HistorialPuntosForm(request.POST)
        if form.is_valid():
            historial = form.save(commit=False)
            historial.autor = request.user if request.user.is_authenticated else None
            historial.save()
            
            # Actualizar puntos del grupo
            grupo = historial.grupo
            grupo.puntos_totales += historial.cantidad
            grupo.save()
            
            messages.success(request, f'✅ Se agregaron {historial.cantidad} puntos a {grupo.nombre}')
            return redirect('agregar_puntos')
    else:
        form = HistorialPuntosForm()
    
    # Obtener todos los grupos para el modo masivo
    grupos = Grupo.objects.all().order_by('nombre')
    
    # Obtener historial completo de puntos
    historial_completo = HistorialPuntos.objects.select_related('grupo', 'autor').order_by('-fecha')
    
    # Paginación
    paginator = Paginator(historial_completo, 20)
    page_number = request.GET.get('page', 1)
    historial_paginado = paginator.get_page(page_number)
    
    # Resumen de puntos por grupo
    grupos_resumen = Grupo.objects.all().order_by('-puntos_totales')
    
    context = {
        'form': form,
        'grupos': grupos,  # Para el formulario masivo
        'historial_completo': historial_paginado,
        'grupos_resumen': grupos_resumen,
    }
    
    return render(request, 'principal/agregar_puntos.html', context)


@require_role('director', 'admin')
@transaction.atomic
def agregar_puntos_masivo(request):
    """Vista para agregar puntos diferenciados a todos los grupos de una vez"""
    if request.method == 'POST':
        motivo_general = request.POST.get('motivo_general', '').strip()
        
        if not motivo_general:
            messages.error(request, '❌ Debes proporcionar un motivo general')
            return redirect('agregar_puntos')
        
        grupos_actualizados = 0
        puntos_asignados_total = 0
        
        # Obtener todos los grupos
        grupos = Grupo.objects.all()
        
        for grupo in grupos:
            # Obtener los puntos para este grupo desde el formulario
            puntos_key = f'puntos_{grupo.id}'
            puntos_str = request.POST.get(puntos_key, '0').strip()
            
            # Convertir a entero, si está vacío o es 0, ignorar
            try:
                puntos = int(puntos_str) if puntos_str else 0
            except ValueError:
                puntos = 0
            
            # Solo procesar si hay puntos diferentes de 0
            if puntos != 0:
                # Crear registro en historial
                HistorialPuntos.objects.create(
                    grupo=grupo,
                    cantidad=puntos,
                    motivo=motivo_general,
                    autor=request.user if request.user.is_authenticated else None
                )
                
                # Actualizar puntos del grupo
                grupo.puntos_totales += puntos
                grupo.save()
                
                grupos_actualizados += 1
                puntos_asignados_total += abs(puntos)
        
        if grupos_actualizados > 0:
            messages.success(
                request, 
                f'✅ Se actualizaron {grupos_actualizados} grupos con un total de {puntos_asignados_total} puntos asignados'
            )
        else:
            messages.warning(request, '⚠️ No se asignaron puntos a ningún grupo')
        
        # Redirigir al ranking como se solicitó
        return redirect('ranking')
    
    # Si no es POST, redirigir a la página de agregar puntos
    return redirect('agregar_puntos')


def historial_puntos(request, grupo_id=None):
    """Vista del historial de puntos por grupo específico"""
    if grupo_id:
        grupo = get_object_or_404(Grupo, id=grupo_id)
        historial = HistorialPuntos.objects.filter(grupo=grupo).select_related('autor').order_by('-fecha')
        
        # Paginación
        paginator = Paginator(historial, 15)
        page_number = request.GET.get('page', 1)
        historial_paginado = paginator.get_page(page_number)
        
        context = {
            'grupo': grupo,
            'historial': historial_paginado,
        }
        return render(request, 'principal/historial_puntos_grupo.html', context)
    else:
        # Vista general de todos los grupos
        grupos = Grupo.objects.all().order_by('-puntos_totales')
        return render(request, 'principal/historial_puntos.html', {'grupos': grupos})
# ============ VISTAS DE USUARIOS ============
@require_role('admin')
def listar_usuarios(request):
    """Lista todos los usuarios"""
    usuarios = Usuario.objects.all().order_by('username')
    return render(request, 'principal/usuarios_lista.html', {'usuarios': usuarios})

def crear_usuario(request):
    """Crea un nuevo usuario"""
    if request.method == 'POST':
        form = UsuarioCrearForm(request.POST)
        if form.is_valid():
            user = form.save()
            # Vincular inscripción si se seleccionó
            insc = form.cleaned_data.get('inscripcion')
            if insc:
                insc.user = user
                insc.save()
            messages.success(request, f'Usuario {user.username} creado correctamente.')
            return redirect('listar_usuarios')
    else:
        form = UsuarioCrearForm()
    
    return render(request, 'principal/usuario_crear.html', {'form': form})

def editar_usuario(request, usuario_id):
    """Edita un usuario existente"""
    usuario = get_object_or_404(Usuario, id=usuario_id)
    
    if request.method == 'POST':
        form = UsuarioEditarForm(request.POST, instance=usuario)
        if form.is_valid():
            form.save()
            messages.success(request, f'Usuario {usuario.username} actualizado correctamente.')
            return redirect('listar_usuarios')
    else:
        form = UsuarioEditarForm(instance=usuario)
    
    return render(request, 'principal/usuario_editar.html', {'form': form, 'usuario': usuario})

def eliminar_usuario(request, usuario_id):
    """Elimina un usuario"""
    usuario = get_object_or_404(Usuario, id=usuario_id)
    
    if request.method == 'POST':
        username = usuario.username
        usuario.delete()
        messages.success(request, f'Usuario {username} eliminado correctamente.')
        return redirect('listar_usuarios')
    
    return render(request, 'principal/usuario_eliminar.html', {'usuario': usuario})

# ============ VISTAS DE INVENTARIO ============
@require_role('inscripcion', 'admin')
def listar_inventario(request):
    """Lista todo el inventario"""
    items = InventarioGlobal.objects.all().order_by('articulo', 'color_nombre', 'talla')
    return render(request, 'principal/inventario_lista.html', {'items': items})

def crear_inventario(request):
    """Crea un nuevo item en el inventario"""
    if not request.user.is_authenticated:
        messages.error(request, 'Debes estar autenticado para crear inventario.')
        return redirect('login')
    
    grupos = Grupo.objects.all().order_by('nombre')
    
    if request.method == 'POST':
        form = InventarioForm(request.POST)
        if form.is_valid():
            inv = form.save(commit=False)
            inv.autor = request.user
            
            color_hex = request.POST.get('color_hex')
            color_nombre = request.POST.get('color_nombre')
            
            if not color_hex or not color_nombre:
                messages.error(request, '⚠️ Debes seleccionar un color de equipo')
                return render(request, 'principal/inventario_crear.html', {
                    'form': form,
                    'grupos': grupos,
                    'titulo': 'Crear Artículo en Inventario'
                })
            
            inv.color_hex = color_hex
            inv.color_nombre = color_nombre
            # Si ya existe un inventario con mismo articulo/talla/color, sumar los stocks en lugar de crear duplicado
            existente = InventarioGlobal.objects.filter(
                articulo=inv.articulo,
                talla=inv.talla,
                color_hex=inv.color_hex
            ).first()

            if existente:
                existente.stock_total = (existente.stock_total or 0) + (inv.stock_actual or 0)
                existente.stock_actual = (existente.stock_actual or 0) + (inv.stock_actual or 0)
                existente.save()
                messages.success(request, f'✅ Stock actualizado para {existente.get_articulo_display()} ({existente.color_nombre}) — +{inv.stock_actual} unidades.')
                return redirect('listar_inventario')

            inv.stock_total = inv.stock_actual
            inv.save()

            messages.success(request, f'✅ Artículo {inv.get_articulo_display()} ({inv.color_nombre}) registrado correctamente.')
            return redirect('listar_inventario')
        else:
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f'{field}: {error}')
    else:
        form = InventarioForm()
    
    return render(request, 'principal/inventario_crear.html', {
        'form': form,
        'grupos': grupos,
        'titulo': 'Crear Artículo en Inventario'
    })

def editar_inventario(request, item_id):
    """Edita un item del inventario"""
    item = get_object_or_404(InventarioGlobal, id=item_id)
    
    grupos = Grupo.objects.all().order_by('nombre')
    
    if request.method == 'POST':
        form = InventarioForm(request.POST, instance=item)
        if form.is_valid():
            inv = form.save(commit=False)
            
            color_hex = request.POST.get('color_hex')
            color_nombre = request.POST.get('color_nombre')
            
            if not color_hex or not color_nombre:
                messages.error(request, '⚠️ Debes seleccionar un color de equipo')
                return render(request, 'principal/inventario_crear.html', {
                    'form': form,
                    'item': item,
                    'grupos': grupos,
                    'titulo': f'Editar {item.get_articulo_display()}'
                })
            
            inv.color_hex = color_hex
            inv.color_nombre = color_nombre
            inv.save()
            
            messages.success(request, '✅ Inventario actualizado correctamente.')
            return redirect('listar_inventario')
        else:
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f'{field}: {error}')
    else:
        form = InventarioForm(instance=item)
    
    return render(request, 'principal/inventario_crear.html', {
        'form': form,
        'item': item,
        'grupos': grupos,
        'titulo': f'Editar {item.get_articulo_display()}'
    })

def eliminar_inventario(request, item_id):
    """Elimina un item del inventario"""
    item = get_object_or_404(InventarioGlobal, id=item_id)
    
    if request.method == 'POST':
        articulo = item.get_articulo_display()
        color = item.color_nombre
        item.delete()
        messages.success(request, f'✅ Artículo {articulo} ({color}) eliminado correctamente.')
        return redirect('listar_inventario')
    
    return render(request, 'principal/inventario_eliminar.html', {'item': item})

# ============ VISTAS DE PERFIL ============
def mi_perfil(request):
    """Vista del perfil del usuario actual"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    usuario = request.user
    
    if request.method == 'POST':
        email = request.POST.get('email', '').strip()
        nueva_contrasena = request.POST.get('nueva_contrasena')
        confirmar_contrasena = request.POST.get('confirmar_contrasena')
        contrasena_actual = request.POST.get('contrasena_actual')
        foto_perfil = request.FILES.get('foto_perfil')
        eliminar_foto = request.POST.get('eliminar_foto')
        
        # Eliminar foto si se solicita
        if eliminar_foto:
            if usuario.foto_perfil:
                usuario.foto_perfil.delete()
                usuario.foto_perfil = None
                messages.success(request, 'Foto de perfil eliminada correctamente.')
        
        if nueva_contrasena:
            if not usuario.check_password(contrasena_actual):
                messages.error(request, 'Contraseña actual incorrecta.')
                return render(request, 'principal/mi_perfil.html', {'usuario': usuario})
            
            if nueva_contrasena != confirmar_contrasena:
                messages.error(request, 'Las contraseñas no coinciden.')
                return render(request, 'principal/mi_perfil.html', {'usuario': usuario})
            
            if len(nueva_contrasena) < 6:
                messages.error(request, 'La contraseña debe tener al menos 6 caracteres.')
                return render(request, 'principal/mi_perfil.html', {'usuario': usuario})
            
            usuario.set_password(nueva_contrasena)
        
        # Email es opcional
        if email:
            usuario.email = email
        
        # Procesar foto de perfil
        if foto_perfil:
            usuario.foto_perfil = foto_perfil
            messages.success(request, 'Foto de perfil actualizada correctamente.')
        
        usuario.save()
        
        if not eliminar_foto:
            messages.success(request, 'Perfil actualizado correctamente.')
        return redirect('mi_perfil')
    
    return render(request, 'principal/mi_perfil.html', {'usuario': usuario})

# ============ VISTAS DE LIKES Y COMENTARIOS ============
def agregar_like(request, publicacion_id):
    """Agrega o quita un like a una publicación"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    publicacion = get_object_or_404(Publicacion, id=publicacion_id)
    
    reaccion_existente = Reaccion.objects.filter(
        publicacion=publicacion, 
        usuario=request.user, 
        tipo='like'
    ).first()
    
    if reaccion_existente:
        reaccion_existente.delete()
        liked = False
    else:
        Reaccion.objects.create(
            publicacion=publicacion,
            usuario=request.user,
            tipo='like'
        )
        liked = True
    
    total_likes = Reaccion.objects.filter(
        publicacion=publicacion,
        tipo='like'
    ).count()
    
    return JsonResponse({
        'success': True,
        'liked': liked,
        'total_likes': total_likes
    })

def agregar_comentario(request, publicacion_id):
    """Agrega un comentario a una publicación"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    publicacion = get_object_or_404(Publicacion, id=publicacion_id)
    
    if request.method == 'POST':
        texto = request.POST.get('texto', '').strip()
        if texto:
            Comentario.objects.create(
                publicacion=publicacion,
                usuario=request.user,
                texto=texto
            )
            messages.success(request, 'Comentario agregado correctamente.')
        else:
            messages.error(request, 'El comentario no puede estar vacío.')
    
    return redirect('muro')

def eliminar_comentario(request, comentario_id):
    """Elimina un comentario"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    comentario = get_object_or_404(Comentario, id=comentario_id)
    
    if comentario.usuario != request.user and not request.user.is_superuser:
        messages.error(request, 'No tienes permiso para eliminar este comentario.')
        return redirect('muro')
    
    comentario.delete()
    messages.success(request, 'Comentario eliminado.')
    return redirect('muro')

# ============ CRUD DE GRUPOS ============
@require_role('inscripcion', 'admin')
def listar_grupos(request):
    """Lista todos los grupos"""
    grupos = Grupo.objects.all().order_by('nombre')
    return render(request, 'principal/grupo_lista.html', {'grupos': grupos})

@require_role('inscripcion', 'admin')
def crear_grupo(request):
    """Crea un nuevo grupo"""
    if request.method == 'POST':
        form = GrupoForm(request.POST, request.FILES)
        if form.is_valid():
            grupo = form.save()
            messages.success(request, f'Grupo "{grupo.nombre}" creado correctamente.')
            return redirect('listar_grupos')
    else:
        form = GrupoForm()
    return render(request, 'principal/grupo_crear.html', {'form': form})

@require_role('inscripcion', 'admin')
def editar_grupo(request, grupo_id):
    """Edita un grupo existente"""
    grupo = get_object_or_404(Grupo, id=grupo_id)
    
    if request.method == 'POST':
        form = GrupoForm(request.POST, request.FILES, instance=grupo)
        if form.is_valid():
            grupo = form.save()
            messages.success(request, f'Grupo "{grupo.nombre}" actualizado correctamente.')
            return redirect('listar_grupos')
    else:
        form = GrupoForm(instance=grupo)
    
    return render(request, 'principal/grupo_editar.html', {'form': form, 'grupo': grupo})

@require_role('inscripcion', 'admin')
def eliminar_grupo(request, grupo_id):
    """Elimina un grupo"""
    grupo = get_object_or_404(Grupo, id=grupo_id)
    
    if request.method == 'POST':
        nombre = grupo.nombre
        grupo.delete()
        messages.success(request, f'Grupo "{nombre}" eliminado correctamente.')
        return redirect('listar_grupos')
    
    return render(request, 'principal/grupo_eliminar.html', {'grupo': grupo})

# ============ CRUD DE ACTIVIDADES ============
@require_role('campamentista', 'inscripcion', 'director', 'admin', 'lider', 'pastor')
def listar_actividades(request):
    """Listar todas las actividades en cronograma"""
    actividades = Actividad.objects.all().order_by('hora_inicio')
    
    es_obligatoria = request.GET.get('obligatoria')
    if es_obligatoria == 'true':
        actividades = actividades.filter(es_obligatoria=True)
    elif es_obligatoria == 'false':
        actividades = actividades.filter(es_obligatoria=False)
    
    return render(request, 'principal/actividad_lista.html', {
        'actividades': actividades,
        'hoy': timezone.now().date(),
    })

@require_role('admin')
def crear_actividad(request):
    """Crear una nueva actividad"""
    if request.method == 'POST':
        form = ActividadForm(request.POST)
        if form.is_valid():
            actividad = form.save(commit=False)
            actividad.autor = request.user
            actividad.save()
            messages.success(request, f'Actividad "{actividad.titulo}" creada correctamente.')
            return redirect('listar_actividades')
    else:
        form = ActividadForm()
    return render(request, 'principal/actividad_crear.html', {'form': form})

@require_role('admin')
def editar_actividad(request, actividad_id):
    """Editar una actividad existente"""
    actividad = get_object_or_404(Actividad, id=actividad_id)
    
    if request.method == 'POST':
        form = ActividadForm(request.POST, instance=actividad)
        if form.is_valid():
            actividad = form.save()
            messages.success(request, f'Actividad "{actividad.titulo}" actualizada correctamente.')
            return redirect('listar_actividades')
    else:
        form = ActividadForm(instance=actividad)
    
    return render(request, 'principal/actividad_editar.html', {'form': form, 'actividad': actividad})

@require_role('admin')
def eliminar_actividad(request, actividad_id):
    """Eliminar una actividad"""
    actividad = get_object_or_404(Actividad, id=actividad_id)
    
    if request.method == 'POST':
        titulo = actividad.titulo
        actividad.delete()
        messages.success(request, f'Actividad "{titulo}" eliminada correctamente.')
        return redirect('listar_actividades')
    
    return render(request, 'principal/actividad_eliminar.html', {'actividad': actividad})

# ============ CRUD DE NOTICIAS ============
@require_role('campamentista', 'inscripcion', 'director', 'admin', 'lider', 'pastor')
def listar_noticias(request):
    """Listar todas las noticias"""
    noticias = Noticia.objects.all().order_by('-fecha_publicacion')
    return render(request, 'principal/noticia_lista.html', {'noticias': noticias})

@require_role('inscripcion', 'admin', 'lider')
def crear_noticia(request):
    """Crear una nueva noticia"""
    if request.method == 'POST':
        form = NoticiaForm(request.POST)
        if form.is_valid():
            noticia = form.save(commit=False)
            noticia.autor = request.user
            noticia.save()
            usuarios = Usuario.objects.all()
            for usuario in usuarios:
                Notificacion.objects.create(
                    usuario=usuario,
                    titulo=f'Nueva noticia: {noticia.titulo}',
                    mensaje=noticia.contenido[:100] + '...',
                    tipo='noticia'
                )
            messages.success(request, f'Noticia "{noticia.titulo}" creada correctamente.')
            return redirect('listar_noticias')
    else:
        form = NoticiaForm()
    return render(request, 'principal/noticia_crear.html', {'form': form})

@require_role('inscripcion', 'admin', 'lider')
def editar_noticia(request, noticia_id):
    """Editar una noticia existente"""
    noticia = get_object_or_404(Noticia, id=noticia_id)
    
    if request.method == 'POST':
        form = NoticiaForm(request.POST, instance=noticia)
        if form.is_valid():
            noticia = form.save()
            messages.success(request, f'Noticia "{noticia.titulo}" actualizada correctamente.')
            return redirect('listar_noticias')
    else:
        form = NoticiaForm(instance=noticia)
    
    return render(request, 'principal/noticia_editar.html', {'form': form, 'noticia': noticia})

@require_role('inscripcion', 'admin', 'lider')
def eliminar_noticia(request, noticia_id):
    """Eliminar una noticia"""
    noticia = get_object_or_404(Noticia, id=noticia_id)
    
    if request.method == 'POST':
        titulo = noticia.titulo
        noticia.delete()
        messages.success(request, f'Noticia "{titulo}" eliminada correctamente.')
        return redirect('listar_noticias')
    
    return render(request, 'principal/noticia_eliminar.html', {'noticia': noticia})

# ============ VISTAS DE NOTIFICACIONES ============
def listar_notificaciones(request):
    """Listar las notificaciones del usuario"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    notificaciones = request.user.notificaciones.all()
    no_leidas = notificaciones.filter(leida=False).count()
    
    return render(request, 'principal/notificacion_lista.html', {
        'notificaciones': notificaciones,
        'no_leidas': no_leidas,
    })

def marcar_notificacion_leida(request, notificacion_id):
    """Marcar una notificación como leída"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    notificacion = get_object_or_404(Notificacion, id=notificacion_id, usuario=request.user)
    notificacion.leida = True
    notificacion.save()
    
    return redirect('listar_notificaciones')

def marcar_todas_leidas(request):
    """Marcar todas las notificaciones como leídas"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    request.user.notificaciones.filter(leida=False).update(leida=True)
    messages.success(request, 'Todas las notificaciones marcadas como leídas.')
    
    return redirect('listar_notificaciones')

def eliminar_notificacion(request, notificacion_id):
    """Eliminar una notificación"""
    if not request.user.is_authenticated:
        return redirect('login')
    
    notificacion = get_object_or_404(Notificacion, id=notificacion_id, usuario=request.user)
    notificacion.delete()
    messages.success(request, 'Notificación eliminada.')
    
    return redirect('listar_notificaciones')

# ============ VISTAS PARA IGLESIAS Y UNIONES ============
@require_role('inscripcion', 'admin')
def gestionar_iglesias_uniones(request):
    """
    Vista unificada para gestionar iglesias y uniones en una sola página
    """
    if request.user.rol not in ['admin', 'director', 'inscripcion']:
        messages.error(request, 'No tienes permiso para acceder a esta página.')
        return redirect('dashboard')
    
    # Contexto inicial
    context = {
        'titulo': 'Gestión de Iglesias y Uniones',
        'active_tab': 'iglesias'  # Tab por defecto
    }
    
    # Obtener datos
    iglesias = Iglesia.objects.all().order_by('nombre')
    uniones = Union.objects.all().order_by('nombre')
    
    # Manejar creación/edición de iglesias
    if 'accion_iglesia' in request.GET:
        accion = request.GET.get('accion_iglesia')
        iglesia_id = request.GET.get('iglesia_id')
        
        if accion == 'crear':
            form_iglesia = IglesiaForm()
            context.update({
                'mostrar_form_iglesia': True,
                'form_iglesia': form_iglesia,
                'accion_iglesia': 'crear'
            })
        
        elif accion == 'editar' and iglesia_id:
            try:
                iglesia = Iglesia.objects.get(id=iglesia_id)
                form_iglesia = IglesiaForm(instance=iglesia)
                context.update({
                    'mostrar_form_iglesia': True,
                    'form_iglesia': form_iglesia,
                    'iglesia_actual': iglesia,
                    'accion_iglesia': 'editar'
                })
            except Iglesia.DoesNotExist:
                messages.error(request, 'Iglesia no encontrada.')
        
        elif accion == 'eliminar' and iglesia_id:
            try:
                iglesia = Iglesia.objects.get(id=iglesia_id)
                context.update({
                    'mostrar_eliminar_iglesia': True,
                    'iglesia_a_eliminar': iglesia
                })
            except Iglesia.DoesNotExist:
                messages.error(request, 'Iglesia no encontrada.')
    
    # Manejar creación/edición de uniones
    if 'accion_union' in request.GET:
        context['active_tab'] = 'uniones'
        accion = request.GET.get('accion_union')
        union_id = request.GET.get('union_id')
        
        if accion == 'crear':
            form_union = UnionForm()
            context.update({
                'mostrar_form_union': True,
                'form_union': form_union,
                'accion_union': 'crear'
            })
        
        elif accion == 'editar' and union_id:
            try:
                union = Union.objects.get(id=union_id)
                form_union = UnionForm(instance=union)
                context.update({
                    'mostrar_form_union': True,
                    'form_union': form_union,
                    'union_actual': union,
                    'accion_union': 'editar'
                })
            except Union.DoesNotExist:
                messages.error(request, 'Unión no encontrada.')
        
        elif accion == 'eliminar' and union_id:
            try:
                union = Union.objects.get(id=union_id)
                context.update({
                    'mostrar_eliminar_union': True,
                    'union_a_eliminar': union
                })
            except Union.DoesNotExist:
                messages.error(request, 'Unión no encontrada.')
    
    # Manejar POST para iglesias
    if request.method == 'POST':
        if 'form_iglesia_submit' in request.POST:
            iglesia_id = request.POST.get('iglesia_id')
            
            if iglesia_id:  # Editar
                try:
                    iglesia = Iglesia.objects.get(id=iglesia_id)
                    form_iglesia = IglesiaForm(request.POST, instance=iglesia)
                except Iglesia.DoesNotExist:
                    messages.error(request, 'Iglesia no encontrada.')
                    return redirect('gestionar_iglesias_uniones')
            else:  # Crear
                form_iglesia = IglesiaForm(request.POST)
            
            if form_iglesia.is_valid():
                form_iglesia.save()
                messages.success(request, f'Iglesia {"actualizada" if iglesia_id else "creada"} exitosamente.')
                return redirect('gestionar_iglesias_uniones')
            else:
                context.update({
                    'mostrar_form_iglesia': True,
                    'form_iglesia': form_iglesia,
                    'accion_iglesia': 'editar' if iglesia_id else 'crear',
                    'active_tab': 'iglesias'
                })
        
        elif 'form_union_submit' in request.POST:
            union_id = request.POST.get('union_id')
            
            if union_id:  # Editar
                try:
                    union = Union.objects.get(id=union_id)
                    form_union = UnionForm(request.POST, instance=union)
                except Union.DoesNotExist:
                    messages.error(request, 'Unión no encontrada.')
                    return redirect('gestionar_iglesias_uniones')
            else:  # Crear
                form_union = UnionForm(request.POST)
            
            if form_union.is_valid():
                form_union.save()
                messages.success(request, f'Unión {"actualizada" if union_id else "creada"} exitosamente.')
                return redirect('gestionar_iglesias_uniones')
            else:
                context.update({
                    'mostrar_form_union': True,
                    'form_union': form_union,
                    'accion_union': 'editar' if union_id else 'crear',
                    'active_tab': 'uniones'
                })
        
        elif 'eliminar_iglesia_confirm' in request.POST:
            iglesia_id = request.POST.get('iglesia_id')
            if iglesia_id and request.user.rol == 'admin':
                try:
                    iglesia = Iglesia.objects.get(id=iglesia_id)
                    # Verificar si tiene inscripciones
                    if hasattr(iglesia, 'inscripcion_set'):
                        if iglesia.inscripcion_set.exists():
                            messages.error(request, 'No se puede eliminar esta iglesia porque tiene inscripciones asociadas.')
                            return redirect('gestionar_iglesias_uniones')
                    
                    iglesia.delete()
                    messages.success(request, 'Iglesia eliminada exitosamente.')
                except Iglesia.DoesNotExist:
                    messages.error(request, 'Iglesia no encontrada.')
            
            return redirect('gestionar_iglesias_uniones')
        
        elif 'eliminar_union_confirm' in request.POST:
            union_id = request.POST.get('union_id')
            if union_id and request.user.rol == 'admin':
                try:
                    union = Union.objects.get(id=union_id)
                    # Verificar si tiene inscripciones
                    if Inscripcion.objects.filter(union=union).exists():
                        messages.error(request, 'No se puede eliminar esta unión porque tiene inscripciones asociadas.')
                        return redirect('gestionar_iglesias_uniones')
                    
                    union.delete()
                    messages.success(request, 'Unión eliminada exitosamente.')
                except Union.DoesNotExist:
                    messages.error(request, 'Unión no encontrada.')
            
            return redirect('gestionar_iglesias_uniones')
    
    # Añadir datos al contexto
    context.update({
        'iglesias': iglesias,
        'uniones': uniones,
        'es_admin': request.user.rol == 'admin'
    })
    
    return render(request, 'principal/gestion_iglesias_uniones.html', context)

@require_role('inscripcion', 'admin')
def registrar_inscrito(request):
    """Redirige a la lista de inscritos con el formulario visible"""
    return redirect(f"{request.scheme}://{request.get_host()}{'/inscripcion/lista/'}?show=form")

# ============ VISTAS PARA GESTIÓN DE KITS (TODAS EN UNA) ============

@login_required
def gestion_kits_completa(request):
    """
    Vista única para gestionar todos los kits en una sola página
    Combina historial, edición y estadísticas
    """
    # Obtener todos los kits con información relacionada
    kits = LogisticaKit.objects.select_related(
        'inscripcion',
        'inscripcion__iglesia',
        'inscripcion__grupo'
    ).order_by('-fecha_entrega', '-id')
    
    # Estadísticas generales
    total_kits = kits.count()
    
    kits_completos = kits.filter(
        polera_entregada=True,
        pañoleta_entregada=True,
        credencial_entregada=True,
        manilla_entregada=True
    ).count()
    
    kits_parciales = kits.filter(
        Q(polera_entregada=True) | Q(pañoleta_entregada=True) | 
        Q(credencial_entregada=True) | Q(manilla_entregada=True)
    ).exclude(
        polera_entregada=True,
        pañoleta_entregada=True,
        credencial_entregada=True,
        manilla_entregada=True
    ).count()
    
    kits_pendientes = kits.filter(
        polera_entregada=False,
        pañoleta_entregada=False,
        credencial_entregada=False,
        manilla_entregada=False
    ).count()
    
    # Filtrar kits por búsqueda
    query = request.GET.get('q', '')
    estado_filter = request.GET.get('estado', '')
    equipo_filter = request.GET.get('equipo', '')
    
    if query:
        kits = kits.filter(
            Q(inscripcion__nombre_persona__icontains=query) |
            Q(inscripcion__iglesia__nombre__icontains=query) |
            Q(polera_numero_id__icontains=query) |
            Q(polera_talla__icontains=query)
        )
    
    if estado_filter:
        if estado_filter == 'completo':
            kits = kits.filter(
                polera_entregada=True,
                pañoleta_entregada=True,
                credencial_entregada=True,
                manilla_entregada=True
            )
        elif estado_filter == 'parcial':
            kits = kits.filter(
                Q(polera_entregada=True) | Q(pañoleta_entregada=True) | 
                Q(credencial_entregada=True) | Q(manilla_entregada=True)
            ).exclude(
                polera_entregada=True,
                pañoleta_entregada=True,
                credencial_entregada=True,
                manilla_entregada=True
            )
        elif estado_filter == 'pendiente':
            kits = kits.filter(
                polera_entregada=False,
                pañoleta_entregada=False,
                credencial_entregada=False,
                manilla_entregada=False
            )
    
    if equipo_filter:
        kits = kits.filter(inscripcion__grupo_id=equipo_filter)
    
    # Obtener grupos para filtro
    grupos = Grupo.objects.all().order_by('nombre')
    
    # Paginación
    paginator = Paginator(kits, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'total_kits': total_kits,
        'kits_completos': kits_completos,
        'kits_parciales': kits_parciales,
        'kits_pendientes': kits_pendientes,
        'grupos': grupos,
        'query': query,
        'estado_filter': estado_filter,
        'equipo_filter': equipo_filter,
    }
    
    return render(request, 'principal/gestion_kits_completa.html', context)

# views.py
from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from django.db.models import Count, Q, F
from django.db import transaction
from django.utils import timezone
from .models import LogisticaKit, Inscripcion, InventarioGlobal

def editar_kit_modal(request, kit_id):
    kit = get_object_or_404(LogisticaKit, id=kit_id)
    inscripcion = kit.inscripcion
    
    print(f"=== DEBUG editar_kit_modal ===")
    print(f"Kit ID: {kit_id}")
    print(f"Inscripción: {inscripcion.nombre_persona}")
    print(f"Grupo: {inscripcion.grupo.nombre if inscripcion.grupo else 'Sin grupo'}")
    
    # Determinar color actual de la polera (del grupo)
    color_polera_actual = None
    if inscripcion.grupo:
        color_polera_actual = {
            'nombre': inscripcion.grupo.color_nombre,
            'hex': inscripcion.grupo.color_hex
        }
        print(f"Color grupo: {inscripcion.grupo.color_hex} - {inscripcion.grupo.color_nombre}")
    
    # Obtener stock del color actual de polera
    stock_color_actual = None
    if inscripcion.grupo and inscripcion.grupo.color_hex:
        # Buscar poleras del color actual con stock
        poleras_color = InventarioGlobal.objects.filter(
            articulo='polera',
            color_hex__iexact=inscripcion.grupo.color_hex,
            stock_actual__gt=0
        )
        
        print(f"Poleras encontradas para color {inscripcion.grupo.color_hex}: {poleras_color.count()}")
        
        if poleras_color.exists():
            # Calcular total por color
            total_color = poleras_color.aggregate(
                total=Sum('stock_actual')
            )['total'] or 0
            
            # Obtener tallas disponibles
            tallas_disponibles = []
            tallas = poleras_color.values('talla').annotate(
                cantidad=Sum('stock_actual')
            ).order_by('talla')
            
            for talla_info in tallas:
                tallas_disponibles.append({
                    'talla': talla_info['talla'],
                    'cantidad': talla_info['cantidad']
                })
            
            stock_color_actual = {
                'total': total_color,
                'tallas': tallas_disponibles
            }
            print(f"Stock polera: {total_color} unidades, {len(tallas_disponibles)} tallas")
    
    # Obtener stock para pañoleta del color actual
    stock_pañoleta_color = None
    if inscripcion.grupo and inscripcion.grupo.color_hex:
        pañoletas = InventarioGlobal.objects.filter(
            articulo='pañoleta',
            color_hex__iexact=inscripcion.grupo.color_hex,
            stock_actual__gt=0
        ).first()
        
        if pañoletas:
            stock_pañoleta_color = {
                'nombre': pañoletas.color_nombre or inscripcion.grupo.color_nombre,
                'hex': pañoletas.color_hex,
                'disponibles': pañoletas.stock_actual
            }
            print(f"Stock pañoleta: {pañoletas.stock_actual}")
    
    # Obtener stock para credencial (general)
    stock_credencial = None
    credenciales = InventarioGlobal.objects.filter(
        articulo='credencial',
        stock_actual__gt=0
    ).first()
    
    if credenciales:
        stock_credencial = {
            'nombre': credenciales.color_nombre or 'Credenciales',
            'disponibles': credenciales.stock_actual
        }
        print(f"Stock credencial: {credenciales.stock_actual}")
    
    # Obtener stock para manilla del color actual
    stock_manilla_color = None
    if inscripcion.grupo and inscripcion.grupo.color_hex:
        manillas = InventarioGlobal.objects.filter(
            articulo='manilla',
            color_hex__iexact=inscripcion.grupo.color_hex,
            stock_actual__gt=0
        ).first()
        
        if manillas:
            stock_manilla_color = {
                'nombre': manillas.color_nombre or inscripcion.grupo.color_nombre,
                'hex': manillas.color_hex,
                'disponibles': manillas.stock_actual
            }
            print(f"Stock manilla: {manillas.stock_actual}")
    
    if request.method == 'POST':
        print(f"\n=== POST recibido ===")
        print(f"POST data: {dict(request.POST)}")
        
        try:
            # Actualizar talla de polera
            nueva_talla = request.POST.get('polera_talla', '').strip()
            if nueva_talla:
                kit.polera_talla = nueva_talla
                print(f"Nueva talla: {nueva_talla}")
            
            # Actualizar número de polera
            polera_numero = request.POST.get('polera_numero', '').strip()
            if polera_numero:
                try:
                    kit.polera_numero_id = int(polera_numero)
                    print(f"Nuevo número: {polera_numero}")
                except ValueError:
                    kit.polera_numero_id = None
                    print("Número inválido, se establece a None")
            
            # Procesar entrega item por item verificando stock por color/talla
            prev_polera = kit.polera_entregada
            prev_pañoleta = kit.pañoleta_entregada
            prev_credencial = kit.credencial_entregada
            prev_manilla = kit.manilla_entregada

            req_polera = 'polera_entregada' in request.POST
            req_pañoleta = 'pañoleta_entregada' in request.POST
            req_credencial = 'credencial_entregada' in request.POST
            req_manilla = 'manilla_entregada' in request.POST

            print(f"Solicitud entrega:")
            print(f"- Polera requested: {req_polera} (prev {prev_polera})")
            print(f"- Pañoleta requested: {req_pañoleta} (prev {prev_pañoleta})")
            print(f"- Credencial requested: {req_credencial} (prev {prev_credencial})")
            print(f"- Manilla requested: {req_manilla} (prev {prev_manilla})")

            errors = []
            delivered = []

            # Color del grupo (para artículos por color)
            grupo_color = inscripcion.grupo.color_hex if inscripcion.grupo else None

            # ========== POLERA ==========
            if req_polera and not prev_polera:
                # Necesitamos talla y color
                talla = nueva_talla or kit.polera_talla
                if not grupo_color:
                    errors.append('No hay color de grupo asignado para la polera.')
                elif not talla:
                    errors.append('No se indicó talla de polera.')
                else:
                    # Usar transacción y lock para evitar asignaciones simultáneas
                    try:
                        with transaction.atomic():
                            polera_inv = InventarioGlobal.objects.select_for_update().filter(
                                articulo='polera',
                                color_hex__iexact=grupo_color,
                                talla__iexact=talla,
                                stock_actual__gt=0
                            ).first()

                            if polera_inv:
                                # Obtener siguiente número de forma segura (inicio en 1)
                                current_next = polera_inv.siguiente_numero or 1
                                assigned_number = current_next if current_next >= 1 else 1

                                # Validar rango (1..60)
                                if assigned_number > 60:
                                    errors.append(f"Se alcanzó el tope de numeración (60) para color {grupo_color}.")
                                else:
                                    # Incrementar siguiente_numero y decrementar stock de forma atómica
                                    polera_inv.siguiente_numero = F('siguiente_numero') + 1
                                    polera_inv.stock_actual = F('stock_actual') - 1
                                    polera_inv.save()
                                    polera_inv.refresh_from_db()

                                    kit.polera_numero_id = assigned_number
                                    kit.polera_entregada = True
                                    kit.polera_talla = talla
                                    kit.pañoleta_color = grupo_color if not kit.pañoleta_color else kit.pañoleta_color
                                    delivered.append('polera')
                                    print(f"Polera entregada: inv_id={polera_inv.id} numero={assigned_number} ({talla}, {grupo_color})")
                            else:
                                errors.append(f'No hay stock de polera talla {talla} color {grupo_color}.')
                    except Exception as ex:
                        errors.append('Error al asignar polera: ' + str(ex))
            else:
                # Mantener estado previo o aplicar desmarcado si el usuario lo hizo
                kit.polera_entregada = req_polera

            # ========== PAÑOLETA ==========
            if req_pañoleta and not prev_pañoleta:
                if not grupo_color:
                    errors.append('No hay color de grupo asignado para la pañoleta.')
                else:
                    pano_inv = InventarioGlobal.objects.filter(
                        articulo='pañoleta',
                        color_hex__iexact=grupo_color,
                        stock_actual__gt=0
                    ).first()

                    if pano_inv:
                        updated = InventarioGlobal.objects.filter(pk=pano_inv.pk, stock_actual__gt=0).update(stock_actual=F('stock_actual') - 1)
                        if updated:
                            kit.pañoleta_entregada = True
                            kit.pañoleta_color = grupo_color
                            delivered.append('pañoleta')
                            print(f"Pañoleta entregada: {pano_inv.id} ({grupo_color})")
                        else:
                            errors.append(f'No hay stock disponible (otro proceso lo usó) para pañoleta color {grupo_color}.')
                    else:
                        errors.append(f'No hay stock de pañoleta color {grupo_color}.')
            else:
                kit.pañoleta_entregada = req_pañoleta

            # ========== CREDENCIAL ==========
            if req_credencial and not prev_credencial:
                cred_inv = InventarioGlobal.objects.filter(
                    articulo='credencial',
                    stock_actual__gt=0
                ).first()

                if cred_inv:
                    updated = InventarioGlobal.objects.filter(pk=cred_inv.pk, stock_actual__gt=0).update(stock_actual=F('stock_actual') - 1)
                    if updated:
                        kit.credencial_entregada = True
                        delivered.append('credencial')
                        print(f"Credencial entregada: {cred_inv.id}")
                    else:
                        errors.append('No hay stock disponible de credenciales (otro proceso lo usó).')
                else:
                    errors.append('No hay stock de credenciales.')
            else:
                kit.credencial_entregada = req_credencial

            # ========== MANILLA ==========
            if req_manilla and not prev_manilla:
                if not grupo_color:
                    errors.append('No hay color de grupo asignado para la manilla.')
                else:
                    man_inv = InventarioGlobal.objects.filter(
                        articulo='manilla',
                        color_hex__iexact=grupo_color,
                        stock_actual__gt=0
                    ).first()

                    if man_inv:
                        updated = InventarioGlobal.objects.filter(pk=man_inv.pk, stock_actual__gt=0).update(stock_actual=F('stock_actual') - 1)
                        if updated:
                            kit.manilla_entregada = True
                            kit.manilla_color = grupo_color
                            delivered.append('manilla')
                            print(f"Manilla entregada: {man_inv.id} ({grupo_color})")
                        else:
                            errors.append(f'No hay stock disponible (otro proceso lo usó) para manilla color {grupo_color}.')
                    else:
                        errors.append(f'No hay stock de manilla color {grupo_color}.')
            else:
                kit.manilla_entregada = req_manilla
            
            # Verificar si todos o al menos uno de los elementos fueron entregados
            todos_entregados = all([
                kit.polera_entregada,
                kit.pañoleta_entregada,
                kit.credencial_entregada,
                kit.manilla_entregada
            ])

            alguno_entregado = any([
                kit.polera_entregada,
                kit.pañoleta_entregada,
                kit.credencial_entregada,
                kit.manilla_entregada
            ])

            # Actualizar fecha de entrega si al menos un elemento fue entregado
            # (las poleras pueden entregarse después, no esperamos que TODOS estén entregados)
            if alguno_entregado:
                if not kit.fecha_entrega:
                    kit.fecha_entrega = timezone.now()
                    print(f"Fecha entrega establecida (parcial/completo): {kit.fecha_entrega}")
                if request.user.is_authenticated and not kit.entregado_por:
                    kit.entregado_por = request.user
                    print(f"Entregado por: {request.user}")
            
            # Actualizar colores del kit si están vacíos
            if inscripcion.grupo:
                if not kit.pañoleta_color:
                    kit.pañoleta_color = inscripcion.grupo.color_hex
                if not kit.manilla_color:
                    kit.manilla_color = inscripcion.grupo.color_hex

            # Guardar cambios del kit
            kit.save()
            print(f"✅ Kit {kit.id} guardado exitosamente")

            # Si no se pudo entregar nada por falta de stock, devolver error
            if errors and not delivered:
                return JsonResponse({
                    'success': False,
                    'error': 'No se pudo entregar ningún artículo',
                    'errors': errors
                }, status=400)

            # Si hubo entregas mixtas, devolver advertencias junto al éxito
            resp = {
                'success': True,
                'message': '✅ Kit actualizado correctamente',
                'kit_id': kit.id,
                'actualizaciones': {
                    'polera_entregada': kit.polera_entregada,
                    'pañoleta_entregada': kit.pañoleta_entregada,
                    'credencial_entregada': kit.credencial_entregada,
                    'manilla_entregada': kit.manilla_entregada,
                    'polera_talla': kit.polera_talla,
                    'polera_numero': kit.polera_numero_id,
                    'completo': todos_entregados
                }
            }

            if errors:
                resp['warnings'] = errors

            return JsonResponse(resp)
            
        except Exception as e:
            import traceback
            error_details = traceback.format_exc()
            print(f"❌ Error al guardar kit: {error_details}")
            
            return JsonResponse({
                'success': False,
                'error': f'Error al guardar: {str(e)}',
                'error_details': error_details
            }, status=400)
    
    # Contexto para GET request
    context = {
        'kit': kit,
        'inscripcion': inscripcion,
        'color_polera_actual': color_polera_actual,
        'stock_color_actual': stock_color_actual,
        'stock_pañoleta_color': stock_pañoleta_color,
        'stock_credencial': stock_credencial,
        'stock_manilla_color': stock_manilla_color,
    }
    
    print("=== Enviando contexto al template ===")
    return render(request, 'principal/modal_editar_kit.html', context)

def toggle_estado_kit(request, kit_id, campo):
    """Toggle rápido de estado de kit (AJAX)"""
    if request.method == 'POST' and request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        kit = get_object_or_404(LogisticaKit, id=kit_id)
        
        # Campos válidos para toggle (excluir polera_entregada porque necesita talla/número)
        campos_validos = ['pañoleta_entregada', 'credencial_entregada', 'manilla_entregada']
        
        if campo in campos_validos:
            valor_actual = getattr(kit, campo)
            nuevo_valor = not valor_actual

            # Si se intenta marcar como entregado (nuevo_valor == True), verificar stock
            if nuevo_valor:
                grupo_color = kit.inscripcion.grupo.color_hex if kit.inscripcion and kit.inscripcion.grupo else None

                if campo == 'pañoleta_entregada':
                    if not grupo_color:
                        return JsonResponse({'success': False, 'error': 'Sin color asignado para pañoleta'}, status=400)
                    inv = InventarioGlobal.objects.filter(articulo='pañoleta', color_hex__iexact=grupo_color, stock_actual__gt=0).first()
                    if not inv:
                        return JsonResponse({'success': False, 'error': f'No hay stock de pañoleta color {grupo_color}'}, status=400)
                    updated = InventarioGlobal.objects.filter(pk=inv.pk, stock_actual__gt=0).update(stock_actual=F('stock_actual') - 1)
                    if not updated:
                        return JsonResponse({'success': False, 'error': f'No hay stock disponible (otro proceso lo usó) para pañoleta color {grupo_color}'}, status=400)
                    kit.pañoleta_color = grupo_color

                if campo == 'manilla_entregada':
                    if not grupo_color:
                        return JsonResponse({'success': False, 'error': 'Sin color asignado para manilla'}, status=400)
                    inv = InventarioGlobal.objects.filter(articulo='manilla', color_hex__iexact=grupo_color, stock_actual__gt=0).first()
                    if not inv:
                        return JsonResponse({'success': False, 'error': f'No hay stock de manilla color {grupo_color}'}, status=400)
                    updated = InventarioGlobal.objects.filter(pk=inv.pk, stock_actual__gt=0).update(stock_actual=F('stock_actual') - 1)
                    if not updated:
                        return JsonResponse({'success': False, 'error': f'No hay stock disponible (otro proceso lo usó) para manilla color {grupo_color}'}, status=400)
                    kit.manilla_color = grupo_color

                if campo == 'credencial_entregada':
                    inv = InventarioGlobal.objects.filter(articulo='credencial', stock_actual__gt=0).first()
                    if not inv:
                        return JsonResponse({'success': False, 'error': 'No hay stock de credenciales'}, status=400)
                    updated = InventarioGlobal.objects.filter(pk=inv.pk, stock_actual__gt=0).update(stock_actual=F('stock_actual') - 1)
                    if not updated:
                        return JsonResponse({'success': False, 'error': 'No hay stock disponible de credenciales (otro proceso lo usó)'}, status=400)

            # Si se intenta marcar como NO entregado (nuevo_valor == False), devolver al inventario
            else:
                if campo == 'pañoleta_entregada' and kit.pañoleta_color:
                    inv = InventarioGlobal.objects.filter(articulo='pañoleta', color_hex__iexact=kit.pañoleta_color).first()
                    if inv:
                        InventarioGlobal.objects.filter(pk=inv.pk).update(stock_actual=F('stock_actual') + 1)

                if campo == 'manilla_entregada' and kit.manilla_color:
                    inv = InventarioGlobal.objects.filter(articulo='manilla', color_hex__iexact=kit.manilla_color).first()
                    if inv:
                        InventarioGlobal.objects.filter(pk=inv.pk).update(stock_actual=F('stock_actual') + 1)

                if campo == 'credencial_entregada':
                    inv = InventarioGlobal.objects.filter(articulo='credencial').first()
                    if inv:
                        InventarioGlobal.objects.filter(pk=inv.pk).update(stock_actual=F('stock_actual') + 1)

            setattr(kit, campo, nuevo_valor)

            # Actualizar fecha si se marca como entregado
            if nuevo_valor:  # Si ahora será True
                if not kit.fecha_entrega:
                    kit.fecha_entrega = timezone.now()

            kit.save()

            return JsonResponse({
                'success': True,
                'campo': campo,
                'nuevo_valor': nuevo_valor,
                'mensaje': f'{campo.replace("_", " ").title()} actualizado'
            })
        
        return JsonResponse({'error': 'Campo no válido'}, status=400)
    
    return JsonResponse({'error': 'Método no permitido'}, status=405)

@login_required
def marcar_kit_completo(request, kit_id):
    """Marcar un kit como completamente entregado"""
    if request.method == 'POST':
        kit = get_object_or_404(LogisticaKit, id=kit_id)
        
        kit.polera_entregada = True
        kit.pañoleta_entregada = True
        kit.credencial_entregada = True
        kit.manilla_entregada = True
        kit.fecha_entrega = timezone.now()
        kit.save()
        
        messages.success(request, f'✅ Kit marcado como COMPLETO para {kit.inscripcion.nombre_persona}')
        
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({'success': True})
        
        return redirect('gestion_kits_completa')
    
    return redirect('gestion_kits_completa')

# ============ VISTAS DEPRECADAS (las mantenemos por compatibilidad) ============

@login_required
def historial_kits(request):
    """Redirige a la nueva vista unificada"""
    return redirect('gestion_kits_completa')

@login_required 
def gestion_kits(request):
    """Redirige a la nueva vista unificada"""
    return redirect('gestion_kits_completa')

@login_required
def entregar_kit_completo(request, kit_id):
    """Redirige a la nueva función"""
    return marcar_kit_completo(request, kit_id)

@login_required
def detalle_kit(request, kit_id):
    """Vista simple para ver detalles (opcional)"""
    kit = get_object_or_404(LogisticaKit, id=kit_id)
    return render(request, 'principal/detalle_kit.html', {'kit': kit})

@login_required
def estadisticas_kits_api(request):
    """API para obtener estadísticas (opcional)"""
    kits = LogisticaKit.objects.all()
    
    total_kits = kits.count()
    kits_completos = kits.filter(
        polera_entregada=True,
        pañoleta_entregada=True,
        credencial_entregada=True,
        manilla_entregada=True
    ).count()
    
    kits_parciales = kits.filter(
        Q(polera_entregada=True) | Q(pañoleta_entregada=True) | 
        Q(credencial_entregada=True) | Q(manilla_entregada=True)
    ).exclude(
        polera_entregada=True,
        pañoleta_entregada=True,
        credencial_entregada=True,
        manilla_entregada=True
    ).count()
    
    kits_pendientes = total_kits - kits_completos - kits_parciales
    
    return JsonResponse({
        'total_kits': total_kits,
        'kits_completos': kits_completos,
        'kits_parciales': kits_parciales,
        'kits_pendientes': kits_pendientes,
        'timestamp': timezone.now().isoformat()
    })


# ============ CRUD DE DEVOCIONALES ============
@require_role('campamentista', 'inscripcion', 'director', 'admin', 'lider', 'pastor')
def listar_devocionales(request):
    """Listar todos los devocionales"""
    from .models import Devocional
    devocionales = Devocional.objects.all().order_by('-fecha')
    return render(request, 'principal/devocional_lista.html', {'devocionales': devocionales})


@require_role('pastor', 'admin')
def crear_devocional(request):
    """Crear un nuevo devocional"""
    from .models import Devocional
    
    if request.method == 'POST':
        # Procesar formulario
        titulo = request.POST.get('titulo', '')
        mensaje = request.POST.get('mensaje', '')
        cita_biblica = request.POST.get('cita_biblica', '')
        
        if titulo and mensaje:
            devocional = Devocional.objects.create(
                pastor=request.user,
                titulo=titulo,
                mensaje=mensaje,
                cita_biblica=cita_biblica,
            )
            messages.success(request, 'Devocional creado exitosamente.')
            return redirect('listar_devocionales')
        else:
            messages.error(request, 'El título y mensaje son requeridos.')
    
    return render(request, 'principal/devocional_crear.html')