from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse, JsonResponse
from django.contrib import messages
from django.template.loader import render_to_string
from django.views.generic import ListView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from xhtml2pdf import pisa
from django.conf import settings
from .models import InventarioAdministrativo, InventarioTactico, Directores, Subjefes, Unidades, AsignacionAdministrativa, AsignadaUnidadAdministrativa, AsignacionTactica, AsignadaUnidadTactica
from .forms import InventarioAdministrativoForm, InventarioTacticoForm, DirectoresForm, SubjefesForm, UnidadForm, AsignacionAdministrativaForm, AsignacionTacticaForm
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import LoginView
import reportlab.graphics.barcode.code128
import reportlab.graphics.barcode.code39



class CustomLoginView(LoginView):
    template_name = 'registration/login.html'
    redirect_authenticated_user = True

    def form_valid(self, form):
        response = super().form_valid(form)
        # Reiniciar el timer al hacer login
        if hasattr(self.request, 'session'):
            self.request.session.modified = True
        return response

    def form_invalid(self, form):
        messages.error(self.request, 'Usuario o contraseña incorrectos')
        return super().form_invalid(form)
    

# Vista principal
@login_required
def principal(request):

    vehiculos_administrativos_count = InventarioAdministrativo.objects.count()
    vehiculos_tacticos_count = InventarioTactico.objects.count()
    unidades_count = Unidades.objects.count()
    
    request.session.modified = True
    request.session.set_expiry(settings.SESSION_COOKIE_AGE)
    
    
    context = {
        'vehiculos_administrativos_count': vehiculos_administrativos_count,
        'vehiculos_tacticos_count': vehiculos_tacticos_count,
        'unidades_count': unidades_count,
        'session_timeout': settings.SESSION_COOKIE_AGE,
        'warning_time': settings.WARNING_TIME,
    }
    
    return render(request, 'principal/principal.html', context)


@login_required
def obtener_datos(request):
    vehiculos_administrativos_count = InventarioAdministrativo.objects.count()
    vehiculos_tacticos_count = InventarioTactico.objects.count()
    unidades_count = Unidades.objects.count()
    
    data = {
        'vehiculos_administrativos': vehiculos_administrativos_count,
        'vehiculos_tacticos': vehiculos_tacticos_count,
        'unidades': unidades_count,
    }
    
    return JsonResponse(data)

# Vistas genéricas para Directores
@method_decorator(login_required, name='dispatch')
class DirectoresListView(ListView):
    model = Directores
    template_name = 'directores/directores.html'
    context_object_name = 'directores'

@method_decorator(login_required, name='dispatch')
class DirectoresCreateView(CreateView):
    model = Directores
    form_class = DirectoresForm
    template_name = 'directores/crear.html'
    success_url = reverse_lazy('listar_directores')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Director registrado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response

@method_decorator(login_required, name='dispatch')
class DirectoresUpdateView(UpdateView):
    model = Directores
    form_class = DirectoresForm
    template_name = 'directores/editar.html'
    success_url = reverse_lazy('listar_directores')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Director actualizado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response

@method_decorator(login_required, name='dispatch')
class DirectoresDeleteView(DeleteView):
    model = Directores
    template_name = 'directores/eliminar_director.html'
    success_url = reverse_lazy('listar_directores')

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.delete()
        messages.success(request, 'Director eliminado con éxito.')
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return redirect(self.success_url)

# Vistas genéricas para Subjefes
@method_decorator(login_required, name='dispatch')
class SubjefesListView(ListView):
    model = Subjefes
    template_name = 'jefes/jefes.html'
    context_object_name = 'subjefes'

@method_decorator(login_required, name='dispatch')
class SubjefesCreateView(CreateView):
    model = Subjefes
    form_class = SubjefesForm
    template_name = 'jefes/crear.html'
    success_url = reverse_lazy('listar_subjefes')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Grupo registrado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response

@method_decorator(login_required, name='dispatch')
class SubjefesUpdateView(UpdateView):
    model = Subjefes
    form_class = SubjefesForm
    template_name = 'jefes/editar.html'
    success_url = reverse_lazy('listar_subjefes')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Grupo actualizado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response

@method_decorator(login_required, name='dispatch')
class SubjefesDeleteView(DeleteView):
    model = Subjefes
    template_name = 'jefes/eliminar_subjefe.html'
    success_url = reverse_lazy('listar_subjefes')

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.delete()
        messages.success(request, 'Grupo eliminado con éxito.')
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return redirect(self.success_url)


# Vistas genéricas para Inventario Administrativo
@method_decorator(login_required, name='dispatch')
class InventarioAdministrativoListView(ListView):
    model = InventarioAdministrativo
    template_name = 'inventario_administrativo/listar.html'
    context_object_name = 'inventarios'

@method_decorator(login_required, name='dispatch')
class InventarioAdministrativoCreateView(CreateView):
    model = InventarioAdministrativo
    form_class = InventarioAdministrativoForm
    template_name = 'inventario_administrativo/crear.html'
    success_url = reverse_lazy('listar_inventario_administrativo')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Vehículo administrativo registrado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response

@method_decorator(login_required, name='dispatch')
class InventarioAdministrativoUpdateView(UpdateView):
    model = InventarioAdministrativo
    form_class = InventarioAdministrativoForm
    template_name = 'inventario_administrativo/editar.html'
    success_url = reverse_lazy('listar_inventario_administrativo')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Vehículo administrativo actualizado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response


@method_decorator(login_required, name='dispatch')
class InventarioAdministrativoDeleteView(DeleteView):
    model = InventarioAdministrativo
    template_name = 'inventario_administrativo/eliminacion.html'
    success_url = reverse_lazy('listar_inventario_administrativo')

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.delete()
        messages.success(request, 'Vehículo administrativo eliminado con éxito.')
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return redirect(self.success_url)


# Vistas genéricas para Inventario Táctico
@method_decorator(login_required, name='dispatch')
class InventarioTacticoListView(ListView):
    model = InventarioTactico
    template_name = 'inventario_tactico/listar.html'
    context_object_name = 'inventarios'



@method_decorator(login_required, name='dispatch')
class InventarioTacticoCreateView(CreateView):
    model = InventarioTactico
    form_class = InventarioTacticoForm
    template_name = 'inventario_tactico/crear.html'
    success_url = reverse_lazy('listar_inventario_tactico')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Vehículo táctico registrado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response



@method_decorator(login_required, name='dispatch')
class InventarioTacticoUpdateView(UpdateView):
    model = InventarioTactico
    form_class = InventarioTacticoForm
    template_name = 'inventario_tactico/editar.html'
    success_url = reverse_lazy('listar_inventario_tactico')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Vehículo táctico actualizado con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response



@method_decorator(login_required, name='dispatch')
class InventarioTacticoDeleteView(DeleteView):
    model = InventarioTactico
    template_name = 'inventario_tactico/eliminar.html'
    success_url = reverse_lazy('listar_inventario_tactico')

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.delete()
        messages.success(request, 'Vehículo táctico eliminado con éxito.')
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return redirect(self.success_url)



# Vistas genéricas para Unidades
@method_decorator(login_required, name='dispatch')
class UnidadListView(ListView):
    model = Unidades
    template_name = 'unidad/listar.html'
    context_object_name = 'unidades'

@method_decorator(login_required, name='dispatch')
class UnidadCreateView(CreateView):
    model = Unidades
    form_class = UnidadForm
    template_name = 'unidad/crear.html'
    success_url = reverse_lazy('unidad_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Unidad registrada con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response

@method_decorator(login_required, name='dispatch')
class UnidadUpdateView(UpdateView):
    model = Unidades
    form_class = UnidadForm
    template_name = 'unidad/editar.html'
    success_url = reverse_lazy('unidad_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, 'Unidad actualizada con éxito.')
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return response

@method_decorator(login_required, name='dispatch')
class UnidadDeleteView(DeleteView):
    model = Unidades
    template_name = 'unidad/eliminar.html'
    success_url = reverse_lazy('unidad_list')

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.delete()
        messages.success(request, 'Unidad eliminada con éxito.')
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('OK')
        return redirect(self.success_url)


@login_required
def eliminar_asignacion_admin(request, pk):
    asignacion = get_object_or_404(AsignadaUnidadAdministrativa, pk=pk)
    vehiculo = asignacion.vehiculo
    vehiculo.asignado = False  # Liberar el vehículo
    vehiculo.save()
    asignacion.delete()
    messages.success(request, "Vehículo administrativo liberado exitosamente.")
    return redirect('detalle', id=asignacion.unidad.id)


@login_required
def eliminar_asignacion_tactica(request, pk):
    asignacion = get_object_or_404(AsignadaUnidadTactica, pk=pk)
    vehiculo = asignacion.vehiculo
    vehiculo.asignado = False  # Liberar el vehículo
    vehiculo.save()
    asignacion.delete()
    messages.success(request, "Vehículo táctico liberado exitosamente.")
    return redirect('detalle', id=asignacion.unidad.id)


# Asignación Administrativa
@login_required
def asignacion_administrativa(request):
    administrativos = AsignacionAdministrativa.objects.all()
    if request.method == 'POST':
        form = AsignacionAdministrativaForm(request.POST)
        if form.is_valid():
            unidad = form.cleaned_data['unidad']
            directores = form.cleaned_data['directores']
            jefes = form.cleaned_data['jefes']
            comprobante = form.cleaned_data['comprobante']
            vehiculos = form.cleaned_data['vehiculos']
            precios = request.POST.getlist('precios')

            if len(vehiculos) != len(precios):
                messages.error(request, "Debes ingresar un precio para cada vehículo seleccionado.")
            else:
                asignaciones = []
                for vehiculo, precio in zip(vehiculos, precios):
                    try:
                        precio_decimal = float(precio)
                        asignacion = AsignacionAdministrativa(
                            unidad=unidad,
                            directores=directores,
                            jefes=jefes,
                            vehiculo=vehiculo,
                            comprobante=comprobante,
                            precio=precio_decimal
                        )
                        asignacion.save()
                        asignaciones.append(asignacion)
                    except ValueError:
                        messages.error(request, f"Precio inválido para {vehiculo}: '{precio}'")
                        break
                else:
                    messages.success(request, f"{len(asignaciones)} asignación(es) registrada(s) con éxito.")
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return HttpResponse('OK')
            return redirect('asignacion_administrativa')
    else:
        form = AsignacionAdministrativaForm()

    context = {'form': form, 'administrativos': administrativos}
    return render(request, 'asignacion_administrativa/index.html', context)


@login_required
def eliminar_todo(request):
    if request.method == 'POST':
        asignaciones = AsignacionAdministrativa.objects.all()
        for asignacion in asignaciones:
            # Crear registro histórico
            AsignadaUnidadAdministrativa.objects.create(
                unidad=asignacion.unidad,
                directores=asignacion.directores,
                jefes=asignacion.jefes,
                vehiculo=asignacion.vehiculo,
                fecha_creacion=asignacion.fecha_creacion,
                comprobante=asignacion.comprobante,
                precio=asignacion.precio
            )
            # Marcar como no reasignable
            vehiculo = asignacion.vehiculo
            vehiculo.asignado = True  # Mantener como asignado permanentemente
            vehiculo.save()
        AsignacionAdministrativa.objects.all().delete()
        messages.success(request, "Todas las asignaciones han sido archivadas.")
        return redirect('asignacion_administrativa')


@login_required
def generar_pdf(request):
    asignaciones = AsignacionAdministrativa.objects.all()
    if asignaciones.exists():
        unidad = asignaciones.first().unidad
        director = asignaciones.first().directores
        jefe = asignaciones.first().jefes
    else:
        unidad = director = jefe = None
        html_string = render_to_string('pdf/pdf_asinacion.html', {
            'asignaciones': [],
            'jefe': None,
            'director': None,
            'unidad_nombre': "Sin Unidad",
        })
        response = HttpResponse(content_type='application/pdf')
        response['Content-Disposition'] = 'attachment; filename="asignacion_administrativa.pdf"'
        pisa.CreatePDF(html_string, dest=response)
        messages.info(request, "No hay asignaciones para generar el PDF.")
        return response

    html_string = render_to_string('pdf/pdf_asinacion.html', {
        'asignaciones': asignaciones,
        'jefe': jefe,
        'director': director,
        'unidad_nombre': unidad.nombre if unidad else "Sin Unidad",
    })

    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="asignacion_administrativa.pdf"'
    pisa_status = pisa.CreatePDF(html_string, dest=response)
    
    if pisa_status.err:
        return HttpResponse('Error al generar el PDF.')
    
    messages.success(request, "PDF generado con éxito.")
    return response

# Asignación Táctica
@login_required
def asignacion_tactica(request):
    asignaciones = AsignacionTactica.objects.all()
    if request.method == 'POST':
        form = AsignacionTacticaForm(request.POST)
        if form.is_valid():
            unidad = form.cleaned_data['unidad']
            directores = form.cleaned_data['directores']
            jefes = form.cleaned_data['jefes']
            comprobante = form.cleaned_data['comprobante']
            vehiculos = form.cleaned_data['vehiculos']
            precios = request.POST.getlist('precios')

            if len(vehiculos) != len(precios):
                messages.error(request, "Debes ingresar un precio para cada vehículo seleccionado.")
            else:
                asignaciones_nuevas = []
                for vehiculo, precio in zip(vehiculos, precios):
                    try:
                        precio_decimal = float(precio)
                        asignacion = AsignacionTactica(
                            unidad=unidad,
                            directores=directores,
                            jefes=jefes,
                            vehiculo=vehiculo,
                            comprobante=comprobante,
                            precio=precio_decimal
                        )
                        asignacion.save()
                        asignaciones_nuevas.append(asignacion)
                    except ValueError:
                        messages.error(request, f"Precio inválido para {vehiculo}: '{precio}'")
                        break
                else:
                    messages.success(request, f"{len(asignaciones_nuevas)} asignación(es) registrada(s) con éxito.")
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return HttpResponse('OK')
            return redirect('asignacion_tactica')
    else:
        form = AsignacionTacticaForm()

    context = {'form': form, 'asignaciones': asignaciones}
    return render(request, 'asignacion_tactica/index.html', context)

@login_required
def eliminar_todo_tactico(request):
    if request.method == 'POST':
        asignaciones = AsignacionTactica.objects.all()
        for asignacion in asignaciones:
            AsignadaUnidadTactica.objects.create(
                unidad=asignacion.unidad,
                directores=asignacion.directores,
                jefes=asignacion.jefes,
                vehiculo=asignacion.vehiculo,
                fecha_creacion=asignacion.fecha_creacion,
                comprobante=asignacion.comprobante,
                precio=asignacion.precio
            )
            vehiculo = asignacion.vehiculo
            vehiculo.asignado = True  # Mantener como asignado permanentemente
            vehiculo.save()
        AsignacionTactica.objects.all().delete()
        messages.success(request, "Todas las asignaciones tácticas han sido archivadas.")
        return redirect('asignacion_tactica')

@login_required
def generar_pdf_tactico(request):
    asignaciones = AsignacionTactica.objects.all()
    if asignaciones.exists():
        unidad = asignaciones.first().unidad
        director = asignaciones.first().directores
        jefe = asignaciones.first().jefes
    else:
        unidad = director = jefe = None
        html_string = render_to_string('pdf/pdf_asignacion_tactica.html', {
            'asignaciones': [],
            'jefe': None,
            'director': None,
            'unidad_nombre': "Sin Unidad",
        })
        response = HttpResponse(content_type='application/pdf')
        response['Content-Disposition'] = 'attachment; filename="asignacion_tactica.pdf"'
        pisa.CreatePDF(html_string, dest=response)
        messages.info(request, "No hay asignaciones para generar el PDF.")
        return response

    html_string = render_to_string('pdf/pdf_asignacion_tactica.html', {
        'asignaciones': asignaciones,
        'jefe': jefe,
        'director': director,
        'unidad_nombre': unidad.nombre if unidad else "Sin Unidad",
    })

    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="asignacion_tactica.pdf"'
    pisa_status = pisa.CreatePDF(html_string, dest=response)
    
    if pisa_status.err:
        return HttpResponse('Error al generar el PDF.')
    
    messages.success(request, "PDF generado con éxito.")
    return response

# Detalle de Unidad
@login_required
def detalle_unidad(request, id):
    unidad = get_object_or_404(Unidades, id=id)
    administrativo = AsignadaUnidadAdministrativa.objects.filter(unidad=id)
    tactico = AsignadaUnidadTactica.objects.filter(unidad=id)
    context = {
        'unidad': unidad,
        'administrativo': administrativo,
        'tactico': tactico
    }
    return render(request, 'unidad/detalle.html', context)

# Generar PDF por Unidad (Administrativo o Táctico)
@login_required
def detalle_pdf(request, tipo, unidad_id):
    unidad = get_object_or_404(Unidades, pk=unidad_id)
    jefe = Subjefes.objects.first()
    director = Directores.objects.first()

    context = {
        'unidad_nombre': unidad.nombre,
        'jefe': jefe,
        'director': director,
        'tipo': tipo,
    }

    if tipo == 'administrativo':
        asignaciones = AsignadaUnidadAdministrativa.objects.filter(unidad=unidad)
        context['asignaciones'] = asignaciones
    elif tipo == 'tactico':
        asignaciones = AsignadaUnidadTactica.objects.filter(unidad=unidad)
        context['asignaciones'] = asignaciones
    else:
        messages.error(request, "Tipo no válido")
        return HttpResponse("Tipo no válido", status=400)

    html = render_to_string('pdf/administrativo.html', context)
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="reporte_{unidad.nombre}_{tipo}.pdf"'
    pisa_status = pisa.CreatePDF(html, dest=response, encoding='UTF-8')
    
    if pisa_status.err:
        messages.error(request, "Error al generar el PDF")
        return HttpResponse("Error al generar el PDF", status=500)
    
    messages.success(request, f"PDF de {tipo} generado con éxito para {unidad.nombre}")
    return response

def expired_page(request):
    return render(request, 'expired.html', status=403)