import asyncio
import json
import websockets
import hmac
import hashlib
import base64
import time
import requests
import os
from datetime import datetime
from typing import Optional, Dict
import logging
from pathlib import Path

class KrakenWebSocketBot:
    """
    רובוט מסחר ב-Kraken דרך WebSocket
    רווח מינימלי: 0.000000001 (כמעט כל רווח)
    """
    
    def __init__(self, api_key: str, api_secret: str, trade_amount: float = 10, dry_run: bool = True):
        self.api_key = api_key
        self.api_secret = api_secret
        self.api_url = "https://api.kraken.com"
        self.ws_url = "wss://ws.kraken.com"
        self.ws_auth_url = "wss://ws-auth.kraken.com"
        
        # הגדרות מסחר
        self.pair = "USDT/USD"
        self.ws_pair = "USDT/USD"
        self.buy_fee = 0.002    # 0.2%
        self.sell_fee = 0.002   # 0.2%
        self.min_profit = 0.000000001  # רווח מינימלי כמעט אפס!
        self.trade_amount = trade_amount
        self.dry_run = dry_run
        
        # מצב
        self.position = None
        self.current_price = None
        self.best_bid = None
        self.best_ask = None
        self.trades_count = 0
        self.total_profit = 0.0
        
        # חישוב יעד
        self.required_increase = self._calculate_required_increase()
        
        # הגדרת לוגים
        self._setup_logging()
        
        self.logger.info("="*70)
        self.logger.info("🤖 רובוט Kraken WebSocket מאותחל")
        self.logger.info(f"מצב: {'סימולציה' if dry_run else 'מסחר אמיתי'}")
        self.logger.info(f"סכום למסחר: ${self.trade_amount}")
        self.logger.info(f"רווח מינימלי: {self.min_profit * 100:.10f}%")
        self.logger.info(f"אחוז עלייה נדרש במחיר: {self.required_increase * 100:.10f}%")
        self.logger.info("="*70)
    
    def _setup_logging(self):
        """הגדרת מערכת לוגים מקיפה"""
        # יצירת תיקיית לוגים
        log_dir = Path("/home/claude/logs")
        log_dir.mkdir(exist_ok=True)
        
        # שם הקובץ עם תאריך ושעה
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        log_file = log_dir / f"kraken_bot_{timestamp}.log"
        
        # הגדרת logger
        self.logger = logging.getLogger("KrakenBot")
        self.logger.setLevel(logging.DEBUG)
        
        # פורמט עם יותר פרטים
        formatter = logging.Formatter(
            '%(asctime)s | %(levelname)-8s | %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        
        # Handler לקובץ
        file_handler = logging.FileHandler(log_file, encoding='utf-8')
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(formatter)
        
        # Handler למסך
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        console_handler.setFormatter(formatter)
        
        self.logger.addHandler(file_handler)
        self.logger.addHandler(console_handler)
        
        self.logger.info(f"📝 לוגים נשמרים ב: {log_file}")
    
    def _calculate_required_increase(self) -> float:
        """חישוב האחוז המינימלי הנדרש לעלייה"""
        # עלות קנייה אמיתית
        buy_cost = 1.0 * (1 + self.buy_fee)
        
        # צריך לקבל בחזרה
        required_received = buy_cost * (1 + self.min_profit)
        
        # מחיר מכירה נדרש (לפני עמלה)
        required_sell_price = required_received / (1 - self.sell_fee)
        
        return required_sell_price - 1.0
    
    def _generate_signature(self, urlpath: str, data: Dict, nonce: str) -> str:
        """יצירת חתימה לבקשות REST API"""
        postdata = urllib.parse.urlencode(data)
        encoded = (nonce + postdata).encode()
        message = urlpath.encode() + hashlib.sha256(encoded).digest()
        signature = hmac.new(
            base64.b64decode(self.api_secret),
            message,
            hashlib.sha512
        )
        return base64.b64encode(signature.digest()).decode()
    
    def _api_request(self, endpoint: str, data: Optional[Dict] = None) -> Dict:
        """בקשת REST API"""
        url = f"{self.api_url}{endpoint}"
        nonce = str(int(time.time() * 1000))
        data = data or {}
        data['nonce'] = nonce
        
        headers = {
            'API-Key': self.api_key,
            'API-Sign': self._generate_signature(endpoint, data, nonce)
        }
        
        response = requests.post(url, headers=headers, data=data)
        return response.json()
    
    def place_market_order(self, side: str, volume: float) -> bool:
        """ביצוע פקודת שוק (קנייה/מכירה)"""
        if self.dry_run:
            self.logger.info(f"🔵 [סימולציה] פקודת {side}: {volume:.6f} USDT")
            return True
        
        try:
            order_data = {
                'pair': 'USDTUSD',
                'type': side,
                'ordertype': 'market',
                'volume': str(volume)
            }
            
            result = self._api_request("/0/private/AddOrder", order_data)
            
            if result.get('error') and len(result['error']) > 0:
                self.logger.error(f"❌ שגיאה בפקודה: {result['error']}")
                return False
            
            self.logger.info(f"✅ פקודה בוצעה: {result}")
            return True
        except Exception as e:
            self.logger.error(f"❌ חריג: {e}")
            return False
    
    async def handle_ticker(self, data: dict):
        """טיפול בעדכוני מחיר מ-WebSocket"""
        try:
            if len(data) < 2:
                return
            
            ticker_data = data[1]
            
            # עדכון מחירים
            if 'a' in ticker_data:  # Ask (מכירה)
                self.best_ask = float(ticker_data['a'][0])
            if 'b' in ticker_data:  # Bid (קנייה)
                self.best_bid = float(ticker_data['b'][0])
            
            # חישוב מחיר אמצע
            if self.best_ask and self.best_bid:
                self.current_price = (self.best_ask + self.best_bid) / 2
                
                # בדוק אם צריך לסחור
                await self.check_trading_opportunity()
        
        except Exception as e:
            self.logger.error(f"❌ שגיאה בטיפול בטיקר: {e}")
    
    async def check_trading_opportunity(self):
        """בדיקה אם יש הזדמנות מסחר"""
        if self.current_price is None:
            return
        
        # אם אין פוזיציה - חפש הזדמנות לקנות
        if self.position is None:
            await self.try_buy()
        
        # אם יש פוזיציה - בדוק אם אפשר למכור
        else:
            await self.try_sell()
    
    async def try_buy(self):
        """ניסיון קנייה - קונים מיד במחיר השוק"""
        if self.position is not None:
            return
        
        # קונים במחיר ה-ask הנוכחי
        buy_price = self.best_ask
        if buy_price is None:
            return
        
        # חישוב כמות
        volume = self.trade_amount / buy_price
        buy_cost = self.trade_amount * (1 + self.buy_fee)
        
        self.logger.info("")
        self.logger.info("🟢 " + "="*60)
        self.logger.info(f"📥 פתיחת פוזיציה (קנייה)")
        self.logger.info(f"   מחיר: ${buy_price:.8f}")
        self.logger.info(f"   כמות: {volume:.8f} USDT")
        self.logger.info(f"   סכום: ${self.trade_amount:.2f}")
        self.logger.info(f"   עמלה: ${self.trade_amount * self.buy_fee:.6f}")
        self.logger.info(f"   עלות כוללת: ${buy_cost:.6f}")
        
        # שמירת הפוזיציה
        self.position = {
            'price': buy_price,
            'volume': volume,
            'buy_cost': buy_cost,
            'timestamp': datetime.now()
        }
        
        # חישוב מחיר יעד
        target_price = buy_price * (1 + self.required_increase)
        self.logger.info(f"   🎯 מחיר יעד: ${target_price:.8f}")
        self.logger.info(f"   📊 עלייה נדרשת: {self.required_increase * 100:.10f}%")
        self.logger.info("="*60)
        
        # ביצוע הקנייה
        if not self.dry_run:
            self.place_market_order('buy', volume)
    
    async def try_sell(self):
        """ניסיון מכירה - מוכרים כשמגיעים ליעד"""
        if self.position is None:
            return
        
        buy_price = self.position['price']
        target_price = buy_price * (1 + self.required_increase)
        
        # מוכרים במחיר ה-bid הנוכחי
        sell_price = self.best_bid
        if sell_price is None:
            return
        
        # בדיקה אם הגענו ליעד
        if sell_price >= target_price:
            volume = self.position['volume']
            revenue = volume * sell_price
            revenue_after_fee = revenue * (1 - self.sell_fee)
            cost = self.position['buy_cost']
            profit = revenue_after_fee - cost
            profit_percent = (profit / cost) * 100
            
            self.logger.info("")
            self.logger.info("🔴 " + "="*60)
            self.logger.info(f"📤 סגירת פוזיציה (מכירה)")
            self.logger.info(f"   מחיר קנייה: ${buy_price:.8f}")
            self.logger.info(f"   מחיר מכירה: ${sell_price:.8f}")
            self.logger.info(f"   כמות: {volume:.8f} USDT")
            self.logger.info(f"   הכנסה: ${revenue:.6f}")
            self.logger.info(f"   עמלה: ${revenue * self.sell_fee:.6f}")
            self.logger.info(f"   נטו: ${revenue_after_fee:.6f}")
            self.logger.info(f"   עלות: ${cost:.6f}")
            self.logger.info(f"   💰 רווח: ${profit:.8f} ({profit_percent:.10f}%)")
            
            # עדכון סטטיסטיקות
            self.trades_count += 1
            self.total_profit += profit
            
            self.logger.info(f"   📊 סה\"כ עסקאות: {self.trades_count}")
            self.logger.info(f"   📊 סה\"כ רווח: ${self.total_profit:.8f}")
            self.logger.info("="*60)
            
            # איפוס הפוזיציה
            self.position = None
            
            # ביצוע המכירה
            if not self.dry_run:
                self.place_market_order('sell', volume)
        
        else:
            # הצגת מצב כל 10 שניות
            if not hasattr(self, '_last_status_time'):
                self._last_status_time = time.time()
            
            if time.time() - self._last_status_time > 10:
                current_profit = ((sell_price / buy_price - 1) * 100)
                needed = ((target_price / sell_price - 1) * 100)
                
                self.logger.info(f"⏳ ממתין | מחיר: ${sell_price:.8f} | רווח נוכחי: {current_profit:.10f}% | נדרש: {needed:.10f}%")
                self._last_status_time = time.time()
    
    async def connect_websocket(self):
        """התחברות ל-WebSocket של Kraken"""
        self.logger.info("🔌 מתחבר ל-WebSocket...")
        
        async with websockets.connect(self.ws_url) as websocket:
            # הרשמה לערוץ Ticker
            subscribe_message = {
                "event": "subscribe",
                "pair": [self.ws_pair],
                "subscription": {
                    "name": "ticker"
                }
            }
            
            await websocket.send(json.dumps(subscribe_message))
            self.logger.info(f"📡 נרשם לערוץ ticker עבור {self.ws_pair}")
            
            # לולאת קבלת הודעות
            async for message in websocket:
                try:
                    data = json.loads(message)
                    
                    # התעלם מהודעות מערכת
                    if isinstance(data, dict):
                        if data.get('event') == 'heartbeat':
                            continue
                        elif data.get('event') == 'systemStatus':
                            self.logger.info(f"📊 מצב מערכת: {data.get('status')}")
                            continue
                        elif data.get('event') == 'subscriptionStatus':
                            self.logger.info(f"✅ הרשמה: {data}")
                            continue
                    
                    # טיפול בנתוני ticker
                    if isinstance(data, list) and len(data) > 1:
                        await self.handle_ticker(data)
                
                except Exception as e:
                    self.logger.error(f"❌ שגיאה בלולאה: {e}")
    
    async def run(self):
        """הפעלת הבוט"""
        self.logger.info("🚀 הבוט מתחיל...")
        
        try:
            await self.connect_websocket()
        except KeyboardInterrupt:
            self.logger.info("\n⏹️ הבוט נעצר על ידי המשתמש")
        except Exception as e:
            self.logger.error(f"❌ שגיאה קריטית: {e}")
        finally:
            self.logger.info("")
            self.logger.info("="*70)
            self.logger.info("📊 סיכום הפעלה:")
            self.logger.info(f"   עסקאות שבוצעו: {self.trades_count}")
            self.logger.info(f"   רווח כולל: ${self.total_profit:.8f}")
            if self.trades_count > 0:
                avg_profit = self.total_profit / self.trades_count
                self.logger.info(f"   ממוצע רווח לעסקה: ${avg_profit:.8f}")
            self.logger.info("="*70)


def main():
    """פונקציה ראשית"""
    print("="*70)
    print("רובוט Kraken WebSocket - מסחר בזמן אמת")
    print("="*70)
    print()
    
    # קריאת משתני סביבה
    API_KEY = os.getenv('KRAKEN_API_KEY', 'YOUR_API_KEY_HERE')
    API_SECRET = os.getenv('KRAKEN_API_SECRET', 'YOUR_API_SECRET_HERE')
    TRADE_AMOUNT = float(os.getenv('TRADE_AMOUNT', '10'))
    DRY_RUN = os.getenv('DRY_RUN', 'true').lower() == 'true'
    
    # בדיקה שהמפתחות הוגדרו
    if API_KEY == 'YOUR_API_KEY_HERE' or API_SECRET == 'YOUR_API_SECRET_HERE':
        print("⚠️ אזהרה: מפתחות API לא הוגדרו!")
        print("אנא הגדר את המשתנים:")
        print("  - KRAKEN_API_KEY")
        print("  - KRAKEN_API_SECRET")
        print()
        print("דרכים להגדרה:")
        print("1. קובץ .env:")
        print("   echo 'KRAKEN_API_KEY=your_key' > .env")
        print("   echo 'KRAKEN_API_SECRET=your_secret' >> .env")
        print()
        print("2. משתני סביבה:")
        print("   export KRAKEN_API_KEY=your_key")
        print("   export KRAKEN_API_SECRET=your_secret")
        print()
        return
    
    print(f"מצב: {'🔵 סימולציה' if DRY_RUN else '🔴 מסחר אמיתי'}")
    print(f"סכום לעסקה: ${TRADE_AMOUNT}")
    print()
    
    if not DRY_RUN:
        print("⚠️ " + "="*66)
        print("⚠️ מסחר אמיתי מופעל! הבוט יבצע עסקאות אמיתיות בכסף אמיתי!")
        print("⚠️ " + "="*66)
        print()
        confirm = input("האם אתה בטוח לחלוטין? (כתוב 'כן אני מבין את הסיכון'): ")
        if confirm != 'כן אני מבין את הסיכון':
            print("מבוטל.")
            return
    
    # יצירת הבוט
    bot = KrakenWebSocketBot(
        api_key=API_KEY,
        api_secret=API_SECRET,
        trade_amount=TRADE_AMOUNT,
        dry_run=DRY_RUN
    )
    
    # הרצה
    asyncio.run(bot.run())


if __name__ == "__main__":
    main()
