import asyncio
import logging
import yaml
import os
from dotenv import load_dotenv

# Load environment variables FIRST
load_dotenv()

import uvicorn
from api.server import app as fastapi_app
from api.websocket_server import DashboardWS
from modules.data_connector import DataConnector
from modules.signal_generator import SignalGenerator
from modules.risk_manager import RiskManager
from modules.order_executor import OrderExecutor
from modules.notifier import Notifier

# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger("CryptoBot")

def load_config():
    with open("config.yaml", 'r') as f:
        return yaml.safe_load(f)

class CryptoBot:
    def __init__(self):
        self.config = load_config()
        self.api_key = os.getenv("BINANCE_API_KEY")
        self.api_secret = os.getenv("BINANCE_API_SECRET")
        
        self.data_connector = DataConnector(self.api_key, self.api_secret, testnet=self.config['bot_settings']['testnet'])
        self.signal_generator = SignalGenerator(self.config)
        self.risk_manager = RiskManager(self.config)
        self.order_executor = OrderExecutor(self.api_key, self.api_secret, testnet=self.config['bot_settings']['testnet'])
        self.notifier = Notifier(
            telegram_token=os.getenv("TELEGRAM_BOT_TOKEN"),
            chat_id=os.getenv("TELEGRAM_CHAT_ID"),
            email_config={
                'user': os.getenv("EMAIL_USER"),
                'password': os.getenv("EMAIL_PASSWORD"),
                'receiver': os.getenv("EMAIL_RECEIVER")
            }
        )
        self.ws_server = DashboardWS(port=5001)
        self.is_running = False

    async def trading_loop(self):
        logger.info("Starting trading loop...")
        self.is_running = True
        
        # Start data connector in background
        asyncio.create_task(self.data_connector.start(self.config['pairs'], self.config['bot_settings']['timeframe']))
        
        while self.is_running:
            for symbol in self.config['pairs']:
                df = self.data_connector.buffers.get(symbol)
                if df is not None and not df.empty:
                    signal, confidence = self.signal_generator.generate_signal(symbol, df)
                    
                    # Log signal to dashboard
                    await self.ws_server.broadcast({
                        "type": "signal_update",
                        "symbol": symbol,
                        "signal": signal,
                        "price": df['close'].iloc[-1]
                    })
                    
                    if signal == "BUY" and self.risk_manager.can_open_position(0): # simplified
                        balance = self.order_executor.get_balance("USDT")
                        pos_size = self.risk_manager.calculate_position_size(balance)
                        # Execute buy... (omitted for brevity, actual execution would be here)
                        self.notifier.send_telegram(f"🚀 BUY signal for {symbol} at {df['close'].iloc[-1]}")
                        
                    # Broadcast live activity to prove it's evaluating
                    await self.ws_server.broadcast({
                        "type": "activity_log",
                        "message": f"Processed tick for {symbol} | Price Eval: {df['close'].iloc[-1]:.2f} | EMA Long: {self.signal_generator.latest_states[symbol]['ema_long']:.2f}"
                    })
            
            await asyncio.sleep(3) # check every 3 seconds for live visualizer

    async def run(self):
        # Start API server in a separate thread/process if needed, 
        # but here we just run WS and trading loop together
        tasks = [
            self.ws_server.start(),
            self.trading_loop()
        ]
        await asyncio.gather(*tasks)

async def start_all():
    bot = CryptoBot()
    fastapi_app.state.bot = bot
    
    # Get API config
    api_config = bot.config.get('api_settings', {'host': '0.0.0.0', 'port': 5000})
    
    logger.info(f"Starting API server on {api_config['host']}:{api_config['port']}")
    
    config = uvicorn.Config(
        fastapi_app, 
        host=api_config['host'], 
        port=api_config['port'], 
        log_level="info"
    )
    server = uvicorn.Server(config)
    
    # Run everything concurrently
    await asyncio.gather(
        server.serve(),
        bot.run()
    )

if __name__ == "__main__":
    try:
        asyncio.run(start_all())
    except KeyboardInterrupt:
        logger.info("Bot stopped by user")
