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 UltraSmartKrakenBot:
    """
    רובוט מסחר אולטרה-חכם ב-Kraken
    
    אסטרטגיה משופרת:
    1. מחשב ממוצע, מינימום ומקסימום של 24 שעות
    2. קונה רק כשהמחיר קרוב למינימום (בתחתית הטווח)
    3. מוכר רק כשהמחיר קרוב למקסימום (בראש הטווח)
    4. לא קונה אם היה מחיר נמוך הרבה יותר לאחרונה
    """
    
    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 = "USDC/USD"
        self.ws_pair = "USDC/USD"
        self.api_pair = "USDCUSD"
        self.buy_fee = 0.0004
        self.sell_fee = 0.0004
        self.min_profit = 0.000000001
        self.trade_amount = trade_amount
        self.dry_run = dry_run
        
        # אסטרטגיה מתקדמת - מבוססת טווח (Range)
        self.buy_position_in_range = 0.2  # קנה כשבתחתית 20% של הטווח
        self.sell_position_in_range = 0.8  # מכור כשב-80% מלמעלה של הטווח
        
        # נתונים סטטיסטיים
        self.avg_24h = None
        self.min_24h = None
        self.max_24h = None
        self.range_24h = None
        
        # מצב
        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("🧠 רובוט אולטרה-חכם מאותחל")
        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("")
        self.logger.info("📊 אסטרטגיה מבוססת טווח:")
        self.logger.info(f"   🟢 קנייה: כשבתחתית {self.buy_position_in_range * 100}% של טווח 24h")
        self.logger.info(f"   🔴 מכירה: כשב-{self.sell_position_in_range * 100}% מלמעלה של טווח 24h")
        self.logger.info("="*70)
    
    def _setup_logging(self):
        """הגדרת לוגים"""
        log_dir = Path("/app/logs/usdcusd")
        log_dir.mkdir(exist_ok=True)
        
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        log_file = log_dir / f"usdc_usd_bot_{timestamp}.log"
        
        self.logger = logging.getLogger("USDCUSDBot")
        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_stats(self) -> Optional[Dict]:
        """קבלת סטטיסטיקות 24 שעות: ממוצע, מינימום, מקסימום"""
        try:
            # קבלת OHLC
            endpoint = "/0/public/OHLC"
            params = {
                'pair': self.api_pair,
                'interval': 60  # 60 דקות
            }
            
            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
            
            ohlc_data = result['result'][self.api_pair]
            recent_data = ohlc_data[-24:]  # 24 שעות אחרונות
            
            # חישוב ממוצע, מינימום ומקסימום
            close_prices = [float(candle[4]) for candle in recent_data]
            high_prices = [float(candle[2]) for candle in recent_data]
            low_prices = [float(candle[3]) for candle in recent_data]
            
            average = sum(close_prices) / len(close_prices)
            minimum = min(low_prices)  # המינימום המוחלט
            maximum = max(high_prices)  # המקסימום המוחלט
            range_24h = maximum - minimum  # הטווח
            
            stats = {
                'avg': average,
                'min': minimum,
                'max': maximum,
                'range': range_24h
            }
            
            self.logger.info("")
            self.logger.info("📊 סטטיסטיקות 24 שעות:")
            self.logger.info(f"   ממוצע:   ${average:.8f}")
            self.logger.info(f"   מינימום:  ${minimum:.8f} ({((minimum/average - 1) * 100):+.4f}%)")
            self.logger.info(f"   מקסימום: ${maximum:.8f} ({((maximum/average - 1) * 100):+.4f}%)")
            self.logger.info(f"   טווח:    ${range_24h:.8f} ({(range_24h/average * 100):.4f}%)")
            self.logger.info("")
            
            return stats
            
        except Exception as e:
            self.logger.error(f"❌ שגיאה בחישוב סטטיסטיקות: {e}")
            return None
    
    def calculate_position_in_range(self, price: float) -> Optional[float]:
        """
        חישוב מיקום המחיר בטווח ה-24 שעות
        
        Returns:
            0.0 = בתחתית הטווח (מינימום)
            0.5 = באמצע הטווח
            1.0 = בראש הטווח (מקסימום)
        """
        if self.min_24h is None or self.max_24h is None:
            return None
        
        if self.range_24h == 0:
            return 0.5
        
        position = (price - self.min_24h) / self.range_24h
        return position
    
    def _generate_signature(self, urlpath: str, data: Dict, nonce: str) -> str:
        """יצירת חתימה"""
        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:
        """בקשת 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):
        """טיפול בעדכוני מחיר"""
        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
        
        # עדכון סטטיסטיקות כל 5 דקות
        if not hasattr(self, '_last_stats_update'):
            self._last_stats_update = 0
        
        if time.time() - self._last_stats_update > 300:
            stats = self.get_24h_stats()
            if stats:
                self.avg_24h = stats['avg']
                self.min_24h = stats['min']
                self.max_24h = stats['max']
                self.range_24h = stats['range']
            self._last_stats_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.min_24h is None or self.max_24h is None:
            stats = self.get_24h_stats()
            if not stats:
                return
            self.avg_24h = stats['avg']
            self.min_24h = stats['min']
            self.max_24h = stats['max']
            self.range_24h = stats['range']
        
        buy_price = self.best_ask
        if buy_price is None:
            return
        
        # חישוב מיקום המחיר בטווח
        position_in_range = self.calculate_position_in_range(buy_price)
        if position_in_range is None:
            return
        
        # האם המחיר בתחתית הטווח?
        if position_in_range > self.buy_position_in_range:
            # המחיר גבוה מדי בטווח
            if not hasattr(self, '_last_wait_log'):
                self._last_wait_log = 0
            
            if time.time() - self._last_wait_log > 30:
                distance_from_avg = ((buy_price / self.avg_24h - 1) * 100)
                distance_from_min = ((buy_price / self.min_24h - 1) * 100)
                
                # חישוב מחיר יעד לקנייה
                target_buy_price = self.min_24h + (self.range_24h * self.buy_position_in_range)
                needed_drop = ((target_buy_price / buy_price - 1) * 100)
                
                self.logger.info(
                    f"⏸️ ממתין לקנייה | "
                    f"מחיר: ${buy_price:.8f} ({distance_from_avg:+.4f}% מממוצע) | "
                    f"מיקום בטווח: {position_in_range * 100:.1f}% | "
                    f"רוצה: <{self.buy_position_in_range * 100:.0f}% | "
                    f"צריך ירידה: {needed_drop:.4f}%"
                )
                self._last_wait_log = time.time()
            return
        
        # המחיר טוב! בתחתית הטווח!
        volume = self.trade_amount / buy_price
        buy_cost = self.trade_amount * (1 + self.buy_fee)
        
        distance_from_min = ((buy_price / self.min_24h - 1) * 100)
        distance_from_avg = ((buy_price / self.avg_24h - 1) * 100)
        
        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} ({distance_from_avg:+.4f}%)")
        self.logger.info(f"   מינימום 24h: ${self.min_24h:.8f} ({distance_from_min:+.4f}%)")
        self.logger.info(f"   מקסימום 24h: ${self.max_24h:.8f}")
        self.logger.info(f"   🎯 מיקום בטווח: {position_in_range * 100:.1f}% (תחתית!)")
        self.logger.info(f"   כמות: {volume:.8f} USDT")
        self.logger.info(f"   עלות כוללת: ${buy_cost:.6f}")
        
        self.position = {
            'price': buy_price,
            'volume': volume,
            'buy_cost': buy_cost,
            'timestamp': datetime.now(),
            'stats_at_buy': {
                'avg': self.avg_24h,
                'min': self.min_24h,
                'max': self.max_24h,
                'position': position_in_range
            }
        }
        
        target_price = buy_price * (1 + self.required_increase)
        self.logger.info(f"   🎯 מחיר יעד: ${target_price:.8f}")
        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)
                
                status = f"⏳ ממתין למכירה | מחיר: ${sell_price:.8f} | רווח נוכחי: {current_profit:.10f}%"
                
                if self.min_24h and self.max_24h:
                    position = self.calculate_position_in_range(sell_price)
                    if position:
                        status += f" | מיקום בטווח: {position * 100:.1f}%"
                
                self.logger.info(status)
                self._last_status_time = time.time()
            return
        
        # בדיקה 2: האם המחיר בראש הטווח?
        position_in_range = self.calculate_position_in_range(sell_price)
        
        if position_in_range and position_in_range < self.sell_position_in_range:
            self.logger.info(
                f"⏸️ מחיר הגיע ליעד (${sell_price:.8f}) "
                f"אבל מיקום בטווח: {position_in_range * 100:.1f}% "
                f"(רוצה >{self.sell_position_in_range * 100:.0f}%), ממתין..."
            )
            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
        
        distance_from_max = ((sell_price / self.max_24h - 1) * 100) if self.max_24h else 0
        
        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.max_24h:
            self.logger.info(f"   מקסימום 24h: ${self.max_24h:.8f} ({distance_from_max:+.4f}%)")
        if position_in_range:
            self.logger.info(f"   🎯 מיקום בטווח: {position_in_range * 100:.1f}% (ראש!)")
        
        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)
    
    async def connect_websocket(self):
        """התחברות ל-WebSocket"""
        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}")
            
            # קבלת סטטיסטיקות ראשוניות
            stats = self.get_24h_stats()
            if stats:
                self.avg_24h = stats['avg']
                self.min_24h = stats['min']
                self.max_24h = stats['max']
                self.range_24h = stats['range']
            
            async for message in websocket:
                try:
                    data = json.loads(message)
                    
                    if isinstance(data, dict):
                        if data.get('event') == 'heartbeat':
                            continue
                        elif data.get('event') in ['systemStatus', 'subscriptionStatus']:
                            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:
                self.logger.info(f"   ממוצע: ${self.total_profit / self.trades_count:.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':
        print("⚠️ הגדר את KRAKEN_API_KEY ו-KRAKEN_API_SECRET")
        return
    
    print(f"מצב: {'🔵 סימולציה' if DRY_RUN else '🔴 מסחר אמיתי'}")
    print(f"סכום: ${TRADE_AMOUNT}")
    print()
    print("📊 אסטרטגיה:")
    print("   🟢 קנייה בתחתית 20% של טווח 24h")
    print("   🔴 מכירה ב-80% מלמעלה של טווח 24h")
    print()
    
    if not DRY_RUN:
        confirm = input("האם אתה בטוח? (כתוב 'כן אני מבין את הסיכון'): ")
        if confirm != 'כן אני מבין את הסיכון':
            return
    
    bot = UltraSmartKrakenBot(
        api_key=API_KEY,
        api_secret=API_SECRET,
        trade_amount=TRADE_AMOUNT,
        dry_run=DRY_RUN
    )
    
    asyncio.run(bot.run())


if __name__ == "__main__":
    main()
