import sys

from grnexus import NeuralNetwork
from lib.grnexus_text_proccessing import *
import random

print("=" * 100)
print("TEST: CARGAR Y USAR MODELOS DE RUBY EN PYTHON")
print("=" * 100)

# ============================================================================
# TEST 1: CARGAR MODELO DE GENERACIÓN DE TEXTO DE RUBY
# ============================================================================
print("\n[TEST 1] CARGAR MODELO DE GENERACIÓN DE TEXTO (Ruby -> Python)")
print("-" * 100)

try:
    text_model = NeuralNetwork.load('ruby/test/text_generator_ruby.nexus')
    print("[OK] Modelo de texto cargado exitosamente desde Ruby")
    
    # Inspeccionar
    print("\nInspeccionando modelo:")
    NeuralNetwork.inspect_model('ruby/test/text_generator_ruby.nexus')
    
    # Hacer predicciones
    print("Haciendo predicciones con el modelo de Ruby...")
    test_inputs = [[float(i)] for i in range(5)]
    predictions = text_model.predict(test_inputs)
    print(f"  Predicciones realizadas: {len(predictions)} muestras")
    print(f"  Forma de salida: {len(predictions[0])} clases")
    
    print("\n[OK] Test 1 completado")
except Exception as e:
    print(f"[ERROR] Test 1 falló: {e}")

# ============================================================================
# TEST 2: CARGAR MODELO DE SENTIMIENTOS DE RUBY
# ============================================================================
print("\n[TEST 2] CARGAR MODELO DE ANÁLISIS DE SENTIMIENTOS (Ruby -> Python)")
print("-" * 100)

try:
    sentiment_model = NeuralNetwork.load('ruby/test/sentiment_analyzer_ruby.nexus')
    print("[OK] Modelo de sentimientos cargado exitosamente desde Ruby")
    
    # Inspeccionar
    NeuralNetwork.inspect_model('ruby/test/sentiment_analyzer_ruby.nexus')
    
    # Hacer predicciones con vectores aleatorios
    print("\nHaciendo predicciones...")
    vocab_size = sentiment_model.layers[0].input_dim
    test_vectors = [[random.random() for _ in range(vocab_size)] for _ in range(5)]
    predictions = sentiment_model.predict(test_vectors)
    
    for i, pred in enumerate(predictions):
        sentiment = "POSITIVO" if pred[0] > pred[1] else "NEGATIVO"
        confidence = max(pred) * 100
        print(f"  Muestra {i+1}: {sentiment} ({confidence:.2f}%)")
    
    print("\n[OK] Test 2 completado")
except Exception as e:
    print(f"[ERROR] Test 2 falló: {e}")

# ============================================================================
# TEST 3: CARGAR MODELO PROFUNDO DE RUBY
# ============================================================================
print("\n[TEST 3] CARGAR MODELO PROFUNDO (Ruby -> Python)")
print("-" * 100)

try:
    deep_model = NeuralNetwork.load('ruby/test/deep_model_ruby.nexus')
    print("[OK] Modelo profundo cargado exitosamente desde Ruby")
    
    # Inspeccionar
    NeuralNetwork.inspect_model('ruby/test/deep_model_ruby.nexus')
    
    # Verificar arquitectura
    print(f"\nArquitectura cargada:")
    print(f"  Total de capas: {len(deep_model.layers)}")
    print(f"  Parámetros totales: {deep_model.count_params()['total']}")
    print(f"  Parámetros entrenables: {deep_model.count_params()['trainable']}")
    
    # Hacer predicciones
    test_data = [[random.random() * 10 - 5 for _ in range(20)] for _ in range(10)]
    predictions = deep_model.predict(test_data)
    print(f"\n  Predicciones realizadas: {len(predictions)} muestras")
    print(f"  Forma de salida: {len(predictions[0])} valores")
    
    print("\n[OK] Test 3 completado")
except Exception as e:
    print(f"[ERROR] Test 3 falló: {e}")

# ============================================================================
# TEST 4: CARGAR MODELO CON CALLBACKS DE RUBY
# ============================================================================
print("\n[TEST 4] CARGAR MODELO CON CALLBACKS (Ruby -> Python)")
print("-" * 100)

try:
    callbacks_model = NeuralNetwork.load('ruby/test/complex_callbacks_ruby.nexus')
    print("[OK] Modelo con callbacks cargado exitosamente desde Ruby")
    
    # Inspeccionar
    NeuralNetwork.inspect_model('ruby/test/complex_callbacks_ruby.nexus')
    
    # Continuar entrenamiento en Python
    print("\nContinuando entrenamiento en Python...")
    x_train = [[random.random() for _ in range(15)] for _ in range(50)]
    y_train = []
    for _ in range(50):
        label = random.randint(0, 3)
        y_train.append([1.0 if i == label else 0.0 for i in range(4)])
    
    history = callbacks_model.train(x_train, y_train, epochs=5, batch_size=10, verbose=False)
    print(f"  Entrenamiento adicional completado")
    print(f"  Loss final: {history['loss'][-1]:.4f}")
    print(f"  Accuracy final: {history['accuracy'][-1]:.2f}%")
    
    # Guardar modelo actualizado
    callbacks_model.save('python/test/callbacks_continued_python.nexus')
    print("\n  Modelo actualizado guardado: python/test/callbacks_continued_python.nexus")
    
    print("\n[OK] Test 4 completado")
except Exception as e:
    print(f"[ERROR] Test 4 falló: {e}")

# ============================================================================
# TEST 5: CREAR MODELO EN PYTHON Y COMPARAR
# ============================================================================
print("\n[TEST 5] CREAR MODELO EN PYTHON PARA COMPARACIÓN")
print("-" * 100)

from lib.grnexus_layers import *
from lib.grnexus_activations import *
from lib.grnexus_normalization import *

# Crear modelo similar en Python
python_model = NeuralNetwork(
    loss='cross_entropy',
    optimizer='sgd',
    learning_rate=0.05,
    name='python_native_model'
)

python_model.add(DenseLayer(128, 25, activation=GELU()))
python_model.add(BatchNormLayer())
python_model.add(DropoutLayer(rate=0.25))
python_model.add(DenseLayer(64, 128, activation=Swish()))
python_model.add(BatchNormLayer())
python_model.add(DenseLayer(32, 64, activation=Mish()))
python_model.add(DenseLayer(10, 32, activation=Softmax()))

print("Modelo nativo de Python creado:")
python_model.summary()

# Entrenar
x_py = [[random.random() for _ in range(25)] for _ in range(150)]
y_py = []
for _ in range(150):
    label = random.randint(0, 9)
    y_py.append([1.0 if i == label else 0.0 for i in range(10)])

print("\nEntrenando modelo nativo de Python...")
history_py = python_model.train(x_py, y_py, epochs=30, batch_size=20, verbose=False)

print(f"Entrenamiento completado:")
print(f"  Loss inicial: {history_py['loss'][0]:.4f}")
print(f"  Loss final: {history_py['loss'][-1]:.4f}")
print(f"  Accuracy final: {history_py['accuracy'][-1]:.2f}%")

# Guardar
python_model.save('python/test/python_native_model.nexus')
print("\nModelo guardado: python/test/python_native_model.nexus")

print("\n[OK] Test 5 completado")

# ============================================================================
# TEST 6: PROCESAMIENTO DE TEXTO EN PYTHON
# ============================================================================
print("\n[TEST 6] PROCESAMIENTO DE TEXTO AVANZADO EN PYTHON")
print("-" * 100)

# Crear corpus
documents = [
    "machine learning is fascinating and powerful",
    "deep learning neural networks are amazing",
    "artificial intelligence transforms the world",
    "natural language processing enables communication",
    "computer vision recognizes images accurately",
    "reinforcement learning trains intelligent agents"
]

print(f"Corpus: {len(documents)} documentos")

# Crear vocabulario
vocab = Vocabulary(documents, max_vocab_size=200)
print(f"Vocabulario: {vocab.size} tokens únicos")
print(f"Tokens totales: {vocab.total_tokens}")

# Vectorizar
vectorizer = TextVectorizer(vocab)
vectors = [vectorizer.vectorize(doc) for doc in documents]
print(f"\nVectores TF-IDF generados: {len(vectors)} vectores")
print(f"Dimensión: {len(vectors[0])}")

# Crear modelo de clasificación de documentos
doc_model = NeuralNetwork(
    loss='cross_entropy',
    optimizer='sgd',
    learning_rate=0.1,
    name='document_classifier'
)

doc_model.add(DenseLayer(64, vocab.size, activation=ReLU()))
doc_model.add(DropoutLayer(rate=0.3))
doc_model.add(DenseLayer(32, 64, activation=Tanh()))
doc_model.add(DenseLayer(3, 32, activation=Softmax()))

# Crear labels sintéticos (3 categorías)
labels = [
    [1, 0, 0],  # ML
    [1, 0, 0],  # DL
    [0, 1, 0],  # AI
    [0, 1, 0],  # NLP
    [0, 0, 1],  # CV
    [0, 0, 1]   # RL
]

print("\nEntrenando clasificador de documentos...")
history_doc = doc_model.train(vectors, labels, epochs=100, batch_size=2, verbose=False)

print(f"Entrenamiento completado:")
print(f"  Accuracy final: {history_doc['accuracy'][-1]:.2f}%")

# Probar con nuevo documento
test_doc = "neural networks and deep learning"
test_vec = vectorizer.vectorize(test_doc)
prediction = doc_model.predict([test_vec])[0]
predicted_class = prediction.index(max(prediction))
confidence = max(prediction) * 100

print(f"\nPredicción para '{test_doc}':")
print(f"  Clase: {predicted_class}")
print(f"  Confianza: {confidence:.2f}%")

doc_model.save('python/test/document_classifier_python.nexus')
print("\nModelo guardado: python/test/document_classifier_python.nexus")

print("\n[OK] Test 6 completado")

# ============================================================================
# RESUMEN FINAL
# ============================================================================
print("\n" + "=" * 100)
print("RESUMEN DE COMPATIBILIDAD CRUZADA")
print("=" * 100)

print("\n[OK] TEST 1: Modelo de texto de Ruby cargado y usado en Python")
print("[OK] TEST 2: Modelo de sentimientos de Ruby cargado y usado en Python")
print("[OK] TEST 3: Modelo profundo de Ruby cargado y usado en Python")
print("[OK] TEST 4: Modelo con callbacks de Ruby continuado en Python")
print("[OK] TEST 5: Modelo nativo de Python creado y entrenado")
print("[OK] TEST 6: Procesamiento de texto avanzado en Python")

print("\nMODELOS PYTHON GENERADOS:")
print("  1. python/test/callbacks_continued_python.nexus")
print("  2. python/test/python_native_model.nexus")
print("  3. python/test/document_classifier_python.nexus")

print("\n" + "=" * 100)
print("COMPATIBILIDAD RUBY -> PYTHON VERIFICADA EXITOSAMENTE")
print("=" * 100)
