#!/usr/bin/env python3
"""
LuckySt Syndicate - Base Hackathon Deploy Script

Runs locally — no Redis or Pi needed. Sends real transactions to Base
testnet so you can see them on BaseScan.

Two on-chain transactions:
  TX 1: Syndicate Pledge (EIP-712 signed pledge data as calldata)
  TX 2: Game Schedule Commitment (game config as calldata)

Usage:
    export LUCKYST_NETWORK=testnet
    export LUCKBOT_BASE_PRIVATE_KEY=ff0fbd2c...
    export LUCKBOT_BASE_ADDRESS=0x98F18D8F...

    python -m agentic.syndicate.hackathon_deploy
"""

import os
import sys
import json
import uuid
import asyncio
from datetime import datetime, timezone
from dataclasses import asdict

# Ensure project root is on path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))

os.environ.setdefault("LUCKYST_NETWORK", "testnet")

from eth_account import Account

from agentic.syndicate.chain_writer import (
    write_report_to_chain,
    BASE_CHAIN_ID,
    BASE_RPC_URL,
    LUCKYST_BUILDER_SUFFIX,
    _rpc_call,
)
from agentic.syndicate.pledge import (
    load_registry,
    save_registry,
    NETWORK,
)


# ---------------------------------------------------------------------------
# Config
# ---------------------------------------------------------------------------

AGENT_ID = "luckbot-trader-001"
ROLE = "trader"

BASE_ADDRESS = os.environ.get("LUCKBOT_BASE_ADDRESS", "")
BASE_PRIVATE_KEY = os.environ.get("LUCKBOT_BASE_PRIVATE_KEY", "")

EXPLORER_BASE = (
    "https://sepolia.basescan.org" if NETWORK == "testnet"
    else "https://basescan.org"
)

# Game schedule: VIT vs FNC LoL match, Feb 21 2026
GAMES = [
    {
        "markets": [
            "KXLOLGAME-26FEB21VITFNC-VIT",
            "KXLOLGAME-26FEB21VITFNC-FNC",
        ],
        "start_time": "2026-02-21T17:10:00Z",   # 12:10 PM EST
        "stop_time": "2026-02-21T17:40:00Z",     # 12:40 PM EST
        "contract_size": 3,
        "higher_first": False,
        "mode": "jump_and_join",
    },
]

# Local state file so cancel script can reference the schedule
STATE_FILE = os.path.join(os.path.dirname(__file__), ".hackathon_state.json")


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

async def check_eth_balance(address: str) -> float:
    """Check ETH balance via JSON-RPC (in ETH units)."""
    result = await _rpc_call("eth_getBalance", [address, "latest"])
    if "result" in result:
        wei = int(result["result"], 16)
        return wei / 1e18  # wei → ETH
    return 0.0


def save_state(data: dict):
    """Save state to local file for cancel script."""
    with open(STATE_FILE, "w") as f:
        json.dump(data, f, indent=2)
    print(f"  State saved: {STATE_FILE}")


# ---------------------------------------------------------------------------
# TX 1: Syndicate Pledge
# ---------------------------------------------------------------------------

async def do_pledge() -> tuple[bool, str | None]:
    """Sign and broadcast the Syndicate Pledge to Base."""
    print("\n" + "=" * 60)
    print("  TX 1: SYNDICATE PLEDGE ON BASE")
    print("=" * 60)
    print(f"  Agent:    {AGENT_ID}")
    print(f"  Address:  {BASE_ADDRESS}")
    print(f"  Network:  {NETWORK} (chain {BASE_CHAIN_ID})")

    try:
        # Build pledge payload
        now_ts = int(datetime.now(timezone.utc).timestamp())
        pledge_data = {
            "type": "syndicate_pledge",
            "version": 1,
            "agent_id": AGENT_ID,
            "role": ROLE,
            "pledge": (
                "I pledge my allegiance to the LuckySt Agentic Market Making "
                "Syndicate. Syndicate eternal. Spreads temporary. Edge ours."
            ),
            "base_address": BASE_ADDRESS,
            "chain_id": BASE_CHAIN_ID,
            "timestamp": now_ts,
        }

        # Also sign EIP-712 for the signature record
        pledge_message = {
            "types": {
                "EIP712Domain": [
                    {"name": "name", "type": "string"},
                    {"name": "version", "type": "string"},
                    {"name": "chainId", "type": "uint256"},
                ],
                "SyndicatePledge": [
                    {"name": "agentId", "type": "string"},
                    {"name": "role", "type": "string"},
                    {"name": "pledge", "type": "string"},
                    {"name": "timestamp", "type": "uint256"},
                ],
            },
            "primaryType": "SyndicatePledge",
            "domain": {
                "name": "LuckySt Syndicate",
                "version": "1",
                "chainId": BASE_CHAIN_ID,
            },
            "message": {
                "agentId": AGENT_ID,
                "role": ROLE,
                "pledge": pledge_data["pledge"],
                "timestamp": now_ts,
            },
        }

        signed_typed = Account.sign_typed_data(
            BASE_PRIVATE_KEY,
            full_message=pledge_message,
        )
        pledge_data["eip712_signature"] = "0x" + signed_typed.signature.hex()

        print(f"  EIP-712 sig: {pledge_data['eip712_signature'][:20]}...")

        # Encode and send as on-chain self-transfer
        # Prefix byte 0x01 = pledge
        payload_bytes = b"\x01" + json.dumps(pledge_data).encode("utf-8")

        print("  Broadcasting pledge to Base...")
        result = await write_report_to_chain(
            payload_bytes, BASE_PRIVATE_KEY, BASE_ADDRESS
        )

        if result.success and result.tx_hash:
            print(f"  TX Hash:  {result.tx_hash}")
            print(f"  Block:    {result.block_number}")
            print(f"  Gas:      {result.gas_used}")
            print(f"  Explorer: {EXPLORER_BASE}/tx/{result.tx_hash}")

            # Register in registry.yaml
            try:
                registry = load_registry()
                if registry["agents"] is None:
                    registry["agents"] = []
                existing = [a for a in registry["agents"] if a["id"] == AGENT_ID]
                if not existing:
                    registry["agents"].append({
                        "id": AGENT_ID,
                        "role": ROLE,
                        "base_address": BASE_ADDRESS,
                        "pledge_tx": result.tx_hash,
                        "joined": datetime.now(timezone.utc).isoformat(),
                        "status": "active",
                    })
                    save_registry(registry)
                    print(f"  Registered {AGENT_ID} in registry.yaml")
            except Exception as e:
                print(f"  Registry update skipped: {e}")

            print("  PLEDGE ON-CHAIN")
            return True, result.tx_hash
        else:
            print(f"  FAILED: {result.error}")
            return False, None

    except Exception as e:
        print(f"  FAILED: {e}")
        import traceback
        traceback.print_exc()
        return False, None


# ---------------------------------------------------------------------------
# TX 2: Game Schedule Commitment
# ---------------------------------------------------------------------------

async def do_schedule() -> tuple[bool, str | None]:
    """Commit game schedule to Base."""
    print("\n" + "=" * 60)
    print("  TX 2: GAME SCHEDULE COMMITMENT ON BASE")
    print("=" * 60)

    schedule_id = str(uuid.uuid4())[:8]

    for game in GAMES:
        print(f"  Markets:   {', '.join(game['markets'])}")
        print(f"  Deploy:    {game['start_time']} (12:10 PM EST)")
        print(f"  Stop:      {game['stop_time']} (12:40 PM EST)")
        print(f"  Contracts: {game['contract_size']} per side")
        print(f"  Mode:      {game['mode']}")

    try:
        schedule_data = {
            "type": "game_schedule",
            "version": 1,
            "schedule_id": schedule_id,
            "agent_id": AGENT_ID,
            "base_address": BASE_ADDRESS,
            "chain_id": BASE_CHAIN_ID,
            "created_at": datetime.now(timezone.utc).isoformat(),
            "games": GAMES,
        }

        # Prefix byte 0x02 = schedule
        payload_bytes = b"\x02" + json.dumps(schedule_data).encode("utf-8")

        print(f"\n  Schedule ID: {schedule_id}")
        print("  Broadcasting schedule to Base...")
        result = await write_report_to_chain(
            payload_bytes, BASE_PRIVATE_KEY, BASE_ADDRESS
        )

        if result.success and result.tx_hash:
            print(f"  TX Hash:  {result.tx_hash}")
            print(f"  Block:    {result.block_number}")
            print(f"  Gas:      {result.gas_used}")
            print(f"  Explorer: {EXPLORER_BASE}/tx/{result.tx_hash}")
            print("  SCHEDULE ON-CHAIN")
            return True, result.tx_hash
        else:
            print(f"  FAILED: {result.error}")
            return False, None

    except Exception as e:
        print(f"  FAILED: {e}")
        import traceback
        traceback.print_exc()
        return False, None


# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------

async def main():
    print("""
    ██╗     ██╗   ██╗ ██████╗██╗  ██╗██╗   ██╗███████╗████████╗
    ██║     ██║   ██║██╔════╝██║ ██╔╝╚██╗ ██╔╝██╔════╝╚══██╔══╝
    ██║     ██║   ██║██║     █████╔╝  ╚████╔╝ ███████╗   ██║
    ██║     ██║   ██║██║     ██╔═██╗   ╚██╔╝  ╚════██║   ██║
    ███████╗╚██████╔╝╚██████╗██║  ██╗   ██║   ███████║   ██║
    ╚══════╝ ╚═════╝  ╚═════╝╚═╝  ╚═╝   ╚═╝   ╚══════╝   ╚═╝

         B A S E   H A C K A T H O N   D E P L O Y
    """)

    if not BASE_ADDRESS or not BASE_PRIVATE_KEY:
        print("ERROR: Set LUCKBOT_BASE_ADDRESS and LUCKBOT_BASE_PRIVATE_KEY")
        sys.exit(1)

    # Check balance
    balance = await check_eth_balance(BASE_ADDRESS)
    print(f"  Wallet:  {BASE_ADDRESS}")
    print(f"  ETH:     {balance:.6f}")

    if balance <= 0:
        print("\n  ERROR: No ETH balance. Fund from faucet:")
        print("  https://www.coinbase.com/faucets/base-ethereum-goerli-faucet")
        print(f"  Send testnet ETH to: {BASE_ADDRESS}")
        sys.exit(1)

    # TX 1: Pledge
    pledge_ok, pledge_tx = await do_pledge()

    # TX 2: Schedule
    schedule_ok, schedule_tx = await do_schedule()

    # Save state for cancel script
    state = {
        "agent_id": AGENT_ID,
        "base_address": BASE_ADDRESS,
        "network": NETWORK,
        "pledge_tx": pledge_tx,
        "schedule_tx": schedule_tx,
        "games": GAMES,
        "deployed_at": datetime.now(timezone.utc).isoformat(),
    }
    save_state(state)

    # Summary
    print("\n" + "=" * 60)
    print("  HACKATHON DEPLOY COMPLETE")
    print("=" * 60)
    print(f"  Pledge TX:    {'OK' if pledge_ok else 'FAILED'}")
    print(f"  Schedule TX:  {'OK' if schedule_ok else 'FAILED'}")
    print()

    if pledge_tx:
        print(f"  View Pledge:    {EXPLORER_BASE}/tx/{pledge_tx}")
    if schedule_tx:
        print(f"  View Schedule:  {EXPLORER_BASE}/tx/{schedule_tx}")

    print(f"\n  Cancel with:    python -m agentic.syndicate.hackathon_cancel")

    if pledge_ok and schedule_ok:
        print("\n  Syndicate eternal. Spreads temporary. Edge ours.")
        print("  LuckBot Trader is GO for VIT vs FNC at 12:10 PM EST")
    print()


if __name__ == "__main__":
    asyncio.run(main())
