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

class SmartKrakenBot:
    """
    רובוט מסחר חכם ב-Kraken עם אסטרטגיה מבוססת ממוצע 24 שעות
    
    אסטרטגיה:
    1. מחשב ממוצע מחירים של 24 שעות האחרונות
    2. קונה רק כשהמחיר נמוך מהממוצע (הזדמנות!)
    3. מוכר כשהמחיר גבוה מהממוצע + רווח מינימלי (יעד הושג!)
    """
    
    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.pair = "USDT/USD"
        self.ws_pair = "USDT/USD"
        self.api_pair = "USDTUSD"
        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.avg_24h = None  # ממוצע 24 שעות
        self.buy_threshold = 0.001  # קנה כשהמחיר נמוך מהממוצע ב-0.1%
        self.sell_above_avg = True  # מכור רק אם מעל ממוצע
        
        # מצב
        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 חכם מאותחל")
        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("")
        self.logger.info("📊 אסטרטגיה:")
        self.logger.info(f"   - קנייה: כשמחיר < ממוצע 24h - {self.buy_threshold * 100}%")
        self.logger.info(f"   - מכירה: כשמחיר > ממוצע 24h + רווח מינימלי")
        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"smart_bot_{timestamp}.log"
        
        self.logger = logging.getLogger("SmartKrakenBot")
        self.logger.setLevel(logging.DEBUG)
        
        formatter = logging.Formatter(
            '%(asctime)s | %(levelname)-8s | %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        
        file_handler = logging.FileHandler(log_file, encoding='utf-8')
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(formatter)
        
        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 get_24h_average(self) -> Optional[float]:
        """קבלת ממוצע מחירים של 24 שעות האחרונות"""
        try:
            # קבלת נתוני OHLC (Open, High, Low, Close) של השעה האחרונה
            endpoint = "/0/public/OHLC"
            params = {
                'pair': self.api_pair,
                'interval': 60  # 60 דקות = 1 שעה
            }
            
            response = requests.get(f"{self.api_url}{endpoint}", params=params)
            result = response.json()
            
            if result.get('error') and len(result['error']) > 0:
                self.logger.error(f"❌ שגיאה בקבלת OHLC: {result['error']}")
                return None
            
            # חישוב ממוצע של 24 השעות האחרונות
            ohlc_data = result['result'][self.api_pair]
            if len(ohlc_data) < 24:
                self.logger.warning(f"⚠️ יש רק {len(ohlc_data)} נרות, צריך 24")
                # נשתמש במה שיש
            
            # נקח את 24 השעות האחרונות (או פחות אם אין)
            recent_data = ohlc_data[-24:]
            
            # חישוב ממוצע של מחירי הסגירה
            close_prices = [float(candle[4]) for candle in recent_data]  # index 4 = close price
            average = sum(close_prices) / len(close_prices)
            
            self.logger.info(f"📊 ממוצע 24 שעות: ${average:.8f} (מבוסס על {len(close_prices)} שעות)")
            return average
            
        except Exception as e:
            self.logger.error(f"❌ שגיאה בחישוב ממוצע 24h: {e}")
            return None
    
    def get_ticker_info(self) -> Optional[Dict]:
        """קבלת מידע על המחיר הנוכחי מ-REST API"""
        try:
            endpoint = "/0/public/Ticker"
            params = {'pair': self.api_pair}
            
            response = requests.get(f"{self.api_url}{endpoint}", params=params)
            result = response.json()
            
            if result.get('error') and len(result['error']) > 0:
                return None
            
            ticker_data = result['result'][self.api_pair]
            return {
                'ask': float(ticker_data['a'][0]),
                'bid': float(ticker_data['b'][0]),
                'last': float(ticker_data['c'][0]),
                'volume_24h': float(ticker_data['v'][1]),
                'vwap_24h': float(ticker_data['p'][1])  # Volume Weighted Average Price
            }
        except Exception as e:
            self.logger.error(f"❌ שגיאה בקבלת ticker: {e}")
            return None
    
    def _generate_signature(self, urlpath: str, data: Dict, nonce: str) -> str:
        """יצירת חתימה לבקשות REST API"""
        import urllib.parse
        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': self.api_pair,
                '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:
                self.best_ask = float(ticker_data['a'][0])
            if 'b' in ticker_data:
                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
        
        # עדכון ממוצע 24 שעות כל 5 דקות
        if not hasattr(self, '_last_avg_update'):
            self._last_avg_update = 0
        
        if time.time() - self._last_avg_update > 300:  # 5 דקות
            self.avg_24h = self.get_24h_average()
            self._last_avg_update = time.time()
        
        # אין פוזיציה - בדוק אם כדאי לקנות
        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
        
        if self.avg_24h is None:
            # אם עדיין אין ממוצע, נקבל אותו עכשיו
            self.avg_24h = self.get_24h_average()
            if self.avg_24h is None:
                return
        
        buy_price = self.best_ask
        if buy_price is None:
            return
        
        # חישוב סף הקנייה
        buy_threshold_price = self.avg_24h * (1 - self.buy_threshold)
        
        # בדיקה: האם המחיר נמוך מספיק?
        if buy_price >= buy_threshold_price:
            # המחיר גבוה מדי, לא קונים
            if not hasattr(self, '_last_wait_log'):
                self._last_wait_log = 0
            
            if time.time() - self._last_wait_log > 30:  # לוג כל 30 שניות
                diff_percent = ((buy_price / self.avg_24h - 1) * 100)
                self.logger.info(
                    f"⏸️ ממתין | מחיר: ${buy_price:.8f} | "
                    f"ממוצע 24h: ${self.avg_24h:.8f} | "
                    f"הפרש: {diff_percent:+.4f}% | "
                    f"צריך ירידה של: {((buy_threshold_price / buy_price - 1) * 100):.4f}%"
                )
                self._last_wait_log = time.time()
            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"   ממוצע 24h: ${self.avg_24h:.8f}")
        self.logger.info(f"   הנחה: {((buy_price / self.avg_24h - 1) * 100):.4f}%")
        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(),
            'avg_24h_at_buy': self.avg_24h
        }
        
        # חישוב מחיר יעד
        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)
        sell_price = self.best_bid
        
        if sell_price is None:
            return
        
        # בדיקה 1: הגענו ליעד הרווח?
        if sell_price < target_price:
            # עדיין לא הגענו ליעד
            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)
                
                status = f"⏳ ממתין למכירה | מחיר: ${sell_price:.8f} | רווח נוכחי: {current_profit:.10f}% | נדרש: {needed:.10f}%"
                
                # הוסף מידע על ממוצע אם זמין
                if self.avg_24h:
                    diff_from_avg = ((sell_price / self.avg_24h - 1) * 100)
                    status += f" | vs ממוצע: {diff_from_avg:+.4f}%"
                
                self.logger.info(status)
                self._last_status_time = time.time()
            return
        
        # בדיקה 2: האם המחיר מעל הממוצע? (אופציונלי אבל מומלץ)
        if self.sell_above_avg and self.avg_24h:
            if sell_price < self.avg_24h:
                self.logger.info(
                    f"⏸️ מחיר הגיע ליעד (${sell_price:.8f}) אבל מתחת לממוצע 24h (${self.avg_24h:.8f}), "
                    f"ממתין למחיר טוב יותר..."
                )
                return
        
        # כל התנאים מתקיימים - מוכרים!
        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}")
        
        if self.avg_24h:
            diff_from_avg = ((sell_price / self.avg_24h - 1) * 100)
            self.logger.info(f"   ממוצע 24h: ${self.avg_24h:.8f} ({diff_from_avg:+.4f}%)")
        
        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}")
        if self.trades_count > 0:
            avg = self.total_profit / self.trades_count
            self.logger.info(f"   📊 ממוצע רווח לעסקה: ${avg:.8f}")
        self.logger.info("="*60)
        
        # איפוס הפוזיציה
        self.position = None
        
        # ביצוע המכירה
        if not self.dry_run:
            self.place_market_order('sell', volume)
    
    async def connect_websocket(self):
        """התחברות ל-WebSocket של Kraken"""
        self.logger.info("🔌 מתחבר ל-WebSocket...")
        
        async with websockets.connect(self.ws_url) as websocket:
            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}")
            
            # קבלת ממוצע ראשוני
            self.avg_24h = self.get_24h_average()
            
            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.get('status')}")
                            continue
                    
                    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 חכם - מסחר מבוסס ממוצע 24 שעות")
    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()
    print("📊 אסטרטגיה:")
    print("   ✅ קנייה כשהמחיר נמוך מממוצע 24 שעות")
    print("   ✅ מכירה כשהמחיר מעל ממוצע + רווח מינימלי")
    print()
    
    if not DRY_RUN:
        print("⚠️ " + "="*66)
        print("⚠️ מסחר אמיתי מופעל! הבוט יבצע עסקאות אמיתיות בכסף אמיתי!")
        print("⚠️ " + "="*66)
        print()
        confirm = input("האם אתה בטוח לחלוטין? (כתוב 'כן אני מבין את הסיכון'): ")
        if confirm != 'כן אני מבין את הסיכון':
            print("מבוטל.")
            return
    
    # יצירת הבוט
    bot = SmartKrakenBot(
        api_key=API_KEY,
        api_secret=API_SECRET,
        trade_amount=TRADE_AMOUNT,
        dry_run=DRY_RUN
    )
    
    # הרצה
    asyncio.run(bot.run())


if __name__ == "__main__":
    main()
