#!/usr/bin/env python3
"""
Scanne la blockchain BSC pour récupérer TOUTES les positions ApolloX
En décodant les events du smart contract
"""

import os
from web3 import Web3
from eth_abi import decode
import json
from datetime import datetime
from dotenv import load_dotenv
import requests

load_dotenv()

WALLET_ADDRESS = os.getenv('WALLET_ADDRESS', '0x7476737C49d55bea691e54c2c96fD39a6bAf3049')
APOLLOX_CONTRACT = "0x1b6F2d3844C6ae7D56ceb3C3643b9060ba28FEb0"
BSC_RPC = "https://bsc-dataseed.binance.org/"

w3 = Web3(Web3.HTTPProvider(BSC_RPC))

# Event signatures
OPEN_TRADE_EVENT = "0x7064b82c073f138da0ec7646ebb51d4a0061d647accb4670bc564edf0bfac41d"
CLOSE_TRADE_EVENT = "0xYOUR_CLOSE_EVENT_SIG"  # À trouver
LIQUIDATION_EVENT = "0xYOUR_LIQUIDATION_SIG"  # À trouver


def get_btc_price_at_block(block_number: int) -> float:
    """Récupère prix BTC approximatif via timestamp du block"""
    try:
        block = w3.eth.get_block(block_number)
        timestamp_ms = block['timestamp'] * 1000

        # Binance klines
        url = "https://api.binance.com/api/v3/klines"
        params = {
            'symbol': 'BTCUSDT',
            'interval': '5m',
            'startTime': timestamp_ms - 300000,
            'endTime': timestamp_ms + 300000,
            'limit': 1
        }

        response = requests.get(url, params=params, timeout=5)
        data = response.json()

        if data:
            return float(data[0][1])  # Open price
        return None

    except Exception as e:
        print(f"      ⚠️  Erreur prix: {e}")
        return None


def scan_open_trades() -> dict:
    """Scanne tous les events d'ouverture de trades"""

    print("🔍 Scanning blockchain pour les trades...")
    print(f"   Wallet: {WALLET_ADDRESS}")
    print(f"   Contract: {APOLLOX_CONTRACT}\n")

    positions = {}

    # Récupérer toutes les TX du wallet via BSCScan API
    url = "https://api.bscscan.com/api"
    params = {
        'module': 'account',
        'action': 'txlist',
        'address': WALLET_ADDRESS,
        'startblock': 0,
        'endblock': 99999999,
        'sort': 'asc',
        'apikey': 'YourApiKeyToken'
    }

    print("📡 Récupération TX depuis BSCScan...")

    try:
        response = requests.get(url, params=params, timeout=30)
        data = response.json()

        if data.get('status') != '1':
            print(f"❌ Erreur BSCScan: {data.get('message')}")
            return positions

        txs = data.get('result', [])
        print(f"   ✅ {len(txs)} transactions récupérées\n")

        # Filtrer TX vers ApolloX
        apollox_txs = [
            tx for tx in txs
            if tx.get('to', '').lower() == APOLLOX_CONTRACT.lower()
        ]

        print(f"📊 {len(apollox_txs)} transactions ApolloX\n")

        # Parser chaque TX
        for i, tx in enumerate(apollox_txs, 1):
            tx_hash = tx['hash']
            timestamp = int(tx['timeStamp'])
            block_number = int(tx['blockNumber'])

            print(f"   [{i}/{len(apollox_txs)}] {tx_hash[:16]}...")

            try:
                # Récupérer le receipt
                receipt = w3.eth.get_transaction_receipt(tx_hash)

                # Chercher les events
                for log in receipt['logs']:
                    if log['address'].lower() != APOLLOX_CONTRACT.lower():
                        continue

                    topics = log['topics']
                    if len(topics) < 2:
                        continue

                    event_sig = topics[0].hex()

                    # Event d'ouverture de trade
                    if event_sig == OPEN_TRADE_EVENT:
                        # Extraire trade_hash
                        trade_hash = topics[1].hex()

                        # Décoder data (288 bytes = 9 slots)
                        data_bytes = log['data']
                        if isinstance(data_bytes, bytes):
                            data_hex = data_bytes.hex()
                        else:
                            data_hex = data_bytes[2:] if data_bytes.startswith('0x') else data_bytes

                        # Parser les slots (chaque 64 hex chars = 32 bytes)
                        slots = []
                        for j in range(0, len(data_hex), 64):
                            slot_hex = data_hex[j:j+64]
                            slots.append(int(slot_hex, 16))

                        # Extraire infos (structure dépend du contrat)
                        # Slots typiques:
                        # 0: pair address
                        # 1: pair index
                        # 2: token address
                        # 3: margin (wei)
                        # 4: leverage ou autre
                        # 5: price ou autre

                        if len(slots) >= 4:
                            margin_wei = slots[3]
                            margin_usdt = margin_wei / 1e18

                            # Prix BTC au moment du trade
                            entry_price = get_btc_price_at_block(block_number)

                            opened_at = datetime.fromtimestamp(timestamp).isoformat()

                            position = {
                                'trade_hash': trade_hash,
                                'tx_hash': tx_hash,
                                'symbol': 'BTCUSD_DEGEN',
                                'pair_address': '0xD89aE81e55b1Bd46591CB5555209fdF8fFb43b76',
                                'is_long': False,  # À déterminer depuis TX input
                                'margin': margin_usdt,
                                'leverage': 0,  # À calculer
                                'entry_price': entry_price or 0,
                                'qty': 0,
                                'stop_loss': 0,
                                'take_profit': 0,
                                'opened_at': opened_at,
                                'block_number': block_number,
                                'status': 'OPEN',
                                'closed_at': None,
                                'close_tx_hash': None,
                                'exit_price': None,
                                'pnl': None,
                                'pnl_pct': None,
                                'close_reason': None
                            }

                            positions[trade_hash] = position

                            print(f"      ✅ Trade ouvert: ${margin_usdt:.2f} @ ${entry_price or 0:,.0f}")

            except Exception as e:
                print(f"      ⚠️  Erreur: {e}")
                continue

        return positions

    except Exception as e:
        print(f"❌ Erreur: {e}")
        return positions


def main():
    """Main"""

    print("=" * 80)
    print("🔍 SCAN BLOCKCHAIN - POSITIONS APOLLOX")
    print("=" * 80)
    print()

    # Scan trades
    positions = scan_open_trades()

    if not positions:
        print("\n❌ Aucune position trouvée")
        return

    # Save
    data = {
        'positions': positions,
        'last_updated': datetime.now().isoformat(),
        'source': 'blockchain_scan'
    }

    with open('positions.json', 'w') as f:
        json.dump(data, f, indent=2)

    print()
    print("=" * 80)
    print(f"✅ {len(positions)} positions sauvegardées")
    print("=" * 80)


if __name__ == '__main__':
    main()
