"""
Trading Engine Simplifié - Ouverture de positions uniquement
"""

import logging
import time
from datetime import datetime
from threading import Thread, Lock
from typing import Dict, List, Optional
import os
import sys

# Imports locaux
import sys
import os
sys.path.append('..')
from hyperliquid_client import HyperliquidClient
from real_time_trading_engine import Position
import trading_config

class SimpleTradingEngine:
    """Trading engine simplifié qui ne gère que l'ouverture de positions"""

    def __init__(self, trading_mode='SIMULATION', initial_balance=1000, hyperliquid_client=None):
        self.trading_mode = trading_mode
        self.initial_balance = initial_balance
        self.current_balance = initial_balance
        self.hyperliquid_client = hyperliquid_client

        # Configuration trading
        self.max_positions = getattr(trading_config, 'MAX_SIMULTANEOUS_POSITIONS', 5)
        self.position_size_pct = trading_config.POSITION_SIZE_PERCENT / 100
        self.max_leverage = getattr(trading_config, 'MAX_LEVERAGE', 20)
        self.hyperliquid_fee_rate = getattr(trading_config, 'HYPERLIQUID_FEE_RATE', 0.0005)

        # Storage
        self.positions = {}
        self.lock = Lock()
        self.running = False

        # Logger
        self.setup_logger()

        # Signals provider
        self.signals_provider = None

        self.logger.info(f"=== SIMPLE TRADING ENGINE STARTED ===")
        self.logger.info(f"Mode: {trading_mode}")
        self.logger.info(f"Max positions: {self.max_positions}")

    def setup_logger(self):
        """Configure le système de logging"""
        self.logger = logging.getLogger("SimpleTradingEngine")
        self.logger.setLevel(logging.INFO)

        # Créer le dossier logs si nécessaire
        logs_dir = "logs"
        if not os.path.exists(logs_dir):
            os.makedirs(logs_dir)

        # Handler fichier
        file_handler = logging.FileHandler(os.path.join(logs_dir, "simple_trading.log"))
        file_handler.setLevel(logging.INFO)

        # Handler console
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)

        # Format
        formatter = logging.Formatter('%(asctime)s - [%(name)s] - %(message)s')
        file_handler.setFormatter(formatter)
        console_handler.setFormatter(formatter)

        if not self.logger.handlers:
            self.logger.addHandler(file_handler)
            self.logger.addHandler(console_handler)

    def set_signals_provider(self, provider_func):
        """Injecter le fournisseur de signaux"""
        self.signals_provider = provider_func

    def get_signals(self):
        """Récupère les signaux depuis le provider"""
        if not self.signals_provider:
            return []
        return self.signals_provider()

    def should_open_position(self, signal: Dict) -> bool:
        """Vérifie si on peut ouvrir une position basée sur le signal"""
        symbol = signal.get('symbol')
        side = signal.get('side')

        # Vérifier le nombre max de positions (même logique que ProfitTaker)
        current_positions_count = len(self.positions)
        if self.trading_mode in ['LIVE_MANUAL', 'LIVE_AUTO'] and self.hyperliquid_client:
            try:
                hl_positions = self.hyperliquid_client.get_positions()
                current_positions_count = len(hl_positions) if hl_positions else 0
            except Exception as e:
                self.logger.warning(f"Impossible de récupérer les positions: {e}")

        if current_positions_count >= self.max_positions:
            self.logger.info(f"REJECT {symbol}: Max positions atteint ({current_positions_count}/{self.max_positions})")
            return False

        # Vérifier la qualité du signal
        min_quality_score = getattr(trading_config, 'MIN_SIGNAL_QUALITY_SCORE', 0.65)
        quality_score = signal.get('quality_score', 0)

        if quality_score < min_quality_score:
            self.logger.info(f"REJECT {symbol}: Score qualité insuffisant ({quality_score:.2f} < {min_quality_score})")
            return False

        # Vérifier qu'on n'a pas déjà une position sur ce symbole (même logique que ProfitTaker)
        if self.trading_mode in ['LIVE_MANUAL', 'LIVE_AUTO'] and self.hyperliquid_client:
            try:
                hl_positions = self.hyperliquid_client.get_positions()
                for pos in hl_positions:
                    pos_symbol = pos.get('symbol', '').replace('-PERP', '')
                    if pos_symbol == symbol:
                        self.logger.info(f"REJECT {symbol}: Position déjà ouverte")
                        return False
            except Exception as e:
                self.logger.warning(f"Erreur vérification position existante: {e}")

        return True

    def log_detailed_positions(self, hl_positions):
        """Affiche le détail des positions actives (inspiré du ProfitTaker)"""
        if not hl_positions:
            self.logger.info("Status: 0/10 positions actives")
            return

        self.logger.info("=" * 80)
        self.logger.info("POSITIONS ACTIVES:")
        self.logger.info("=" * 80)

        for pos in hl_positions:
            try:
                symbol = pos.get('symbol', '').replace('-PERP', '')
                side = pos.get('side', '').upper()
                entry_price = float(pos.get('entry_price', 0))
                size = abs(float(pos.get('size', 0)))
                leverage = int(pos.get('leverage', {}).get('value', 1))

                # Récupérer le prix actuel
                try:
                    current_price = self.hyperliquid_client.get_current_market_price(symbol)
                    if not current_price:
                        current_price = entry_price
                except:
                    current_price = entry_price

                # Calculer le PnL
                if entry_price > 0 and current_price > 0:
                    if side == 'LONG':
                        pnl_percent = ((current_price - entry_price) / entry_price) * 100 * leverage
                    else:  # SHORT
                        pnl_percent = ((entry_price - current_price) / entry_price) * 100 * leverage
                else:
                    pnl_percent = 0

                # Formatage selon la taille du prix
                if entry_price >= 1000:
                    entry_str = f"${entry_price:,.2f}"
                    current_str = f"${current_price:,.2f}"
                else:
                    entry_str = f"${entry_price:.5f}"
                    current_str = f"${current_price:.5f}"

                pnl_sign = "+" if pnl_percent >= 0 else ""
                pnl_color = "UP" if pnl_percent >= 0 else "DOWN"

                self.logger.info(f"{symbol:<6} {side:<5} | Entry: {entry_str:<12} -> Current: {current_str:<12} | "
                               f"Size: {size:<8.3f} | Leverage: {leverage:>2}x | "
                               f"PnL: {pnl_sign}{pnl_percent:>6.2f}% {pnl_color}")

            except Exception as e:
                self.logger.warning(f"Erreur affichage position {pos}: {e}")

        self.logger.info("=" * 80)

    def open_position(self, signal: Dict) -> Optional[Position]:
        """Ouvre une nouvelle position basée sur un signal"""
        try:
            symbol = signal.get('symbol')
            side = signal.get('side')

            # Vérifier que les champs obligatoires sont présents
            if not symbol or not side:
                self.logger.error(f"Signal invalide - manque symbol ou side: {signal}")
                return None

            leverage = min(signal.get('leverage', 1), self.max_leverage)

            # Calculer la taille de position
            if self.trading_mode in ['LIVE_MANUAL', 'LIVE_AUTO'] and self.hyperliquid_client:
                account_state = self.hyperliquid_client.get_account_state()
                if account_state and 'marginSummary' in account_state:
                    available_balance = float(account_state['marginSummary'].get('accountValue', 0))
                else:
                    available_balance = self.current_balance
            else:
                available_balance = self.current_balance

            position_value = available_balance * self.position_size_pct
            entry_price = signal.get('current_price', 0)

            if entry_price <= 0:
                self.logger.error(f"Prix invalide pour {symbol}: {entry_price}")
                return None

            size = (position_value * leverage) / entry_price
            margin_used = position_value

            # Calculer stop loss et take profit simples
            risk_pct = 0.15 / leverage
            if side == 'LONG':
                stop_loss = entry_price * (1 - risk_pct)
                take_profit = entry_price * (1 + risk_pct * 2)
            else:
                stop_loss = entry_price * (1 + risk_pct)
                take_profit = entry_price * (1 - risk_pct * 2)

            # Créer l'objet Position
            position = Position(
                id=f"{symbol}_{side}_{int(time.time())}",
                symbol=symbol,
                side=side,
                size=size,
                entry_price=entry_price,
                current_price=entry_price,
                leverage=leverage,
                stop_loss=stop_loss,
                take_profit=take_profit,
                timestamp=datetime.now().isoformat(),
                status='OPEN',
                margin_used=margin_used,
                trading_mode=self.trading_mode
            )

            # Placer l'ordre sur Hyperliquid si mode LIVE
            if self.trading_mode in ['LIVE_MANUAL', 'LIVE_AUTO'] and self.hyperliquid_client:
                is_buy = (side == 'LONG')
                result = self.hyperliquid_client.place_market_order(
                    symbol=symbol,
                    is_buy=is_buy,
                    size=size,
                    leverage=leverage,
                    order_tag=f"OPEN_{side}_{symbol}"
                )

                if not result.get('success'):
                    self.logger.error(f"Échec ouverture {symbol}: {result.get('error')}")
                    return None

            # Enregistrer la position
            with self.lock:
                self.positions[position.id] = position
                if self.trading_mode == 'SIMULATION':
                    self.current_balance -= margin_used

            self.logger.info(f"OPENED: {symbol} {side} | Size: {size:.6f} | Entry: ${entry_price:.4f} | Leverage: {leverage}x")

            return position

        except Exception as e:
            self.logger.error(f"Erreur ouverture position: {e}")
            return None

    def trading_loop(self):
        """Boucle principale de trading - Ouverture uniquement"""
        self.logger.info("Démarrage de la boucle de trading...")

        while self.running:
            try:
                # L'état des positions est maintenant géré centralement via hyperliquid_client

                # Recherche de nouvelles opportunités (mode AUTO seulement)
                if self.trading_mode == 'LIVE_AUTO':
                    signals = self.get_signals()

                    for signal in signals:
                        if self.should_open_position(signal):
                            self.open_position(signal)
                            time.sleep(1)  # Petit délai entre les ouvertures

                # Afficher le statut avec détail des positions (même logique que ProfitTaker)
                if self.trading_mode in ['LIVE_MANUAL', 'LIVE_AUTO'] and self.hyperliquid_client:
                    try:
                        hl_positions = self.hyperliquid_client.get_positions()
                        positions_count = len(hl_positions) if hl_positions else 0

                        # Affichage détaillé toutes les 3 fois (1 minute)
                        if hasattr(self, '_status_counter'):
                            self._status_counter += 1
                        else:
                            self._status_counter = 1

                        if self._status_counter % 3 == 0:  # Toutes les 3 fois = 1 minute
                            self.log_detailed_positions(hl_positions)
                        else:
                            self.logger.info(f"Status: {positions_count}/{self.max_positions} positions actives")

                    except Exception as e:
                        self.logger.warning(f"Erreur comptage positions: {e}")
                        positions_count = len(self.positions)
                        self.logger.info(f"Status: {positions_count}/{self.max_positions} positions actives")
                else:
                    positions_count = len(self.positions)
                    self.logger.info(f"Status: {positions_count}/{self.max_positions} positions actives")

                # Pause avant la prochaine itération
                time.sleep(20)

            except Exception as e:
                self.logger.error(f"Erreur dans trading_loop: {e}")
                time.sleep(5)

    def start(self):
        """Démarre le trading engine"""
        if not self.running:
            self.running = True
            self.trading_thread = Thread(target=self.trading_loop)
            self.trading_thread.daemon = True
            self.trading_thread.start()
            self.logger.info("Trading engine démarré")

    def stop(self):
        """Arrête le trading engine"""
        self.running = False
        if hasattr(self, 'trading_thread'):
            self.trading_thread.join(timeout=5)
        self.logger.info("Trading engine arrêté")