import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_absolute_percentage_error, mean_squared_error  # Added
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt

# File path and data settings
file_path = r"C:\Users\jack8\OneDrive\stock cow ai\data\stock price.csv"
features = ['Opening Price', 'Highest Price', 'Lowest Price', 'Closing Price']
target = 'Closing Price'

# Read and preprocess the CSV file
df = pd.read_csv(file_path, parse_dates=['Date'])
df = df.sort_values('Date')

# Scale data
scaler = MinMaxScaler()
scaled_data = scaler.fit_transform(df[features])

# Convert the data into sequences for LSTM input
def create_sequences(data, seq_length):
    x, y = [], []
    for i in range(len(data) - seq_length):
        x.append(data[i:i+seq_length])
        y.append(data[i+seq_length, features.index(target)])
    return np.array(x), np.array(y)

# Define sequence length (e.g., 40 days)
seq_length = 40  # Changed from 60 to match your code
x, y = create_sequences(scaled_data, seq_length)

# Split data into training and testing sets
train_size = int(0.8 * len(x))
x_train, x_test = x[:train_size], x[train_size:]
y_train, y_test = y[:train_size], y[train_size:]

# Build the LSTM model
model = Sequential([
    LSTM(25, return_sequences=True, input_shape=(x_train.shape[1], x_train.shape[2])),
    LSTM(25),
    Dense(1)
])

# Compile the model
model.compile(optimizer=Adam(learning_rate=0.001), loss='mean_squared_error')

# Train the model
early_stop = EarlyStopping(monitor='val_loss', patience=5)
history = model.fit(
    x_train, y_train,
    validation_data=(x_test, y_test),
    epochs=100,
    batch_size=32,
    callbacks=[early_stop],
    verbose=1
)

# Predict and inverse scale the predictions
predicted = model.predict(x_test)
# To inverse scale, we need to concatenate with other features to match scaler's input
# Here, we replace the target column with the predicted values
scaled_pred = np.copy(scaled_data[-len(predicted):])
scaled_pred[:, features.index(target)] = predicted[:, 0]
predicted_prices = scaler.inverse_transform(scaled_pred)[:, features.index(target)]

# Actual prices
actual_scaled = scaled_data[-len(predicted):]
actual_prices = scaler.inverse_transform(actual_scaled)[:, features.index(target)]

# Calculate Metrics
mape = mean_absolute_percentage_error(actual_prices, predicted_prices) * 100  # In percentage
rmse = np.sqrt(mean_squared_error(actual_prices, predicted_prices))

# Extract the last loss and val_loss
training_loss = history.history['loss'][-1]
validation_loss = history.history['val_loss'][-1]

# Print Metrics
print(f"Training Loss: {training_loss:.6f}")
print(f"Validation Loss: {validation_loss:.6f}")
print(f"MAPE: {mape:.2f}%")
print(f"RMSE: {rmse:.4f}")

# Display results
plt.figure(figsize=(14,5))
plt.plot(actual_prices, color='red', label='Actual Stock Price')
plt.plot(predicted_prices, color='blue', label='Predicted Stock Price')
plt.title('Stock Price Prediction')
plt.xlabel('Time')
plt.ylabel('Stock Price')
plt.legend()


###loss降步下來，請一一說明辦法並給coding