# processors/process_timer.py
# -*- coding: utf-8 -*-
import sympy
import traceback
# Usar las nuevas utilidades
from .processor_utils import get_sympy_representation, sympy_expr_to_scl, format_variable_name, get_target_scl_name
from .symbol_manager import SymbolManager, extract_plc_variable_name

SCL_SUFFIX = "_sympy_processed"

def process_timer(instruction, network_id, sympy_map, symbol_manager: SymbolManager, data):
    """
    Genera SCL para Temporizadores (TON, TOF) directamente.
    Requiere datos de instancia.
    """
    instr_uid = instruction["instruction_uid"]
    instr_type_original = instruction.get("type", "").replace(SCL_SUFFIX,"").replace("_error","") # TON o TOF
    if instruction.get("type","").endswith(SCL_SUFFIX) or "_error" in instruction.get("type",""):
        return False

    scl_timer_type = instr_type_original.upper()
    if scl_timer_type not in ["TON", "TOF"]:
         instruction["scl"] = f"// ERROR: Tipo de temporizador directo no soportado: {instr_type_original}"
         instruction["type"] = instr_type_original + "_error"
         return True

    # 1. Obtener Inputs: IN, PT, y nombre de instancia (implícito o explícito)
    in_info = instruction["inputs"].get("IN")
    pt_info = instruction["inputs"].get("PT")
    # Buscar instancia: ¿está en inputs? ¿o como instance_db?
    instance_plc_name = instruction.get("instance_db") # Buscar primero aquí
    if not instance_plc_name:
        # Si no, buscar un input llamado 'timer' o similar? No estándar.
        # Asumir que debe estar declarado como STAT si no hay instance_db
        instance_plc_name = instruction.get("instance_name") # Nombre directo?
        if not instance_plc_name:
            instance_plc_name = f"#{scl_timer_type}_INSTANCE_{instr_uid}" # Placeholder final
            print(f"Advertencia: No se encontró nombre/instancia para {instr_type_original} UID {instr_uid}. Usando placeholder '{instance_plc_name}'.")


    sympy_in_expr = get_sympy_representation(in_info, network_id, sympy_map, symbol_manager)
    sympy_or_const_pt = get_sympy_representation(pt_info, network_id, sympy_map, symbol_manager)

    # Verificar dependencias
    if sympy_in_expr is None or sympy_or_const_pt is None or instance_plc_name is None:
        return False

    # Formatear nombre de instancia
    instance_name_scl = format_variable_name(instance_plc_name)

    # Convertir entradas SymPy/Constante a SCL strings
    in_scl = sympy_expr_to_scl(sympy_in_expr, symbol_manager)
    pt_scl = sympy_expr_to_scl(sympy_or_const_pt, symbol_manager)

    # Generar la llamada SCL
    scl_call = f"{instance_name_scl}(IN := {in_scl}, PT := {pt_scl}); // TODO: Declarar {instance_name_scl} : {scl_timer_type};"

    # Actualizar instrucción
    instruction["scl"] = scl_call # SCL final generado
    instruction["type"] = instr_type_original + SCL_SUFFIX

    # 7. Actualizar sympy_map para las salidas Q y ET
    map_key_q = (network_id, instr_uid, "Q") # Pin estándar SCL
    # *** Store SymPy Symbol for boolean output Q ***
    q_output_scl_access = f"{instance_name_scl}.Q" # String for SCL access
    sympy_q_symbol = symbol_manager.get_symbol(q_output_scl_access) # Get/Create Symbol
    if sympy_q_symbol:
        sympy_map[map_key_q] = sympy_q_symbol # Store the SYMBOL
    else:
        print(f"Error: Could not create symbol for {q_output_scl_access} in {instr_type_original} {instr_uid}")
        sympy_map[map_key_q] = None

    map_key_et = (network_id, instr_uid, "ET") # Pin estándar SCL
    # ET is TIME, store SCL access string
    sympy_map[map_key_et] = f"{instance_name_scl}.ET"

    return True

# --- Processor Information Function ---
def get_processor_info():
    """Devuelve info para TON y TOF directos."""
    return [
        {'type_name': 'ton', 'processor_func': process_timer, 'priority': 5},
        {'type_name': 'tof', 'processor_func': process_timer, 'priority': 5}
    ]