#!/usr/bin/env python3
"""
Service de surveillance et reporting par email - DEGEN BOT
Envoie un récapitulatif des trades Apollo Degen Bot toutes les 6h
"""

import smtplib
import json
import time
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime, timedelta
from typing import List, Dict
import logging
import os
import sys
from pathlib import Path

# Ajouter le path du bot degen
sys.path.insert(0, '/var/www/html/HyperOracle/crypto_trader/apollo_degen_bot')
from apollox_v2_client import ApolloXV2Client
from dotenv import load_dotenv

class DegenBotReportMailer:
    """Service d'envoi de rapports du Degen Bot par email"""

    def __init__(self, recipient_email: str = "binet.benjamin@gmail.com"):
        self.recipient_email = recipient_email
        self.report_interval = 6 * 3600  # 6 heures
        self.last_report_time = 0

        # Paths
        self.bot_dir = Path('/var/www/html/HyperOracle/crypto_trader/apollo_degen_bot')
        self.positions_file = self.bot_dir / 'positions.json'
        self.log_file = self.bot_dir / 'bot_v10_onchain.log'

        # Load env et init client
        load_dotenv(self.bot_dir / '.env')
        private_key = os.getenv('WALLET_PRIVATE_KEY')
        self.client = ApolloXV2Client(private_key) if private_key else None

        self.setup_logger()

    def setup_logger(self):
        """Configure le logging"""
        self.logger = logging.getLogger("DegenBotMailer")
        self.logger.setLevel(logging.INFO)

        handler = logging.StreamHandler()
        formatter = logging.Formatter('%(asctime)s - [%(name)s] - %(message)s')
        handler.setFormatter(formatter)

        if not self.logger.handlers:
            self.logger.addHandler(handler)

    def get_recent_trades(self, hours: int = 6) -> List[Dict]:
        """Récupère les trades des X dernières heures depuis positions.json"""
        try:
            if not self.positions_file.exists():
                return []

            with open(self.positions_file) as f:
                data = json.load(f)

            cutoff = datetime.now() - timedelta(hours=hours)
            recent = []

            for trade_hash, pos in data.get('positions', {}).items():
                if pos.get('status') == 'CLOSED':
                    closed_at = pos.get('closed_at')
                    if closed_at:
                        closed_time = datetime.fromisoformat(closed_at)
                        if closed_time > cutoff:
                            recent.append(pos)

            self.logger.info(f"📊 Trades fermés: {len(recent)} dans les {hours}h")
            return recent

        except Exception as e:
            self.logger.error(f"Erreur récupération trades: {e}")
            return []

    def get_current_positions(self) -> List[Dict]:
        """Récupère les positions actuelles depuis positions.json"""
        try:
            if not self.positions_file.exists():
                return []

            with open(self.positions_file) as f:
                data = json.load(f)

            open_positions = [
                pos for pos in data.get('positions', {}).values()
                if pos.get('status') == 'OPEN'
            ]

            return open_positions

        except Exception as e:
            self.logger.error(f"Erreur récupération positions: {e}")
            return []

    def get_bnb_price(self) -> float:
        """Récupère le prix BNB actuel depuis Binance"""
        try:
            import requests
            response = requests.get('https://api.binance.com/api/v3/ticker/price?symbol=BNBUSDT', timeout=5)
            data = response.json()
            return float(data['price'])
        except Exception as e:
            self.logger.error(f"Erreur récupération prix BNB: {e}")
            return 600.0  # Fallback

    def get_account_balance(self) -> Dict:
        """Récupère les balances BNB et USDT"""
        try:
            if not self.client:
                return {'bnb': 0, 'usdt': 0, 'bnb_price': 600}

            bnb = self.client.get_balance()
            usdt = self.client.get_usdt_balance()
            bnb_price = self.get_bnb_price()

            return {'bnb': bnb, 'usdt': usdt, 'bnb_price': bnb_price}

        except Exception as e:
            self.logger.error(f"Erreur récupération balance: {e}")
            return {'bnb': 0, 'usdt': 0, 'bnb_price': 600}

    def get_bot_stats(self) -> Dict:
        """Extrait les stats du bot depuis les logs"""
        try:
            if not self.log_file.exists():
                return {}

            # Lire les dernières 1000 lignes du log
            with open(self.log_file) as f:
                lines = f.readlines()[-1000:]

            # Chercher la dernière ligne de résumé
            for line in reversed(lines):
                if 'Total trades:' in line and 'Win rate:' in line:
                    # Parser la ligne
                    stats = {}
                    if 'Win rate:' in line:
                        parts = line.split('Win rate:')[1].strip()
                        win_rate = parts.split('%')[0].strip()
                        stats['win_rate'] = float(win_rate)

                    if 'Total PnL:' in line:
                        parts = line.split('Total PnL:')[1].strip()
                        pnl = parts.replace('$', '').replace('+', '').strip()
                        stats['total_pnl'] = float(pnl)

                    return stats

            return {}

        except Exception as e:
            self.logger.error(f"Erreur extraction stats: {e}")
            return {}

    def format_report(self, trades: List[Dict], positions: List[Dict],
                     balance: Dict, stats: Dict) -> str:
        """Formate le rapport en HTML"""

        html = f"""
        <html>
        <body style="font-family: Arial, sans-serif;">
            <h2>🤖 Apollo Degen Bot - Rapport {datetime.now().strftime('%d/%m/%Y %H:%M')}</h2>

            <h3>💰 Balance</h3>
            <ul>
                <li>USDT: <b>${balance.get('usdt', 0):.2f}</b></li>
                <li>BNB: <b>{balance.get('bnb', 0):.6f}</b> (~${balance.get('bnb', 0) * balance.get('bnb_price', 600):.2f} @ ${balance.get('bnb_price', 600):.2f}/BNB)</li>
            </ul>

            <h3>📊 Performance Globale</h3>
            <ul>
                <li>Win Rate: <b>{stats.get('win_rate', 0):.1f}%</b></li>
                <li>Total PnL: <b>${stats.get('total_pnl', 0):+.2f}</b></li>
            </ul>

            <h3>💼 Positions Ouvertes ({len(positions)})</h3>
        """

        if positions:
            html += "<table border='1' cellpadding='5' style='border-collapse: collapse;'>"
            html += "<tr><th>Symbol</th><th>Side</th><th>Leverage</th><th>Entry</th><th>PnL</th></tr>"

            for pos in positions:
                side = 'LONG' if pos.get('is_long', True) else 'SHORT'
                pnl = pos.get('pnl', 0)
                color = 'green' if pnl > 0 else 'red'

                html += f"""
                <tr>
                    <td>{pos.get('symbol', '?')}</td>
                    <td>{side}</td>
                    <td>{pos.get('leverage', '?')}x</td>
                    <td>${pos.get('entry_price', 0):.2f}</td>
                    <td style='color: {color};'><b>${pnl:+.2f}</b></td>
                </tr>
                """

            html += "</table>"
        else:
            html += "<p>Aucune position ouverte</p>"

        html += f"""
            <h3>📈 Trades Fermés (6h) ({len(trades)})</h3>
        """

        if trades:
            html += "<table border='1' cellpadding='5' style='border-collapse: collapse;'>"
            html += "<tr><th>Symbol</th><th>Side</th><th>PnL</th><th>Fermé à</th></tr>"

            for trade in trades[:20]:  # Max 20 derniers
                side = 'LONG' if trade.get('is_long', True) else 'SHORT'
                pnl = trade.get('pnl', 0)
                color = 'green' if pnl > 0 else 'red'
                closed = trade.get('closed_at', '')[:16]

                html += f"""
                <tr>
                    <td>{trade.get('symbol', '?')}</td>
                    <td>{side}</td>
                    <td style='color: {color};'><b>${pnl:+.2f}</b></td>
                    <td>{closed}</td>
                </tr>
                """

            html += "</table>"

            # Stats des trades
            total_pnl = sum(t.get('pnl', 0) for t in trades)
            wins = sum(1 for t in trades if t.get('pnl', 0) > 0)
            losses = len(trades) - wins

            html += f"""
            <p>
                <b>Résumé période:</b><br>
                Win Rate: {wins}/{len(trades)} ({wins/len(trades)*100:.1f}%)<br>
                PnL total: <span style='color: {"green" if total_pnl > 0 else "red"};'><b>${total_pnl:+.2f}</b></span>
            </p>
            """
        else:
            html += "<p>Aucun trade fermé</p>"

        html += """
            <hr>
            <p style="color: gray; font-size: 12px;">
                Apollo Degen Bot - Trading automatique sur BSC<br>
                Rapport généré automatiquement toutes les 6h
            </p>
        </body>
        </html>
        """

        return html

    def send_email(self, subject: str, html_content: str):
        """Envoie l'email via la commande mail système"""
        try:
            import subprocess
            import tempfile

            # Créer un fichier temporaire pour le HTML
            with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False) as f:
                f.write(html_content)
                html_file = f.name

            # Utiliser la commande mail système
            cmd = [
                'mail',
                '-s', subject,
                '-a', f'Content-Type: text/html; charset=UTF-8',
                '-a', 'From: Degen Bot <server@codeben.fr>',
                self.recipient_email
            ]

            with open(html_file, 'r') as f:
                result = subprocess.run(
                    cmd,
                    stdin=f,
                    capture_output=True,
                    text=True,
                    timeout=30
                )

            # Nettoyer le fichier temporaire
            os.unlink(html_file)

            if result.returncode == 0:
                self.logger.info(f"✅ Email envoyé à {self.recipient_email}")
                return True
            else:
                self.logger.error(f"❌ Erreur mail: {result.stderr}")
                return False

        except Exception as e:
            self.logger.error(f"❌ Erreur envoi email: {e}")
            return False

    def send_report(self):
        """Génère et envoie le rapport"""
        try:
            self.logger.info("📧 Génération du rapport...")

            # Collecter les données
            trades = self.get_recent_trades(hours=6)
            positions = self.get_current_positions()
            balance = self.get_account_balance()
            stats = self.get_bot_stats()

            # Générer le rapport
            html = self.format_report(trades, positions, balance, stats)

            # Sujet avec stats clés
            subject = f"🤖 Degen Bot - {len(positions)} positions | PnL: ${stats.get('total_pnl', 0):+.2f}"

            # Envoyer
            success = self.send_email(subject, html)

            if success:
                self.last_report_time = time.time()

        except Exception as e:
            self.logger.error(f"❌ Erreur génération rapport: {e}")

    def run(self):
        """Boucle principale du service"""
        self.logger.info("🚀 Service Degen Bot Mailer démarré")
        self.logger.info(f"   Email: {self.recipient_email}")
        self.logger.info(f"   Intervalle: {self.report_interval/3600:.0f}h")

        # Envoyer un premier rapport immédiatement
        self.send_report()

        while True:
            try:
                # Attendre l'intervalle
                time.sleep(60)  # Check toutes les minutes

                # Vérifier si il est temps d'envoyer un rapport
                if time.time() - self.last_report_time >= self.report_interval:
                    self.send_report()

            except KeyboardInterrupt:
                self.logger.info("⏹️  Service arrêté")
                break
            except Exception as e:
                self.logger.error(f"❌ Erreur boucle: {e}")
                time.sleep(300)  # Wait 5 min avant retry


if __name__ == "__main__":
    mailer = DegenBotReportMailer()
    mailer.run()
