
import os
# సర్వర్ ఓవర్లోడ్ అవ్వకుండా త్రెడ్స్ తగ్గించండి
os.environ["OMP_NUM_THREADS"] = "1"
os.environ["MKL_NUM_THREADS"] = "1"
os.environ["OPENBLAS_NUM_THREADS"] = "1"  # ఇది చాలా ముఖ్యం
os.environ["VECLIB_MAXIMUM_THREADS"] = "1"
os.environ["NUMEXPR_NUM_THREADS"] = "1"
os.environ["TF_NUM_INTEROP_THREADS"] = "1"
os.environ["TF_NUM_INTRAOP_THREADS"] = "1"
import sys
import threading
import logging
import warnings
import joblib
import pickle
import pandas as pd
import numpy as np
import pytz
import time
import csv
import requests
from datetime import datetime, timedelta
from flask import Flask, jsonify
from flask_cors import CORS
import tensorflow as tf
from tensorflow.keras.models import load_model
import ta
import keras




# మెమరీని లిమిట్ చేయండి
gpus = tf.config.list_physical_devices('CPU')
tf.config.set_visible_devices(gpus, 'CPU')

# 2. లాగింగ్ & ఎన్విరాన్మెంట్
warnings.filterwarnings('ignore')
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
app = Flask(__name__)
CORS(app)
IST = pytz.timezone('Asia/Kolkata')

# 3. గ్లోబల్ వేరియబుల్స్ (Fix for NameError)
engine_lock = threading.Lock()
csv_lock = threading.Lock()
bot_state = {"is_bot_active": True, "in_pos": False, "sleep_until": None, "last_reset_date": "", "total_wallet": 1000.0}

# 4. SmartAPI ఇంపార్ట్స్
try:
    from SmartApi import SmartConnect
    import pyotp
except ImportError:
    logging.error("❌ SmartApi or pyotp package missing.")

# ⚙️ CONFIGURATION
API_KEY = "ks5b6F2r"
CLIENT_ID = "AACF248938"
PASSWORD = "2525"
TOKEN_KEY = "CFHTTKQNW5LN2YSLKRRSVEKVKI"
BASE_DIR = "/home/luxonweb/luxon_inr_bot"
LOG_FILE = os.path.join(BASE_DIR, "reliance_luxon_history.csv")
obj = None

# 🔐 ANGEL ONE AUTHENTICATION
def connect_angel_one():
    global obj
    try:
        logging.info("🔐 INITIATING ANGEL ONE SECURE LOGIN...")
        obj = SmartConnect(api_key=API_KEY)
        totp = pyotp.TOTP(TOKEN_KEY).now()
        session_data = obj.generateSession(CLIENT_ID, PASSWORD, totp)
        if session_data.get('status'):
            logging.info("✅ AUTHENTICATION SUCCESSFUL!")
            return True
        return False
    except Exception as e:
        logging.error(f"💥 Connection Error: {e}")
        return False

connect_angel_one()

# 🏆 AI ENGINE (CRITICAL FIX)
model, scaler = None, None

def load_ai_engine():
    global model, scaler
    model_path = os.path.join(BASE_DIR, "reliance_nn_model.keras")
    scaler_path = os.path.join(BASE_DIR, "reliance_scaler.pkl")
    
    if os.path.exists(model_path) and os.path.exists(scaler_path):
        try:
            # compile=False మాత్రమే వాడండి, config పద్ధతి కన్నా ఇది సేఫ్
            model = load_model(model_path, compile=False)
            with open(scaler_path, 'rb') as f:
                scaler = pickle.load(f)
            logging.info("✅ AI ENGINE: Loaded successfully!")
        except Exception as e:
            logging.error(f"⚠️ AI ENGINE LOAD ERROR: {e}")
            model = None
    else:
        logging.warning("⚠️ AI files not found. Manual mode.")

load_ai_engine()


        
# ==============================================================================
# ⚙️ BOT STATE MANAGEMENT
# ==============================================================================
def load_bot_state():
    defaults = {
        "consecutive_losses": 0, "sleep_until": None, "last_price": 0.0,
        "last_adx": 0.0, "last_news": "SCANNING...", "last_sync": datetime.now(IST).strftime("%H:%M:%S"),
        "last_status": "INR ENGINE ONLINE", "last_bull": 50, "last_bear": 50,
        "last_pnl": 0.0, "last_news_time": 0, 
        "last_reset_date": datetime.now(IST).strftime("%Y-%m-%d"),
        "atr_stop_loss_price": 0.0, "last_trade_candle": 0,
        "total_wallet": 1000.0, "today_profit": 0.0, "closed_trades_profit": 0.0,
        "wins": 0, "losses": 0, "trades": 0, "in_pos": False,
        "pos_type": "NONE", "entry_p": 0.0, "qty": 0.0, "max_pnl_reached": 0.0,
        "max_price_reached": 0.0, "min_price_reached": 999999.0,
        "onchain_buyer_pressure": "NORMAL", "ai_pred_state": "NEUTRAL",
        "is_bot_active": True
    }
    return defaults

bot_state = load_bot_state()
def save_bot_state(): joblib.dump(bot_state, STATE_FILE)

# ==============================================================================
# 📊 ANGEL ONE LIVE MARKET DATA FETCHERS
# ==============================================================================
def get_live_market_data():
    """ Angel One API ద్వారా రిలయన్స్ కరెంట్ LTP తెస్తుంది """
    global obj
    try:
        if obj is not None:
            response = obj.ltpData("NSE", SYMBOL, TOKEN)
            if response.get('status') == True and response.get('data') is not None:
                return float(response['data']['ltp'])
    except Exception as e:
        logging.error(f"⚠️ Angel One LTP Fetch Error: {e}. Re-authenticating...")
        connect_angel_one()
    return bot_state["last_price"] if bot_state["last_price"] > 0 else 2450.0

def fetch_reliance_klines():
    """ SmartAPI చారిత్రాత్మక డేటా ఎండ్ పాయింట్ నుండి 5 నిమిషాల క్యాండిల్స్ తెస్తుంది """
    global obj
    try:
        if obj is not None:
            to_date = datetime.now(IST).strftime("%Y-%m-%d %H:%M")
            from_date = (datetime.now(IST) - timedelta(days=2)).strftime("%Y-%m-%d %H:%M")
            
            historicParam = {
                "exchange": "NSE",
                "symboltoken": TOKEN,
                "interval": CURRENT_INTERVAL,
                "fromdate": from_date,
                "todate": to_date
            }
            
            res = obj.getCandleData(historicParam)
            if res.get('status') == True and res.get('data') is not None:
                df = pd.DataFrame(res['data'], columns=['time', 'open', 'high', 'low', 'close', 'volume'])
                df['close'] = df['close'].astype(float)
                df['open'] = df['open'].astype(float)
                df['high'] = df['high'].astype(float)
                df['low'] = df['low'].astype(float)
                df['volume'] = df['volume'].astype(float)
                return df
    except Exception as e:
        logging.error(f"⚠️ Failed to fetch historic 5m candles from Angel One: {e}")
    
    # సేఫ్ ఫాల్‌బ్యాక్ బ్యాకప్ పాండాస్ డేటాఫ్రేమ్ (సిమ్యులేటెడ్)
    base_price = get_live_market_data()
    dates = [datetime.now(IST) - timedelta(minutes=5*i) for i in range(100)]
    dates.reverse()
    closes = base_price + np.random.randn(100).cumsum()
    df = pd.DataFrame({'time': dates, 'open': closes-1, 'high': closes+2, 'low': closes-2, 'close': closes, 'volume': np.random.randint(1000, 5000, size=100).astype(float)})
    return df

# ==============================================================================
# 📰 INDIAN MARKET NEWS ENGINE
# ==============================================================================
def execute_news_update():
    global bot_state
    try:
        url = f"https://newsapi.org/v2/everything?q=reliance+OR+nse+OR+nifty&language=en&pageSize=30&apiKey={API_KEY_NEWS}"
        response = requests.get(url).json()
        articles = response.get('articles', [])
        score, total_analyzed = 0, 0
        kw_bullish = ['rally', 'bullish', 'surge', 'breakout', 'growth', 'profit', 'gains']
        kw_bearish = ['crash', 'bearish', 'drop', 'fall', 'losses', 'panic', 'dip']
        
        if articles:
            for art in articles:
                title = str(art.get('title', ''))
                if "[removed]" in title.lower() or not title: continue
                text = (title + " " + str(art.get('description', ''))).lower()
                matched_bull = [kw for kw in kw_bullish if kw in text]
                matched_bear = [kw for kw in kw_bearish if kw in text]
                if matched_bull or matched_bear:
                    score += (1.5 * len(matched_bull)) - (2.0 * len(matched_bear))
                    total_analyzed += 1
            avg_score = score / total_analyzed if total_analyzed > 0 else 0
            if avg_score >= 0.3: bot_state["last_news"] = "BULLISH 📈"
            elif avg_score <= -0.3: bot_state["last_news"] = "BEARISH 📉"
            else: bot_state["last_news"] = "NEUTRAL ⚖️"
        bot_state["last_news_time"] = time.time()
    except Exception:
        bot_state["last_news"] = "NEUTRAL ⚖️"

## ==============================================================================
# 🔥 CORE ENGINE DRIVER (WITH COMPOUNDING & STRICT RISK MANAGEMENT)
# ==============================================================================
def run_trading_engine():
    global bot_state, engine_lock, csv_lock, model, scaler
    last_metrics_refresh_time = 0
    current_atr = 5.0  # Default fallback ATR
    
    while True:
        # 🛑 MANUAL STOP / START LOGIC
        if not bot_state.get("is_bot_active", True):
            bot_state["last_status"] = "SYSTEM MANUALLY STOPPED 🛑"
            time.sleep(2)
            continue

        try:
            with engine_lock:
                # 1. లైవ్ రియల్-టైమ్ ప్రైస్ ట్రాకింగ్
                current_price = get_live_market_data()
                if current_price is None:
                    time.sleep(1)
                    continue
                    
                bot_state["last_price"] = current_price
                bot_state["last_sync"] = datetime.now(IST).strftime("%H:%M:%S")
                
                # రోజువారీ ప్రాఫిట్ రీసెట్ లోప్
                current_date = datetime.now(IST).strftime("%Y-%m-%d")
                if current_date != bot_state.get("last_reset_date", ""):
                    bot_state["today_profit"] = 0.0
                    bot_state["closed_trades_profit"] = 0.0
                    bot_state["last_reset_date"] = current_date

                # ==============================================================================
                # 🛠️ DYNAMIC POSITION MANAGEMENT ENGINE (With Trailing & Profit Guard)
                # ==============================================================================
                if bot_state["in_pos"]:
                    if bot_state["pos_type"] == "LONG":
                        bot_state["last_pnl"] = round((current_price - bot_state["entry_p"]) * bot_state["qty"], 2)
                        if bot_state["last_pnl"] > bot_state["max_pnl_reached"]: 
                            bot_state["max_pnl_reached"] = bot_state["last_pnl"]
                        if current_price > bot_state["max_price_reached"]: 
                            bot_state["max_price_reached"] = current_price
                        
                        price_drop = bot_state["max_price_reached"] - current_price
                        new_sl = round(current_price - (current_atr * ATR_MULTIPLIER), 2)
                        if new_sl > bot_state["atr_stop_loss_price"]:
                            bot_state["atr_stop_loss_price"] = new_sl
                        
                        if bot_state["max_pnl_reached"] >= 50.0 and price_drop >= REVERSAL_DROP_INR: 
                            execute_market_exit("LONG - Profit Guard")
                        elif current_price <= bot_state["atr_stop_loss_price"]: 
                            execute_market_exit("LONG - SL Hit")
                            
                    elif bot_state["pos_type"] == "SHORT":
                        bot_state["last_pnl"] = round((bot_state["entry_p"] - current_price) * bot_state["qty"], 2)
                        if bot_state["last_pnl"] > bot_state["max_pnl_reached"]: 
                            bot_state["max_pnl_reached"] = bot_state["last_pnl"]
                        if current_price < bot_state["min_price_reached"] or bot_state["min_price_reached"] == 999999.0: 
                            bot_state["min_price_reached"] = current_price
                        
                        price_rise = current_price - bot_state["min_price_reached"]
                        new_sl = round(current_price + (current_atr * ATR_MULTIPLIER), 2)
                        if bot_state["atr_stop_loss_price"] == 0 or new_sl < bot_state["atr_stop_loss_price"]:
                            bot_state["atr_stop_loss_price"] = new_sl
                            
                        if bot_state["max_pnl_reached"] >= 50.0 and price_rise >= REVERSAL_DROP_INR: 
                            execute_market_exit("SHORT - Profit Guard")
                        elif current_price >= bot_state["atr_stop_loss_price"]: 
                            execute_market_exit("SHORT - SL Hit")

                # ==============================================================================
                # 📊 MARKET METRICS REFRESH ENGINE (5-Min Candles & AI Scoring)
                # ==============================================================================
                if time.time() - last_metrics_refresh_time > 2:
                    last_metrics_refresh_time = time.time()
                    
                    if time.time() - bot_state.get("last_news_time", 0) > 600: 
                        execute_news_update()
                    
                    df = fetch_reliance_klines()
                    if df is not None and not df.empty:
                        df['return_1'] = df['close'].pct_change(1)
                        df['return_4'] = df['close'].pct_change(4)
                        df['volatility_14'] = df['return_1'].rolling(14).std()
                        df['RSI'] = ta.momentum.rsi(df['close'], window=14)
                        df['Spread_Norm'] = (df['high'] - df['low']) / df['close']
                        df['Volume_Z'] = (df['volume'] - df['volume'].rolling(14).mean()) / df['volume'].rolling(14).std()
                        df['adx'] = ta.trend.adx(df['high'], df['low'], df['close'], window=14)
                        df['atr'] = ta.volatility.average_true_range(df['high'], df['low'], df['close'], window=14)
                        
                        latest_row = df.iloc[-1]
                        bot_state["last_adx"] = round(latest_row['adx'], 2)
                        current_atr = latest_row['atr'] if not np.isnan(latest_row['atr']) else 5.0

                        # --- PURE UNBIASED AI MODEL PREDICTION ENGINE ---
                        if model is not None and scaler is not None:
                            feat_vector = df[features_list].iloc[-1].values.reshape(1, -1)
                            if not np.isnan(feat_vector).any():
                                scaled_feat = scaler.transform(feat_vector)
                                raw_pred = model.predict(scaled_feat, verbose=0)[0][0]
                                bot_state["last_bull"] = int(raw_pred * 100)
                                bot_state["last_bear"] = 100 - bot_state["last_bull"]
                                
                                if bot_state["last_bull"] >= 70: bot_state["ai_pred_state"] = "BULLISH"
                                elif bot_state["last_bear"] >= 70: bot_state["ai_pred_state"] = "BEARISH"
                                else: bot_state["ai_pred_state"] = "NEUTRAL"
                            else:
                                bot_state["ai_pred_state"] = "NEUTRAL"
                        else:
                            bot_state["ai_pred_state"] = "NEUTRAL"

                    # ==============================================================================
                    # 🚀 ORDER TRIGGER ENGINE (WITH 100% WALLET COMPOUNDING LOGIC)
                    # ==============================================================================
                    if not bot_state["in_pos"] and bot_state["sleep_until"] is None:
                        adx_trend_valid = bot_state.get("last_adx", 0) >= 25
                        news_status = bot_state.get("last_news", "")
                        
                        pillar_long = adx_trend_valid and (bot_state.get("last_bull", 0) >= 75) and ("BULLISH" in news_status)
                        pillar_short = adx_trend_valid and (bot_state.get("last_bear", 0) >= 75) and ("BEARISH" in news_status)
                        
                        if pillar_long or pillar_short:
                            # 100% వాలెట్ కంపౌండింగ్
                            wallet_balance = float(bot_state.get("total_wallet", 1000.0))
                            allocated_capital = wallet_balance * LEVERAGE
                            calculated_qty = round(allocated_capital / current_price, 2)
                            
                            bot_state["qty"] = calculated_qty
                            trade_side = "LONG" if pillar_long else "SHORT"
                            execute_market_entry(trade_side, current_price, current_atr)

                    bot_state["today_profit"] = bot_state["closed_trades_profit"]
                    save_bot_state()

        except Exception as e:
            logging.error(f"❌ Core Engine loop Exception: {e}")
            
        time.sleep(5.0)
        
        
# ==============================================================================
# 📥 ORDER EXECUTION SUB-FUNCTIONS
# ==============================================================================
def execute_market_entry(side, current_price, atr):
    global bot_state
    bot_state["in_pos"] = True
    bot_state["pos_type"] = side
    bot_state["entry_p"] = current_price
    bot_state["max_pnl_reached"] = 0.0
    
    atr_offset = atr * ATR_MULTIPLIER
    if side == "LONG":
        bot_state["atr_stop_loss_price"] = round(current_price - atr_offset, 2)
        bot_state["max_price_reached"] = current_price
    else:
        bot_state["atr_stop_loss_price"] = round(current_price + atr_offset, 2)
        bot_state["min_price_reached"] = current_price
    logging.info(f"🚀 RELIANCE POSITION OPENED VIA COMPOUNDING: {side} {bot_state['qty']} Qty at ₹{current_price}")

def execute_market_exit(reason):
    global bot_state
    gross_pnl = bot_state["last_pnl"]
    brokerage = 40.0  # Intraday Roundtrip Brokerage Estimation
    net_pnl = gross_pnl - brokerage
    
    # కంపౌండింగ్ ఇంపాక్ట్: ప్రాఫిట్/లాస్ నేరుగా మెయిన్ వాలెట్ బ్యాలెన్స్‌కు యాడ్ అవుతుంది
    bot_state["total_wallet"] = round(bot_state["total_wallet"] + net_pnl, 2)
    bot_state["closed_trades_profit"] = round(bot_state["closed_trades_profit"] + net_pnl, 2)
    bot_state["today_profit"] = bot_state["closed_trades_profit"]
    
    bot_state["trades"] += 1
    if net_pnl > 0: bot_state["wins"] += 1
    else: bot_state["losses"] += 1
    
    # హిస్టారికల్ రికార్డింగ్
    with csv_lock:
        with open(LOG_FILE, 'a', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerow([datetime.now(IST).strftime("%Y-%m-%d %H:%M:%S"), bot_state["entry_p"], bot_state["last_price"], bot_state["pos_type"], gross_pnl, brokerage, net_pnl, bot_state["total_wallet"]])

    logging.info(f"🛑 POSITION CLOSED: {reason} | Net PnL: ₹{net_pnl} | New Wallet Balance: ₹{bot_state['total_wallet']}")
    bot_state["in_pos"], bot_state["pos_type"], bot_state["entry_p"], bot_state["qty"], bot_state["last_pnl"] = False, "NONE", 0.0, 0.0, 0.0

# ==============================================================================
# 🌐 FLASK REST API ENDPOINTS
# ==============================================================================
@app.route('/api/state', methods=['GET'])
def get_state():
    with engine_lock: 
        return jsonify(bot_state)


# ==============================================================================
# 🌐 FLASK WEB API ROUTES (PURE INR DYNAMIC ENGINE)
# ==============================================================================

@app.route('/')
def home():
    """ లక్సాన్ బాట్ మెయిన్ డ్యాష్‌బోర్డ్ వెబ్ ఇంటర్‌ఫేస్ """
    return render_template("index.html")


@app.route('/api/get_data', methods=['GET'])
def get_data():
    """ 
    UI కి లైవ్ డేటా డిస్‌ప్లే చేసే మెయిన్ ఎండ్ పాయింట్.
    ఇందులో నుండి డాలర్ ($) సింబల్స్ మరియు అనవసర USDT లాజిక్స్ పూర్తిగా తొలగించబడ్డాయి.
    """
    with engine_lock:
        # సక్సెస్ రేట్ కాలిక్యులేషన్
        win_rate = (bot_state["wins"] / bot_state["trades"] * 100) if bot_state["trades"] > 0 else 0.0
        
        current_price = float(bot_state.get("last_price", 0.0))
        entry_price = float(bot_state.get("entry_p", 0.0))
        qty = float(bot_state.get("qty", 0.0))
        pos_type = bot_state.get("pos_type", "NONE")
        
        live_pnl_inr = 0.0
        active_order_display = "₹0.00"
        
        # ఓపెన్ పొజిషన్ ఉంటే లైవ్ రన్నింగ్ PnL కాలిక్యులేషన్
        if bot_state.get("in_pos") and entry_price > 0 and qty > 0:
            live_pnl_inr = bot_state["last_pnl"]
            active_order_display = f"₹{live_pnl_inr:,.2f}"
            display_today_profit = bot_state["closed_trades_profit"] + live_pnl_inr
        else:
            display_today_profit = bot_state["closed_trades_profit"]

        display_wallet_inr = bot_state["total_wallet"]

        # అన్‌лиమిటెడ్ ప్రాఫిట్ గార్డ్ టార్గెట్ డిస్‌ప్లే లాజిక్
        tp_target_val = bot_state.get("max_pnl_reached", 0.0)
        if bot_state.get("in_pos"):
            tp_display = f"PROFIT GUARD ACTIVE (Peak: ₹{tp_target_val:,.2f})"
        else:
            tp_display = "₹0.00"

        # స్టాప్ లాస్ మరియు ఎంట్రీ ప్రైస్ డిస్‌ప్లే (INR ఫార్మాట్)
        sl_target_val = bot_state.get("atr_stop_loss_price", 0.0)
        sl_display = f"₹{float(sl_target_val):,.2f}" if sl_target_val > 0 else "₹0.00"
        entry_display = f"₹{float(entry_price):,.2f}" if entry_price > 0 else "₹0.00"

        # CSV ఫైల్ నుండి గత ట్రేడింగ్ హిస్టరీ ని సింక్ చేయడం
        past_trades = []
        with csv_lock:
            if os.path.exists(LOG_FILE):
                try:
                    with open(LOG_FILE, 'r', encoding='utf-8') as f:
                        reader = csv.DictReader(f)
                        for s_no, row in enumerate(reader, start=1):
                            if not row.get('net_pnl'):
                                continue
                                
                            entry_v = row.get('entry', '0').strip()
                            exit_v = row.get('exit', '0').strip()
                            gross_v = row.get('gross_pnl', '0').strip()
                            broke_v = row.get('brokerage', '0').strip()
                            net_v = row.get('net_pnl', '0').strip()
                            wal_v = row.get('wallet', '0').strip()
                            
                            dt_v = row.get('date_time') or row.get('\ufeffdate_time') or 'N/A'
                            dt_v = dt_v.strip()
                            
                            try:
                                net_float = float(net_v.replace('₹', '').replace(',', '').strip())
                            except ValueError:
                                net_float = 0.0
                                
                            status_str = "WIN" if net_float > 0 else "LOSS" if net_float < 0 else "NEUTRAL"

                            try:
                                past_trades.append({
                                    's_no': s_no,
                                    'date_time': dt_v,
                                    'type': row.get('type', '').strip().upper(),
                                    'entry': entry_v if '₹' in entry_v else f"₹{float(entry_v):,.2f}",
                                    'exit': exit_v if '₹' in exit_v else f"₹{float(exit_v):,.2f}",
                                    'gross_pnl': gross_v if '₹' in gross_v else f"₹{float(gross_v):,.2f}",
                                    'brokerage': broke_v if '₹' in broke_v else f"₹{float(broke_v):,.2f}",
                                    'net_pnl': net_v if '₹' in net_v else f"₹{float(net_v):,.2f}",
                                    'wallet_balance': wal_v if '₹' in wal_v else f"₹{float(wal_v):,.2f}",
                                    'status': status_str
                                })
                            except:
                                continue
                except Exception as ex:
                    logging.error(f"❌ Error reading log inside API: {ex}")

        # ==============================================================================
        # 📌 UI డ్యాష్‌బోర్డ్ పేలోడ్: (ప్యూర్ INR - నో డాలర్స్)
        # ==============================================================================
        payload = {
            "mode": "REAL PRODUCTION LIVE MODE", 
            "wallet_balance_inr": f"₹{display_wallet_inr:,.2f}",
            "today_profit_inr": f"₹{display_today_profit:,.2f}",
            "live_price": current_price,
            "adx_value": bot_state["last_adx"],
            "news_sentiment": bot_state["last_news"],
            "onchain_signal": bot_state["onchain_buyer_pressure"],
            "ai_prediction": bot_state["ai_pred_state"],
            "bullish_strength": bot_state["last_bull"],   
            "bearish_strength": bot_state["last_bear"],   
            "bot_status": bot_state["last_status"],
            "total_trades": bot_state["trades"],
            "wins": bot_state["wins"],
            "losses": bot_state["losses"],
            "success_rate": round(win_rate, 2),
            
            "position_type": pos_type,
            "position_qty": f"{qty:.2f}",  # ఈక్విటీ షేర్స్ కాబట్టి 2 డెసిమల్స్ చాలు
            "entry_price": entry_display,
            "live_pnl": f"₹{live_pnl_inr:,.2f}",
            "active_order_pnl": active_order_display,
            "margin_used": f"₹{round(((qty * (entry_price if entry_price > 0 else current_price)) / LEVERAGE), 2):,.2f}",
            "current_sl": sl_display,
            "current_tp": tp_display,
            
            "trade_history": past_trades[::-1]  # లేటెస్ట్ ట్రేడ్స్ పైన డిస్‌ప్లే అవ్వడానికి
        }
        return jsonify(payload)


@app.route('/api/get_history', methods=['GET'])
def get_history():
    """ పూర్తి ట్రేడింగ్ లాగ్స్ ని క్లయింట్ అడిగినప్పుడు పంపుతుంది """
    trades = []
    with csv_lock:
        if os.path.exists(LOG_FILE):
            try:
                with open(LOG_FILE, 'r', encoding='utf-8') as f:
                    reader = csv.DictReader(f)
                    for row in reader:
                        trades.append(row)
            except Exception as e:
                logging.error(f"❌ Error inside get_history: {e}")
    return jsonify(trades[::-1])


@app.route('/api/emergency_exit', methods=['POST'])
def emergency_exit():
    """ EMERGENCY EXIT BUTTON TRIGGER: లైవ్ పొజిషన్ ఉంటే ఇమ్మీడియట్‌గా మార్కెట్ ఆర్డర్ తో క్లోజ్ చేస్తుంది """
    global bot_state
    with engine_lock:
        if bot_state.get("in_pos"):
            # మన కోర్ ఇంజిన్ ఎగ్జిట్ ఫంక్షన్‌ను పిలిచి రికార్డ్ లాక్ చేయడం
            execute_market_exit("MANUAL EMERGENCY EXIT BUTTON TRIGGERED")
            bot_state["last_status"] = "EMERGENCY POSITION CLOSED 🚨"
            save_bot_state()
            return jsonify({"status": "success", "message": "Emergency market exit executed successfully."})
        return jsonify({"status": "failed", "message": "No active live position detected to exit."})


@app.route('/api/bot_control', methods=['POST'])
def bot_control():
    """ BOT START / STOP BUTTON LOGIC: బాట్ లోప్‌ను రన్ లేదా పాజ్ చేయడం కోసం """
    data = request.json or {}
    action = data.get('action') # 'START' లేదా 'STOP'
    
    global bot_state
    with engine_lock:
        if action == 'STOP':
            bot_state["is_bot_active"] = False
            bot_state["last_status"] = "SYSTEM MANUALLY STOPPED 🛑"
            save_bot_state()
            logging.info("🛑 బాట్ మాన్యువల్‌గా ఆపివేయబడింది.")
            return jsonify({"status": "stopped", "message": "Bot is now turned OFF."})
        
        elif action == 'START':
            bot_state["is_bot_active"] = True
            bot_state["last_status"] = "SCANNING MARKET METRICS 🔍"
            save_bot_state()
            logging.info("✅ బాట్ మళ్ళీ స్టార్ట్ చేయబడింది.")
            return jsonify({"status": "running", "message": "Bot is now turned ON."})
            
    return jsonify({"status": "failed", "message": "Invalid control action specified."})

# 2. గ్లోబల్ వేరియబుల్స్
lock_fp = None

# 3. ఫంక్షన్ డెఫినిషన్స్ (ఇక్కడ డిఫైన్ చేస్తేనే కింద పనిచేస్తాయి)
def start_single_instance():
    global lock_fp
    lock_file = "/tmp/luxon_bot.lock"
    os.makedirs(os.path.dirname(lock_file), exist_ok=True)
    lock_fp = open(lock_file, 'w')
    try:
        fcntl.lockf(lock_fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
        return True 
    except IOError:
        return False

def background_bot_worker():
    # మీ మెయిన్ ట్రేడింగ్ లాజిక్ ఇక్కడ ఉండాలి
    while True:
        print("[ENGINE] Working...")
        time.sleep(30)

# 4. చివరగా MAIN బ్లాక్ (ఇక్కడ మాత్రమే కోడ్ స్టార్ట్ అవ్వాలి)
if __name__ == '__main__':
    if start_single_instance():
        print("[SYSTEM] Starting Bot Engine...")
        # థ్రెడ్ స్టార్ట్ చేయడం
        threading.Thread(target=background_bot_worker, daemon=True).start()
        
        # ఫ్లాస్క్ యాప్ రన్ చేయడం
        app.run(host='0.0.0.0', port=5002, debug=False)
    else:
        print("[SYSTEM] Instance already running!")