from django.contrib import admin

from django.contrib import admin, messages
from django.urls import path, reverse
from django.shortcuts import redirect, render, get_object_or_404
from django.utils.html import format_html
from django.core.exceptions import ValidationError
from django.forms import formset_factory
from django.utils import timezone

from .models import MovimientoPerdidaProceso, OrdenCompra, ItemOrdenCompra , DevolucionCompra , DevolucionMuestraComercial , DevolucionProduccion, AjusteInventarioFisico, MovimientoDevolucionVenta, MuestraComercial, RecepcionProduccion, MovimientoVenta
from .forms import DevolucionCompraForm


class ItemOrdenCompraInline(admin.TabularInline):
    model = ItemOrdenCompra
    extra = 1
    fields = (
        'referencia', 'cantidad', 'precio_unitario',
        'subtotal_admin', 'empaque', 'proveedor_referencia',
        'lead_time', 'certificado'
    )
    readonly_fields = ('subtotal_admin',)
    autocomplete_fields = ('referencia', 'proveedor_referencia')
    raw_id_fields = ('proveedor_referencia',)

    def subtotal_admin(self, instance):
        if instance.cantidad is not None and instance.precio_unitario is not None:
            return f"${instance.cantidad * instance.precio_unitario:,.2f}"
        return "$0.00"
    subtotal_admin.short_description = 'Subtotal'


@admin.register(OrdenCompra)
class OrdenCompraAdmin(admin.ModelAdmin):
    list_display = (
        'numero_orden',
        'proveedor_link',
        'fecha_creacion',
        'fecha_requerida',
        'estado',
        'total_orden',
        'acciones_personalizadas'
    )
    list_filter = ('estado', 'proveedor', 'fecha_creacion')
    search_fields = ('numero_orden', 'proveedor__nombre_empresa')
    date_hierarchy = 'fecha_creacion'
    inlines = [ItemOrdenCompraInline]
    actions = ['aprobar_ordenes', 'marcar_en_camino']
    readonly_fields = ('numero_orden', 'total_orden')

    def proveedor_link(self, obj):
        url = reverse('admin:proveedores_proveedor_change', args=[obj.proveedor.id])
        return format_html('<a href="{}">{}</a>', url, obj.proveedor)
    proveedor_link.short_description = 'Proveedor'
    proveedor_link.admin_order_field = 'proveedor'

    def total_orden(self, obj):
        return f"${obj.total:,.2f}"
    total_orden.short_description = 'Total'

    def acciones_personalizadas(self, obj):
        buttons = []
        if obj.estado == 'pendiente':
            buttons.append(f'<a href="{obj.id}/aprobar/" class="button">Aprobar</a>')
        elif obj.estado == 'aprobada':
            buttons.append(f'<a href="{obj.id}/enviar/" class="button">Enviar a Proveedor</a>')
        return format_html(' '.join(buttons))
    acciones_personalizadas.short_description = 'Acciones'

    def aprobar_ordenes(self, request, queryset):
        if not request.user.has_perm('compras.aprobar_ordencompra'):
            self.message_user(request, "No tienes permiso para aprobar órdenes", level=messages.ERROR)
            return
        count = queryset.filter(estado='pendiente').update(estado='aprobada')
        self.message_user(request, f"{count} órdenes aprobadas")
    aprobar_ordenes.short_description = "Aprobar órdenes seleccionadas"

    def marcar_en_camino(self, request, queryset):
        count = queryset.filter(estado='aprobada').update(estado='en_camino')
        self.message_user(request, f"{count} órdenes marcadas como enviadas")
    marcar_en_camino.short_description = "Marcar como enviadas a proveedor"

    def get_urls(self):
        urls = super().get_urls()
        custom = [
            # 1) interceptamos la ruta "add/" del admin
            path(
                'add/',
                self.admin_site.admin_view(self._redirect_to_manual),
                name='mov_compras_ordencompra_add'
            ),
            # 2) rutas de aprobar y enviar
            path(
                '<path:object_id>/aprobar/',
                self.admin_site.admin_view(self.aprobar_orden),
                name='mov_compras_ordencompra_aprobar'
            ),
            path(
                '<path:object_id>/enviar/',
                self.admin_site.admin_view(self.enviar_proveedor),
                name='mov_compras_ordencompra_enviar'
            ),
        ]
        return custom + urls

    def _redirect_to_manual(self, request):
        # Aquí redirige a tu URL de compras, no a ajuste de inventario
        return redirect('movimientos:ordencompra_manual')

    def aprobar_orden(self, request, object_id, *args, **kwargs):
        orden = self.get_object(request, object_id)
        try:
            orden.aprobar(request.user)
            self.message_user(request, "Orden aprobada exitosamente")
        except ValidationError as e:
            self.message_user(request, str(e), level=messages.ERROR)
        return redirect('..')

    def enviar_proveedor(self, request, object_id, *args, **kwargs):
        orden = self.get_object(request, object_id)
        orden.estado = 'en_camino'
        orden.save()
        self.message_user(request, "Orden marcada como enviada al proveedor")
        return redirect('..')


@admin.register(ItemOrdenCompra)
class ItemOrdenCompraAdmin(admin.ModelAdmin):
    list_display = ('orden', 'referencia', 'cantidad', 'precio_unitario', 'subtotal_admin')
    list_select_related = ('orden', 'referencia')
    search_fields = ('orden__numero_orden', 'referencia__sku')
    autocomplete_fields = ('referencia', 'proveedor_referencia')
    raw_id_fields = ('proveedor_referencia',)

    def subtotal_admin(self, obj):
        if obj.cantidad is not None and obj.precio_unitario is not None:
            return f"${obj.cantidad * obj.precio_unitario:,.2f}"
        return "$0.00"
    subtotal_admin.short_description = 'Subtotal'


@admin.register(DevolucionCompra)
class DevolucionCompraAdmin(admin.ModelAdmin):
    # Ruta a tu template override
    add_form_template = 'admin/devolucion_compras/add_form.html'
    change_list_template = None
    list_display = ('referencia', 'fecha', 'cantidad_devuelta', 'valor_total')

    def get_urls(self):
        urls = super().get_urls()
        # Reemplacemos la URL de “add/” por nuestra propia vista
        # Import or define devolver_orden_unificado at the top of the file if not already present
        from .views import devolver_orden_unificado  # Make sure this import is correct

        custom = [
        path(
                    'add/',
                    self.admin_site.admin_view(devolver_orden_unificado),
                    name='movimientos_devolucioncompra_add'
                    ),        ]
        return custom + urls

    def devolver_add(self, request):
        """Vista custom para el add de DevolucionCompra en el Admin."""
        # 1) Preparamos datos de las órdenes recibidas
        ordenes = OrdenCompra.objects.filter(estado='recibida').order_by('-fecha_creacion')

        # 2) Creamos un FormSet con tu DevolucionCompraForm, sin formularios extra
        DevolucionFormSet = formset_factory(DevolucionCompraForm, extra=0)

        orden_selected = request.GET.get('orden_select')
        formset        = None

        if request.method == 'POST':
            # Procesamos el POST del formset
            formset = DevolucionFormSet(request.POST)
            if formset.is_valid():
                creadas = 0
                for form in formset:
                    # Guardamos sólo si puso cantidad_devuelta > 0
                    if form.cleaned_data.get('cantidad_devuelta'):
                        form.save()   # tu save() calcula todo
                        creadas += 1
                messages.success(request, f"{creadas} devoluciones creadas correctamente.")
                return redirect(reverse('admin:movimientos_devolucioncompra_changelist'))

        elif orden_selected:
            # GET con orden_select → precargamos initial para cada ítem
            orden = get_object_or_404(OrdenCompra, pk=orden_selected)
            items = orden.items.select_related('referencia').all()

            initial = []
            for item in items:
                initial.append({
                    'item':                      item.pk,
                    'referencia':               item.referencia.pk,
                    'fecha':                    timezone.now().date(),
                    'cantidad_antes':           item.referencia.stock,
                    'precio_unitario_devuelto': item.precio_unitario,
                })
            formset = DevolucionFormSet(initial=initial)

        # 3) Renderizamos tu plantilla con el contexto que necesita
        context = {
            'ordenes':        ordenes,
            'orden_selected': orden_selected,
            'formset':        formset,
        }
        return render(request, self.add_form_template, context)

@admin.register(DevolucionMuestraComercial)
class DevolucionMuestraComercialAdmin(admin.ModelAdmin):
    list_display  = ('referencia', 'cantidad', 'fecha', 'usuario')
    search_fields = ('referencia__sku', 'usuario__username')
    list_filter   = ('fecha',)

    def add_view(self, request, form_url='', extra_context=None):
        return redirect('movimientos:dev_muestra_comercial_manual')


@admin.register(DevolucionProduccion)
class DevolucionProduccionAdmin(admin.ModelAdmin):
    list_display     = (
        'referencia', 'cantidad_devuelta', 'costo_unitario', 'stock_antes',
        'stock_despues', 'nuevo_precio_costo', 'valor_inventario', 'fecha'
    )
    readonly_fields  = (
        'stock_antes', 'stock_despues',
        'precio_costo_antes', 'nuevo_precio_costo', 'valor_inventario'
    )
    search_fields    = ('referencia__sku',)
    list_filter      = ('fecha',)

    def get_urls(self):
        urls = super().get_urls()
        custom = [
            path(
                'add/',
                self.admin_site.admin_view(self._redirect_add),
                name='mov_devolucion_produccion_devolucionproduccion_add'
            ),
        ]
        return custom + urls

    def _redirect_add(self, request):
        return redirect('movimientos:devolucion_produccion_manual')


@admin.register(MovimientoDevolucionVenta)
class MovimientoDevolucionVentaAdmin(admin.ModelAdmin):
    list_display  = ('referencia','cantidad','precio_venta_unitario','fecha')
    search_fields = ('referencia__sku',)
    list_filter   = ('fecha','referencia')

    def get_urls(self):
        urls = super().get_urls()
        custom = [
            path(
                'add/',
                self.admin_site.admin_view(self._redirect_add),
                name='mov_devolucion_venta_movimientodevolucionventa_add'
            ),
        ]
        return custom + urls

    def _redirect_add(self, request):
        return redirect('movimientos:devolucion_venta_manual')


@admin.register(AjusteInventarioFisico)
class AjusteInventarioFisicoAdmin(admin.ModelAdmin):
    list_display = (
        'referencia', 'fecha',
        'cantidad_antes', 'cantidad_despues',
        'unidades_entrada', 'unidades_salida',
        'valor_total'
    )
    readonly_fields = ('unidades_entrada', 'unidades_salida', 'valor_total')
    list_filter = ('fecha',)
    search_fields = ('referencia__sku',)

    def get_urls(self):
        # Primero obtenemos las URLs estándar del admin
        urls = super().get_urls()
        # Luego definimos nuestra ruta 'add/' que intercepta la petición de crear
        custom_urls = [
            path(
                'add/',
                self.admin_site.admin_view(self._redirect_to_manual),
                name='mov_inventario_fisico_ajusteinventariofisico_add',
            ),
        ]
        # Devolvemos primero nuestra ruta, luego las estándar
        return custom_urls + urls

    def _redirect_to_manual(self, request):
        # Redirige al nombre de la ruta que definimos en urls.py
        return redirect('movimientos:ajuste_manual')

@admin.register(MuestraComercial)
class MuestraComercialAdmin(admin.ModelAdmin):
    list_display = (
        'referencia', 'fecha', 'cantidad_entregada',
        'costo_unitario', 'valor_total_salida', 'entregado_por'
    )
    readonly_fields = (
        'stock_antes', 'stock_despues',
        'costo_unitario', 'valor_total_salida'
    )
    search_fields = ('referencia__sku', 'entregado_por__username')
    list_filter = ('fecha',)

    def get_urls(self):
        urls = super().get_urls()
        custom = [
            path(
                'add/',
                self.admin_site.admin_view(self._redirect_add),
                name='mov_muestra_comercial_muestracomercial_add'
            ),
        ]
        return custom + urls

    def _redirect_add(self, request):
        # Redirige al formulario manual
        return redirect('movimientos:muestra_comercial_manual')

@admin.register(RecepcionProduccion)
class RecepcionProduccionAdmin(admin.ModelAdmin):
    list_display = (
        'referencia', 'planta', 'maquina', 'fecha',
        'cantidad_producida', 'costo_unitario_produccion',
        'nuevo_costo_ponderado', 'cantidad_despues'
    )
    readonly_fields = ('cantidad_despues', 'nuevo_costo_ponderado', 'valor_total')
    list_filter = ('fecha', 'planta', 'maquina')
    search_fields = ('referencia__sku', 'maquina__nombre')

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path(
                'add/',
                self.admin_site.admin_view(self._redirect_add),
                name='mov_produccion_recepcionproduccion_add'
            ),
        ]
        return custom_urls + urls

    def _redirect_add(self, request):
        return redirect('movimientos:recepcion_produccion_manual')

@admin.register(MovimientoVenta)
class MovimientoVentaAdmin(admin.ModelAdmin):
    list_display  = ('referencia', 'cantidad', 'precio_unitario_venta', 'fecha', 'creado_por')
    search_fields = ('referencia__sku',)
    list_filter   = ('fecha', 'referencia')

    # Cuando el usuario haga clic en “Add” en el changelist, le redirigimos a la vista manual
    def add_view(self, request, form_url='', extra_context=None):
        return redirect('movimientos:venta_manual')

@admin.register(MovimientoPerdidaProceso)
class MovimientoPerdidaProcesoAdmin(admin.ModelAdmin):
    list_display = ('referencia', 'cantidad', 'fecha', 'motivo')
    list_filter = ('fecha', 'referencia')
    search_fields = ('referencia__sku', 'motivo')
    date_hierarchy = 'fecha'

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('add/', self.admin_site.admin_view(self.redirect_to_custom_add), name='movimientos_movimientoperdidaproceso_add'),
        ]
        return custom_urls + urls

    def redirect_to_custom_add(self, request):
        return redirect('movimientos:perdida_add')