from core.models.listener import eventAfterSave, _DB_INSTANCE
from project.models.production.image import Image
from project.models.production.measurement import Measurement
from project.models.production.object import Object
from project.models.production.locationlog import Locationlog
from flask_sqlalchemy import SQLAlchemy 

# El registro de handlers (ejemplo, ajusta según tu implementación real)
_POST_SAVE_REGISTRY = {} 

def update_qty_img(object_instance: Object):
    """
    Recalcula la cantidad de imágenes para un objeto específico.
    """
    db = _DB_INSTANCE
    if db is None:
        print("!!! Error: La instancia de DB no está disponible en update_qty_img.")
        return

    try:
        # ------------------------------------------------------------------
        # 1. Recálculo de Cantidad Total y por Calidad (HD / SD)
        # ------------------------------------------------------------------
        
        # Conteo de imágenes HD (highDefinition == True)
        new_qty_hd = db.session.query(Image).filter(
            Image.object_id == object_instance.id,
            Image.highDefinition == True
        ).count()

        # Conteo de imágenes SD (highDefinition == False o NULL, asumiendo NULL es SD)
        new_qty_sd = db.session.query(Image).filter(
            Image.object_id == object_instance.id,
            Image.highDefinition != True
        ).count()
        
        new_qty_total = new_qty_hd + new_qty_sd
        
        # ------------------------------------------------------------------
        # 2. Actualización de Qty Total y por Calidad
        # ------------------------------------------------------------------
        
        if object_instance.qtyImage != new_qty_total:
            object_instance.qtyImage = new_qty_total
            print(f"  -> Object ID {object_instance.id}: QtyImage actualizado a {new_qty_total}")
            
        if object_instance.qtyHD != new_qty_hd:
            object_instance.qtyHD = new_qty_hd
            print(f"  -> Object ID {object_instance.id}: QtyHD actualizado a {new_qty_hd}")
            
        if object_instance.qtySD != new_qty_sd:
            object_instance.qtySD = new_qty_sd
            print(f"  -> Object ID {object_instance.id}: QtySD actualizado a {new_qty_sd}")


        # ------------------------------------------------------------------
        # 3. Actualización de Imagen Destacada (featuredImage)
        # ------------------------------------------------------------------
        
        # Obtenemos la primera imagen, que ya está ordenada por 'position'
        # Usamos .first() para obtener una sola imagen, o None si no hay
        featured_image = db.session.query(Image).filter(
            Image.object_id == object_instance.id
        ).order_by(Image.position).first()
        
        # Determinamos el ID de la nueva imagen destacada (None si no hay imágenes)
        new_featured_id = featured_image.image_id if featured_image else None
        
        # Verificamos si el valor necesita ser actualizado
        if object_instance.featuredImage_id != new_featured_id:
            object_instance.featuredImage_id = new_featured_id
            print(f"  -> Object ID {object_instance.id}: featuredImage actualizado a {new_featured_id}")
        else:
            print(f"  -> Object ID {object_instance.id}: featuredImage sin cambio.")
    except Exception as e:
        # Usa el ID del objeto para un mejor registro de errores
        print(f"Error en el listener (update_qty_img) para Object ID {object_instance.id}: {e}")

def update_last_location(object_instance: Object):
    """
    Recalcula la cantidad de imágenes para un objeto específico.
    """
    db = _DB_INSTANCE
    if db is None:
        print("!!! Error: La instancia de DB no está disponible en update_qty_img.")
        return

    try:
        # Usamos .first() para obtener una sola imagen, o None si no hay
        last_location = db.session.query(Locationlog).filter(
            Locationlog.object_id == object_instance.id
        ).order_by(Locationlog.fromDate.desc()).first()

        # Determinamos el ID de la nueva imagen destacada (None si no hay imágenes)
        location_id = last_location.location_id if last_location else None
        if location_id is not None:
            #enlace = f"<a href='/admin/18/{location_id}/'>{last_location.__repr__()}</a>"
            enlace = f"{last_location.__repr__()}"
            if last_location.fromDate:
                enlace += f" (Desde: {last_location.fromDate.strftime('%Y-%m-%d')})"
        
            # Verificamos si el valor necesita ser actualizado
            if object_instance.lastLocation != enlace:
                object_instance.lastLocation = enlace
                print(f"  -> Object ID {object_instance.id}: lastLocation actualizado a {enlace}")
            else:
                print(f"  -> Object ID {object_instance.id}: lastLocation sin cambio.")
    except Exception as e:
        # Usa el ID del objeto para un mejor registro de errores
        print(f"Error en el listener (update_qty_img) para Object ID {object_instance.id}: {e}")

def update_measurements(object_instance: Object):
    """
    Recalcula la cantidad de imágenes para un objeto específico.
    """
    db = _DB_INSTANCE
    if db is None:
        print("!!! Error: La instancia de DB no está disponible en update_qty_img.")
        return

    try:
        # ------------------------------------------------------------------
        # 1. Recálculo de Measurements
        # ------------------------------------------------------------------
        
        # Conteo de imágenes HD (highDefinition == True)
        measurements = db.session.query(Measurement).filter(
            Measurement.object_id == object_instance.id
        )

        # ------------------------------------------------------------------
        # 2. Actualización de Qty Total y por Calidad
        # ------------------------------------------------------------------
        if measurements:
            output = ""
            for measurement in measurements:
                output += "<p>"
                if measurement.item:
                    output += f"<b>{measurement.item}:</b> ["
                else:
                    output += "<b>Medida:</b> ["
                if measurement.width:
                    output += f"{measurement.width} (Ancho) "
                if measurement.height:
                    output += f"{measurement.height} (Alto) "
                if measurement.withFrame:
                    output += f"- (Con marco) - "
                if measurement.units:
                    units = ""
                    if measurement.units == "2":
                        units = "En centímetros"
                    elif measurement.units == "3":
                        units = "En milímetros"
                    elif measurement.units == "4":
                        units = "En pulgadas"
                    elif measurement.units == "1":
                        units = "En metros"
                    output += f"{units}, "
                if measurement.exactApprox:
                    exact = ""
                    if measurement.exactApprox == "1":
                        exact = "Medida exacta"
                    else:
                        exact = "Medida aproximada"
                    output += f"{exact}, "
                if measurement.circumference:
                    output += f"Circunferencia: {measurement.circumference}, "
                if measurement.contour:
                    output += f"Contorno: {measurement.contour}, "
                if measurement.diameter:
                    output += f"Diámetro: {measurement.diameter}, "
                if measurement.outsideSize:
                    output += f"Exterior: {measurement.outsideSize}, "
                if measurement.insideSize:
                    output += f"Interior: {measurement.insideSize}, "
                if measurement.thickness:
                    output += f"Grosor: {measurement.thickness}, "
                if measurement.depth:
                    output += f"Profundidad: {measurement.depth}, "
                if measurement.length:
                    output += f"Largo: {measurement.length}, "
                if measurement.size:
                    output += f"Tamaño: {measurement.size}, "
                if measurement.volume:
                    output += f"Volumen: {measurement.volume}, "
                if measurement.weight:
                    output += f"Peso: {measurement.weight}, "
                if measurement.weightUnit:
                    output += f"Unidad de Peso: {measurement.weightUnit}, "
                if measurement.other:
                    output += f"Otro: {measurement.other}"
                output += "</p>"
        # Verificamos si el valor necesita ser actualizado
        if object_instance.allMeasurements != output:
            object_instance.allMeasurements = output
            print(f"  -> Object ID {object_instance.id}: allMeasurements actualizado a {output}")
        else:
            print(f"  -> Object ID {object_instance.id}: allMeasurements sin cambio.")
    except Exception as e:
        # Usa el ID del objeto para un mejor registro de errores
        print(f"Error en el listener (update_qty_img) para Object ID {object_instance.id}: {e}")

# --- 2. Registro de Eventos ---
eventAfterSave(ParentModel=Object, ChildModel=Image, handler_function=update_qty_img)
eventAfterSave(ParentModel=Object, ChildModel=Measurement, handler_function=update_measurements)
eventAfterSave(ParentModel=Object, ChildModel=Locationlog, handler_function=update_last_location)