# Sterling RFQ Bot Client
# Standard: public RFQ discovery -> 1492 claim construction -> optional wallet signing.
#
# Install:
#   python -m pip install requests solana solders
#
# Environment:
#   export STERLING_TARGET_FILL_USD=250
#   export STERLING_PAYMENT_RAIL=USDC
#   export STERLING_BOT_PRIVATE_KEY_BASE58=...
#   export SOLANA_RPC_URL=https://api.mainnet-beta.solana.com

import base64
import json
import os
import sys
from typing import Any, Dict

import requests

STERLING_SITE = os.getenv("STERLING_SITE", "https://sterlingchain.net").rstrip("/")
STERLING_API = os.getenv("STERLING_API", f"{STERLING_SITE}/api/v1/rfq").rstrip("/")
STERLING_NATIVE = os.getenv("STERLING_NATIVE", f"{STERLING_SITE}/rfq-native").rstrip("/")
SOLANA_RPC_URL = os.getenv("SOLANA_RPC_URL", "https://api.mainnet-beta.solana.com")
TARGET_FILL_USD = os.getenv("STERLING_TARGET_FILL_USD", "250")
PAYMENT_RAIL = os.getenv("STERLING_PAYMENT_RAIL", "USDC")
BOT_PRIVATE_KEY_BASE58 = os.getenv("STERLING_BOT_PRIVATE_KEY_BASE58", "")


def request_json(method: str, url: str, **kwargs: Any) -> Dict[str, Any]:
    response = requests.request(method, url, timeout=20, **kwargs)
    response.raise_for_status()
    return response.json()


def current_ticket() -> Dict[str, Any]:
    payload = request_json("GET", f"{STERLING_API}/current-sellable-ticket")
    if payload.get("ticket") and isinstance(payload["ticket"], dict):
        return payload["ticket"]
    return payload


def quote(ticket: Dict[str, Any]) -> Dict[str, Any]:
    body = {
        "order_id": ticket["order_id"],
        "tranche_id": ticket["tranche_id"],
        "fill_usd": TARGET_FILL_USD,
        "payment_rail": PAYMENT_RAIL,
    }
    return request_json("POST", f"{STERLING_API}/quote", json=body)


def build_claim(ticket: Dict[str, Any], wallet: str) -> Dict[str, Any]:
    body = {
        "bot_wallet": wallet,
        "order_id": ticket["order_id"],
        "tranche_id": ticket["tranche_id"],
        "fill_usd": TARGET_FILL_USD,
        "payment_rail": PAYMENT_RAIL,
    }
    return request_json("POST", f"{STERLING_NATIVE}/modular-claim-take", json=body)


def load_wallet_pubkey() -> str:
    if not BOT_PRIVATE_KEY_BASE58:
        return os.getenv("STERLING_BOT_PUBLIC_KEY", "")
    try:
        from solders.keypair import Keypair

        keypair = Keypair.from_base58_string(BOT_PRIVATE_KEY_BASE58)
        return str(keypair.pubkey())
    except Exception as exc:
        raise RuntimeError(f"Unable to load bot keypair: {exc}") from exc


def sign_and_send(transaction_base64: str) -> str:
    if not BOT_PRIVATE_KEY_BASE58:
        raise RuntimeError("STERLING_BOT_PRIVATE_KEY_BASE58 is not set; running in dry-run mode.")

    try:
        from solana.rpc.api import Client
        from solders.keypair import Keypair
        from solders.transaction import VersionedTransaction
    except Exception as exc:
        raise RuntimeError("Install solana and solders to sign locally: pip install solana solders") from exc

    keypair = Keypair.from_base58_string(BOT_PRIVATE_KEY_BASE58)
    tx_bytes = base64.b64decode(transaction_base64)
    tx = VersionedTransaction.from_bytes(tx_bytes)
    signed_tx = VersionedTransaction(tx.message, [keypair])
    client = Client(SOLANA_RPC_URL)
    result = client.send_raw_transaction(bytes(signed_tx))
    return str(result.value)


def main() -> None:
    print(f"[~] Sterling RFQ discovery fill_usd={TARGET_FILL_USD} rail={PAYMENT_RAIL}")
    ticket = current_ticket()
    print(f"[+] Ticket: {ticket.get('ticket_label')} order_id={ticket.get('order_id')}")
    print(f"[+] Tranche: {ticket.get('tranche_id')} accepted={ticket.get('accepted_child_tranches')}")

    quote_payload = quote(ticket)
    print("[+] Quote:")
    print(json.dumps(quote_payload, indent=2, sort_keys=True))

    wallet = load_wallet_pubkey()
    if not wallet:
        print("[!] No wallet configured. Set STERLING_BOT_PUBLIC_KEY for dry-run or STERLING_BOT_PRIVATE_KEY_BASE58 to sign.")
        sys.exit(0)

    claim = build_claim(ticket, wallet)
    print("[+] Claim package:")
    print(json.dumps({k: v for k, v in claim.items() if k != "transaction_base64"}, indent=2, sort_keys=True))

    transaction_base64 = claim.get("transaction_base64")
    if not transaction_base64:
        print("[!] No transaction_base64 returned by the claim endpoint.")
        sys.exit(1)

    if not BOT_PRIVATE_KEY_BASE58:
        print("[DRY-RUN] transaction_base64 received. Set STERLING_BOT_PRIVATE_KEY_BASE58 to sign and send.")
        sys.exit(0)

    signature = sign_and_send(transaction_base64)
    print(f"[+] Solana signature submitted: {signature}")
    print("[~] Submit the signature to verify-payment if your integration does not auto-submit it.")


if __name__ == "__main__":
    main()
