# gestion_usuarios/views.py

import csv
import io

from django.contrib import messages
from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse_lazy
from django.views.generic import (
    ListView, DetailView, CreateView, UpdateView, DeleteView
)
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Usuario
from gestion_equipos.forms import FileUploadForm, ActaFirmadaUploadForm
from gestion_equipos.models import ActaConsolidada, HistorialMovimiento

# ==========================================================
# VISTAS BASADAS EN CLASE PARA GESTIÓN DE USUARIOS
# ==========================================================

class UsuarioListView(LoginRequiredMixin, ListView):
    model = Usuario
    template_name = 'gestion_usuarios/listar_usuarios.html'
    context_object_name = 'usuarios_list'  # Cambiado para evitar conflictos con el objeto de la página
    paginate_by = 10  # Define cuántos usuarios mostrar por página

    def get_queryset(self):
        # Permite filtrar usuarios por nombre, apellido, email o cargo
        query = self.request.GET.get('q', '')
        queryset = super().get_queryset().order_by('nombre')
        if query:
            queryset = queryset.filter(
                Q(nombre__icontains=query) |
                Q(apellido__icontains=query) |
                Q(email__icontains=query) |
                Q(cargo__icontains=query)
            ).distinct()
        return queryset

    def get_context_data(self, **kwargs):
        # Añade el término de búsqueda y el objeto de paginación al contexto
        context = super().get_context_data(**kwargs)
        context['query'] = self.request.GET.get('q', '')
        
        # Lógica de paginación
        queryset = self.get_queryset()
        paginator = Paginator(queryset, self.paginate_by)
        page = self.request.GET.get('page')

        try:
            usuarios_paginados = paginator.page(page)
        except PageNotAnInteger:
            usuarios_paginados = paginator.page(1)
        except EmptyPage:
            usuarios_paginados = paginator.page(paginator.num_pages)
        
        context['usuarios'] = usuarios_paginados  # El objeto de la página es ahora 'usuarios'
        
        return context

class UsuarioCreateView(LoginRequiredMixin, CreateView):
    """
    Vista para crear un nuevo usuario.
    """
    model = Usuario
    fields = ['nombre', 'apellido', 'email', 'telefono']
    template_name = 'gestion_usuarios/crear_editar_usuario.html'
    success_url = reverse_lazy('gestion_usuarios:listar_usuarios')

class UsuarioDetailView(LoginRequiredMixin, DetailView):
    """
    Muestra el detalle de un usuario, sus asignaciones y actas.
    Permite subir actas firmadas.
    """
    model = Usuario
    template_name = 'gestion_usuarios/detalle_usuario.html'
    context_object_name = 'usuario'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        usuario_actual = self.get_object()
        context['asignaciones_activas'] = usuario_actual.asignaciones.filter(activa=True).select_related('equipo')
        context['historial_actas'] = ActaConsolidada.objects.filter(usuario=usuario_actual).order_by('-fecha_generacion')
        return context

    def post(self, request, *args, **kwargs):
        """
        Maneja la subida del formulario del acta firmada desde la misma página de detalle.
        """
        acta_pk = request.POST.get('acta_pk')
        if not acta_pk:
            messages.error(request, "No se pudo identificar el acta a actualizar.")
            return redirect(request.path_info)

        acta = get_object_or_404(ActaConsolidada, pk=acta_pk)
        form = ActaFirmadaUploadForm(request.POST, request.FILES, instance=acta)

        if form.is_valid():
            form.save()
            HistorialMovimiento.objects.create(
                usuario=request.user,
                accion=f"Subió el acta consolidada firmada '{acta.identificador}'"
            )
            messages.success(request, 'El acta firmada se ha subido correctamente.')
        else:
            messages.error(request, 'Hubo un error al subir el archivo. Por favor, inténtalo de nuevo.')

        return redirect(request.path_info) 

class UsuarioUpdateView(LoginRequiredMixin, UpdateView):
    """
    Permite editar los datos de un usuario.
    """
    model = Usuario
    fields = ['nombre', 'apellido', 'email', 'telefono']
    template_name = 'gestion_usuarios/crear_editar_usuario.html'
    success_url = reverse_lazy('gestion_usuarios:listar_usuarios')

class UsuarioDeleteView(LoginRequiredMixin, DeleteView):
    """
    Permite eliminar un usuario.
    """
    model = Usuario
    template_name = 'gestion_usuarios/usuario_confirm_delete.html'
    success_url = reverse_lazy('gestion_usuarios:listar_usuarios')
    success_message = "¡Usuario eliminado correctamente!"

# ==========================================================
# VISTAS BASADAS EN FUNCIÓN PARA IMPORTACIÓN Y DESCARGA MASIVA
# ==========================================================

def importar_usuarios_masivamente(request):
    """
    Permite importar usuarios desde un archivo CSV.
    Valida, crea o actualiza usuarios y muestra mensajes de éxito o error.
    """
    if request.method == 'POST':
        form = FileUploadForm(request.POST, request.FILES)
        if form.is_valid():
            csv_file = request.FILES['file']
            if not csv_file.name.endswith('.csv'):
                messages.error(request, '¡Error! El archivo debe tener formato .csv')
            else:
                try:
                    decoded_file = csv_file.read().decode('utf-8-sig')
                    io_string = io.StringIO(decoded_file)
                    reader = csv.DictReader(io_string, delimiter=';')

                    usuarios_creados = 0
                    usuarios_actualizados = 0
                    log_errores = []

                    for i, row in enumerate(reader, 2):
                        email = row.get('email', '').strip()
                        if not email:
                            log_errores.append(f"Fila {i}: Falta el email, que es obligatorio.")
                            continue

                        try:
                            data = {
                                'nombre': row.get('nombre', '').strip(),
                                'apellido': row.get('apellido', '').strip(),
                                'cargo': row.get('cargo', '').strip(),
                                'telefono': row.get('telefono', '').strip(),
                            }

                            obj, created = Usuario.objects.update_or_create(
                                email=email,
                                defaults=data
                            )
                            if created:
                                usuarios_creados += 1
                            else:
                                usuarios_actualizados += 1

                        except Exception as e:
                            log_errores.append(f"Fila {i} (Email: {email}): {e}")

                    # Mensajes según resultado de la importación
                    if not log_errores:
                        messages.success(
                            request,
                            f'¡Carga completada! Usuarios creados: {usuarios_creados}, Actualizados: {usuarios_actualizados}.'
                        )
                    else:
                        messages.warning(
                            request,
                            f'Carga finalizada con errores. Creados: {usuarios_creados}, Actualizados: {usuarios_actualizados}, Errores: {len(log_errores)}.'
                        )
                        for error in log_errores[:5]:
                            messages.error(request, error)

                    # Registrar movimiento en historial
                    HistorialMovimiento.objects.create(
                        usuario=request.user,
                        accion=f"Carga masiva de usuarios. Creados: {usuarios_creados}, Actualizados: {usuarios_actualizados}, Errores: {len(log_errores)}."
                    )

                except Exception as e:
                    messages.error(request, f"Error crítico al procesar el archivo: {e}")

            form = FileUploadForm()
    else:
        form = FileUploadForm()

    context = {
        'form': form,
        'titulo_pagina': 'Carga Masiva de Usuarios'
    }
    return render(request, 'gestion_usuarios/importar_usuarios.html', context)

def descargar_plantilla_usuarios_csv(request):
    """
    Permite descargar una plantilla CSV para la carga masiva de usuarios.
    """
    response = HttpResponse(
        content_type='text/csv',
        headers={'Content-Disposition': 'attachment; filename="plantilla_usuarios.csv"'},
    )
    response.write(u'\ufeff'.encode('utf8'))  # BOM para Excel
    writer = csv.writer(response, delimiter=';')

    headers = ['nombre', 'apellido', 'email', 'cargo', 'telefono']
    writer.writerow(headers)
    example_row = ['Juan', 'Perez', 'juan.perez@ejemplo.com', 'Desarrollador', '3101234567']
    writer.writerow(example_row)

    return response
