import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 1. Citirea și pregătirea datelor
print("Citire fișier...")
with open('datebinare.txt', 'r') as f:
    data_str = f.read().strip()  # Citește tot conținutul ca string

# Convertire la array de biți (elimină spații, newline-uri; presupune '0' și '1')
data = np.array([int(bit) for bit in data_str if bit in ['0', '1']])

print(f'Lungime șir: {len(data)}')
print(f'Exemplu primii 20 biți: {data[:20]}')

# Parametri model
sequence_length = 10  # Lungime secvență input (poți schimba)
X, y = [], []
for i in range(len(data) - sequence_length):
    X.append(data[i:i + sequence_length])
    y.append(data[i + sequence_length])

X, y = np.array(X), np.array(y)
X = X.reshape((X.shape[0], X.shape[1], 1))  # Reshape pentru LSTM (samples, timesteps, features)

print(f'Număr sample-uri: {len(X)}')

# Split: 80% train, 20% test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, shuffle=False)  # shuffle=False pentru secvențe temporale

print(f'Train: {len(X_train)}, Test: {len(X_test)}')

# 2. Construire model LSTM
model = Sequential([
    LSTM(50, input_shape=(sequence_length, 1), return_sequences=True),  # Primul LSTM cu return sequences
    LSTM(50),  # Al doilea LSTM
    Dense(1, activation='sigmoid')  # Output: probabilitate 0/1
])

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

print("Model construit:")
model.summary()

# 3. Antrenare
epochs = 20  # Poți crește pentru mai multă antrenare
batch_size = 32
history = model.fit(
    X_train, y_train,
    epochs=epochs,
    batch_size=batch_size,
    validation_split=0.1,  # 10% din train ca validare
    verbose=1  # Afișează progresul
)

# 4. Evaluare
test_loss, test_accuracy = model.evaluate(X_test, y_test, verbose=0)
print(f'\nAcuratețe pe setul de test: {test_accuracy:.4f} (față de 0.5 în aleatoriu pur)')

# Predicții pe tot setul de test (pentru acuratețe detaliată)
y_pred_prob = model.predict(X_test)
y_pred = (y_pred_prob > 0.5).astype(int).flatten()
detailed_accuracy = accuracy_score(y_test, y_pred)
print(f'Acuratețe detaliată (threshold 0.5): {detailed_accuracy:.4f}')

# 5. Exemplu predicții (primii 5 din test)
print('\nExemplu predicții pe primii 5 din test:')
for i in range(5):
    input_seq = X_test[i].flatten()
    pred = y_pred[i]
    real = y_test[i]
    print(f'Input: {input_seq} -> Predicție: {pred} (real: {real})')

# Salvează modelul (opțional)
model.save('model_predict_bit.h5')
print("\nModel salvat ca 'model_predict_bit.h5'. Poți încărca cu: model = tf.keras.models.load_model('model_predict_bit.h5')")

# Plot istoric (opțional, pentru vizualizare loss/accuracy)
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Val Loss')
plt.title('Loss')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(history.history['accuracy'], label='Train Acc')
plt.plot(history.history['val_accuracy'], label='Val Acc')
plt.title('Accuracy')
plt.legend()
plt.show()
