"""
Late Entry Trading Bot - Continuous Monitor
Runs in background, captures momentum when markets get active
"""

import os
import json
import time
from datetime import datetime

os.environ['KALSHI_API_KEY_ID'] = '81fe00fc-27b2-48ca-85f8-9c37ec1dc82f'
os.environ['KALSHI_PRIVATE_KEY_PATH'] = './kalshi_private_key'

from pykalshi import KalshiClient, MarketStatus

# Config
PAPER_BALANCE = 1500
MIN_PROFIT = 0.25
MAX_LOSS = 0.20
POSITION_PCT = 0.10

class Bot:
    def __init__(self):
        self.client = None
        self.balance = PAPER_BALANCE
        self.positions = []
        self.trades = []
        self.losses = 0
        self.prices = {}  # ticker -> price
        
    def setup(self):
        self.client = KalshiClient()
        print("✅ Connected")
        return self
        
    def get_active_markets(self):
        markets = self.client.get_markets(status=MarketStatus.OPEN, limit=500)
        return [m for m in markets if m.volume > 0 and 
                ('wins by' in m.title.lower() or 'over ' in m.title.lower() or 'under ' in m.title.lower())]
    
    def price(self, market):
        if market.yes_bid == 0 and market.yes_ask == 0:
            return 0
        return (market.yes_bid + market.yes_ask) / 200
    
    def run(self, cycles=30, delay=3):
        print(f"\n🚀 Running {cycles} cycles...\n")
        
        for i in range(cycles):
            markets = self.get_active_markets()
            
            # Check exits
            self.check_exits(markets)
            
            if self.losses >= 3:
                print("🛑 Circuit breaker")
                break
            
            # Check entries
            for m in markets:
                # Skip if already open
                if any(p['status'] == 'open' and p['ticker'] == m.ticker for p in self.positions):
                    continue
                
                curr = self.price(m)
                if curr == 0:
                    continue
                
                prev = self.prices.get(m.ticker, 0)
                
                # Entry signal: price appeared (0 -> something) OR moved 10%+
                signal = None
                
                if prev == 0 and curr > 0:
                    # Just became active - momentum!
                    signal = 'YES' if curr > 0.5 else 'NO'
                elif prev > 0:
                    change = abs(curr - prev)
                    if change >= 0.10:  # 10%+ move
                        signal = 'YES' if curr > prev else 'NO'
                
                if signal:
                    self.enter(m, signal, curr)
                
                self.prices[m.ticker] = curr
            
            # Stats
            closed = [t for t in self.trades if t['status'] == 'closed']
            wins = len([t for t in closed if t['pnl'] > 0])
            print(f"[{i+1}] Balance: ${self.balance:.0f} | Trades: {len(closed)} | Wins: {wins} | Open: {len([p for p in self.positions if p['status']=='open'])}")
            
            time.sleep(delay)
        
        # Final stats
        print("\n" + "="*50)
        print(f"FINAL BALANCE: ${self.balance:.2f}")
        closed = [t for t in self.trades if t['status'] == 'closed']
        if closed:
            wins = [t for t in closed if t['pnl'] > 0]
            print(f"Trades: {len(closed)} | Wins: {len(wins)} | Win Rate: {len(wins)/len(closed)*100:.0f}%")
        print("="*50)
        
        # Save
        with open('paper_trading_state.json', 'w') as f:
            json.dump({'balance': self.balance, 'trades': self.trades}, f, indent=2, default=str)
    
    def enter(self, market, side, price):
        contracts = int(self.balance * POSITION_PCT)
        if contracts < 1:
            return
        
        pos = {
            'ticker': market.ticker,
            'title': market.title[:50],
            'side': side,
            'entry': price,
            'contracts': contracts,
            'time': datetime.now().isoformat(),
            'status': 'open'
        }
        self.positions.append(pos)
        self.balance -= contracts
        
        print(f"  📝 ENTER {side} @ {price*100:.0f}¢ | {market.title[:40]}...")
    
    def check_exits(self, markets):
        market_dict = {m.ticker: m for m in markets}
        
        for p in self.positions:
            if p['status'] != 'open':
                continue
            if p['ticker'] not in market_dict:
                continue
            
            m = market_dict[p['ticker']]
            curr = self.price(m)
            
            if p['side'] == 'YES':
                pnl_pct = (curr - p['entry']) / p['entry'] if p['entry'] > 0 else 0
            else:
                pnl_pct = (p['entry'] - curr) / p['entry'] if p['entry'] > 0 else 0
            
            if pnl_pct >= MIN_PROFIT or pnl_pct <= -MAX_LOSS:
                self.close(p, curr, "target" if pnl_pct > 0 else "stop")
    
    def close(self, pos, price, reason):
        pnl = (price - pos['entry']) * pos['contracts'] if pos['side'] == 'YES' else (pos['entry'] - price) * pos['contracts']
        
        self.balance += pos['contracts'] + pnl
        pos['status'] = 'closed'
        pos['exit'] = price
        pos['pnl'] = pnl
        pos['reason'] = reason
        self.trades.append(pos)
        
        if pnl > 0:
            self.losses = 0
            print(f"  ✅ WIN +${pnl:.0f}")
        else:
            self.losses += 1
            print(f"  ❌ LOSS ${pnl:.0f}")

if __name__ == '__main__':
    Bot().setup().run(cycles=20, delay=4)
