#!/usr/bin/env python3
"""
Scanne l'historique du wallet en parcourant les blocks récents
SOLUTION AUTOMATIQUE ULTIME
"""

from web3 import Web3
import json
from datetime import datetime
import os
from dotenv import load_dotenv

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 trouvées
OPEN_TRADE_EVENT = "0x7064b82c073f138da0ec7646ebb51d4a0061d647accb4670bc564edf0bfac41d"


def find_wallet_transactions(max_blocks=10000):
    """
    Parcourt les blocks récents pour trouver les TX du wallet
    """

    current_block = w3.eth.block_number
    start_block = current_block - max_blocks

    print(f"🔍 Scan des blocks {start_block:,} à {current_block:,}...")
    print(f"   Wallet: {WALLET_ADDRESS}")
    print(f"   Target: {APOLLOX_CONTRACT}\n")

    wallet_lower = WALLET_ADDRESS.lower()
    apollox_lower = APOLLOX_CONTRACT.lower()

    transactions = []

    # Scanner par chunks
    chunk_size = 100

    for block_num in range(current_block, start_block, -chunk_size):
        start = max(block_num - chunk_size + 1, start_block)
        end = block_num

        if (current_block - block_num) % 1000 == 0:
            print(f"   Block {block_num:,} ({current_block - block_num:,} blocks scannés)...")

        try:
            for bn in range(end, start - 1, -1):
                block = w3.eth.get_block(bn, full_transactions=True)

                for tx in block['transactions']:
                    # TX depuis notre wallet vers ApolloX
                    if (tx['from'].lower() == wallet_lower and
                        tx['to'] and tx['to'].lower() == apollox_lower):

                        transactions.append({
                            'hash': tx['hash'].hex(),
                            'blockNumber': block['number'],
                            'timestamp': block['timestamp'],
                            'from': tx['from'],
                            'to': tx['to'],
                        })

                        print(f"      ✅ TX trouvée: {tx['hash'].hex()[:16]}... (block {block['number']:,})")

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

    return transactions


def parse_tx_events(tx_hash: str):
    """Parse les events d'une transaction"""

    try:
        receipt = w3.eth.get_transaction_receipt(tx_hash)

        # Filtrer events ApolloX
        apollox_events = []

        for log in receipt['logs']:
            if log['address'].lower() == APOLLOX_CONTRACT.lower():
                apollox_events.append(log)

        # Chercher l'event OpenTrade
        for log in apollox_events:
            if len(log['topics']) > 0 and log['topics'][0].hex() == OPEN_TRADE_EVENT:
                # Parser les données
                return parse_open_trade_event(log, receipt)

        return None

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


def parse_open_trade_event(log: dict, receipt: dict):
    """Parse un event OpenTrade"""

    # Topics
    topics = log['topics']
    wallet_topic = topics[1].hex() if len(topics) > 1 else None

    # Data
    data = log['data']
    if isinstance(data, bytes):
        data_hex = data.hex()
    else:
        data_hex = data[2:] if data.startswith('0x') else data

    # Parser slots (9 slots de 32 bytes)
    slots = []
    for i in range(0, min(len(data_hex), 576), 64):
        slot_hex = data_hex[i:i+64]
        if len(slot_hex) == 64:
            slots.append(int(slot_hex, 16))

    if len(slots) < 4:
        return None

    # Trouver le trade_hash depuis les autres logs
    trade_hash = None
    for other_log in receipt['logs']:
        if (other_log['address'].lower() == APOLLOX_CONTRACT.lower() and
            other_log != log and len(other_log['topics']) > 1):
            potential_hash = other_log['topics'][1].hex()
            if potential_hash != wallet_topic and len(potential_hash) == 66:
                trade_hash = potential_hash[2:]
                break

    if not trade_hash:
        trade_hash = receipt['transactionHash'].hex()[2:]

    # Extraction données
    pair_address = f"0x{slots[0]:040x}"
    is_long = bool(slots[1])
    token_address = f"0x{slots[2]:040x}"
    margin_wei = slots[3]
    margin = margin_wei / 1e18

    # Timestamp
    block = w3.eth.get_block(receipt['blockNumber'])
    timestamp = block['timestamp']
    opened_at = datetime.fromtimestamp(timestamp).isoformat()

    return {
        'trade_hash': trade_hash,
        'tx_hash': receipt['transactionHash'].hex(),
        'symbol': 'BTCUSD_DEGEN',
        'pair_address': pair_address,
        'is_long': is_long,
        'margin': margin,
        'leverage': 0,
        'entry_price': 0,
        'qty': 0,
        'stop_loss': 0,
        'take_profit': 0,
        'opened_at': opened_at,
        'block_number': receipt['blockNumber'],
        'status': 'OPEN',
        'closed_at': None,
        'close_tx_hash': None,
        'exit_price': None,
        'pnl': None,
        'pnl_pct': None,
        'close_reason': None,
        'token_address': token_address,
    }


def main():
    print("=" * 80)
    print("📥 SCAN HISTORIQUE WALLET -> APOLLOX")
    print("=" * 80)
    print()

    # 1. Trouver les TX
    print("🔍 Recherche des transactions...\n")

    transactions = find_wallet_transactions(max_blocks=10000)  # ~8h sur BSC

    print(f"\n✅ {len(transactions)} transactions trouvées\n")

    if not transactions:
        print("❌ Aucune transaction trouvée")
        return

    # 2. Parser chaque TX
    print("📊 Parsing des positions...\n")

    positions = {}

    for i, tx in enumerate(transactions, 1):
        print(f"   [{i}/{len(transactions)}] {tx['hash'][:16]}...")

        position = parse_tx_events(tx['hash'])

        if position:
            trade_hash = position['trade_hash']
            positions[trade_hash] = position

            print(f"      ✅ Position: ${position['margin']:.2f} USDT")
        else:
            print(f"      ⚠️  Pas de position")

    # 3. Sauvegarder
    print("\n" + "=" * 80)
    print("💾 SAUVEGARDE")
    print("=" * 80)

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

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

    print(f"\n✅ {len(positions)} positions sauvegardées")
    print(f"\n✅ Dashboard: http://localhost:8889")


if __name__ == '__main__':
    main()
