import gradio as gr
import pandas as pd
import yfinance as yf
from utils import (
    calculate_technical_indicators,
    generate_trading_signals,
    get_fundamental_data,
    predict_prices,
    create_price_chart,
    create_technical_chart,
    create_prediction_chart,
    calculate_advanced_risk_metrics 
)
import warnings
import numpy as np 
warnings.filterwarnings("ignore")
def analyze_stock(symbol, prediction_days=30):
    try:
        if not symbol.strip():
            raise ValueError("Please enter a valid stock symbol.")
        if not symbol.endswith(".JK"):
            symbol = symbol.upper() + ".JK"
        stock = yf.Ticker(symbol)
        data = stock.history(period="1y", interval="1d") 
        if data.empty:
            raise ValueError("No price data available for this stock.")
        indicators = calculate_technical_indicators(data)
        signals = generate_trading_signals(data, indicators)
        fundamental_info = get_fundamental_data(stock)
        
        risk_metrics = calculate_advanced_risk_metrics(data.copy())
        predictions = predict_prices(data, prediction_days=prediction_days)
        fig_price = create_price_chart(data, indicators)
        fig_technical = create_technical_chart(data, indicators)
        fig_prediction = create_prediction_chart(data, predictions)
        # kalkulasi TP1, TP2, SL yang diperbarui berdasarkan quantiles/range prediksi
        last_price = data['Close'].iloc[-1]
        
        # Dapatkan array prediksi dengan fallback ke array yang berisi harga terakhir
        q05 = predictions.get('values', np.array([last_price]))
        q01 = predictions.get('q01', np.array([last_price * 0.95]))
        q09 = predictions.get('q09', np.array([last_price * 1.05]))
        
        # Robust max/min calculation
        q05_max = np.max(q05) if q05.size > 0 else last_price
        q09_max = np.max(q09) if q09.size > 0 else last_price * 1.05
        q01_min = np.min(q01) if q01.size > 0 else last_price * 0.95
        
        # Target/SL calculation
        tp1 = (last_price + q05_max) / 2
        tp2 = q09_max
        sl = q01_min
        
        if tp1 > tp2:
            tp1, tp2 = tp2, tp1 
        if sl > last_price:
            sl = last_price * 0.95 # Fallback
        predictions["tp1"] = tp1
        predictions["tp2"] = tp2
        predictions["sl"] = sl
        return fundamental_info, indicators, signals, risk_metrics, fig_price, fig_technical, fig_prediction, predictions
    except Exception as e:
        print(f"Error analyzing {symbol}: {e}")
        
        try:
            stock = yf.Ticker(symbol)
            data = stock.history(period="1d", interval="1d")
            last_price = data['Close'].iloc[-1] if not data.empty else 0
        except:
            last_price = 0
        default_tp1 = last_price * 1.01 
        default_tp2 = last_price * 1.02 
        default_sl = last_price * 0.95
        empty_predictions = {
            "high_30d": 0, "low_30d": 0, "change_pct": 0,
            "summary": f"Prediction unavailable. Model error: {e}",
            # Menggunakan list kosong sebagai fallback jika error terjadi
            "q01": [], "q09": [], 
            "tp1": default_tp1, "tp2": default_tp2, "sl": default_sl,
        }
        empty_risk = {"error": "Prediction Model Failed to Load/Run. See console for details."}
        
        # Mengembalikan None untuk output plot Gradio untuk membersihkan plot
        return {}, {}, {}, empty_risk, None, None, None, empty_predictions
def update_analysis(symbol, prediction_days):
    (
        fundamental_info,
        indicators,
        signals,
        risk_metrics,
        fig_price,
        fig_technical,
        fig_prediction,
        predictions,
    ) = analyze_stock(symbol, prediction_days)
    # Cek apakah ada plot yang None (berarti ada error)
    if fig_price is None: 
        error_msg = f"Unable to run AI prediction or fetch data for {symbol.upper()}. Check the model logs for details."
        tp_sl_info = f"TP1: Rp{predictions.get('tp1', 0):,.2f}
TP2: Rp{predictions.get('tp2', 0):,.2f}
Stop Loss: Rp{predictions.get('sl', 0):,.2f}
Model Insight:
{predictions.get('summary', 'Data fetching or model execution failed. Cannot proceed with analysis.')}"
        
        return (
            f"""