# processors/process_o.py
# -*- coding: utf-8 -*-
import sympy
import traceback
# Usar las nuevas utilidades
from .processor_utils import get_sympy_representation
from .symbol_manager import SymbolManager

SCL_SUFFIX = "_sympy_processed" # Nuevo sufijo

def process_o(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data):
    """Genera la expresión SymPy para la operación lógica O (OR)."""
    instr_uid = instruction["instruction_uid"]
    instr_type_original = instruction.get("type", "O")
    if instr_type_original.endswith(SCL_SUFFIX) or "_error" in instr_type_original:
        return False

    # Buscar todas las entradas 'in', 'in1', 'in2', ...
    input_pins = sorted([pin for pin in instruction.get("inputs", {}) if pin.startswith("in")])

    if not input_pins:
        print(f"Error: O {instr_uid} sin pines de entrada (inX).")
        instruction["scl"] = f"// ERROR: O {instr_uid} sin pines inX"
        instruction["type"] = instr_type_original + "_error"
        return True

    sympy_parts = []
    all_resolved = True
    missing_deps = []
    
    for pin in input_pins:
        input_info = instruction["inputs"][pin]
        sympy_expr = get_sympy_representation(input_info, network_id, sympy_map, symbol_manager)

        if sympy_expr is None:
            all_resolved = False
            missing_deps.append(pin)
            # Continue checking other pins instead of breaking immediately
            continue

        # Optimización: No incluir FALSE en un OR
        if sympy_expr != sympy.false:
             sympy_parts.append(sympy_expr)

    if not all_resolved:
        # More detailed debug info
        # print(f"DEBUG: O {instr_uid} esperando pines {missing_deps}")
        return False # Esperar dependencias

    # Enhanced handling: If all inputs are FALSE or no valid inputs, result is FALSE
    if not sympy_parts:
        result_sympy_expr = sympy.false
    elif len(sympy_parts) == 1:
        # Optimization: OR with single input is just the input
        result_sympy_expr = sympy_parts[0]
    else:
        # Use sympy.Or for multiple inputs
        result_sympy_expr = sympy.Or(*sympy_parts)
        
    # Optional: Apply simplification
    try:
        result_sympy_expr = sympy.simplify_logic(result_sympy_expr, force=False)
    except Exception as e:
        # If simplification fails, use original expression
        # print(f"DEBUG: O {instr_uid} simplification failed: {e}")
        pass


    # Guardar la expresión SymPy resultante en el mapa para 'out'
    map_key_out = (network_id, instr_uid, "out")
    sympy_map[map_key_out] = result_sympy_expr

    # Marcar como procesado, SCL principal es solo comentario
    instruction["scl"] = f"// SymPy O: {result_sympy_expr}" # Comentario opcional
    instruction["type"] = instr_type_original + SCL_SUFFIX
    # La instrucción 'O' no tiene ENO propio, propaga el resultado por 'out'
    return True

# --- Processor Information Function ---
def get_processor_info():
    """Devuelve la información para la operación lógica O (OR)."""
    return {'type_name': 'o', 'processor_func': process_o, 'priority': 1}