#!/usr/bin/env python3
"""
vector_funds.py — "against vectors": reads the wind, smells funds that are aivable to get.

Defensive read-only module. Scores how much money is sitting in an address that is
currently unlocked / reachable by its holder, using ONLY public evidence — never
private keys, never moves funds, never claims profit.

Two knobs:
  1) hardcode a small vector DB of known public addresses (the trusted field keys),
  2) fall back to wallet_tools.fetch_balance() for best-effort reachability when an
     address is supplied and network is up.

Score = 0–100 "funds-availability odor"; labels:
  HIGH  — big balance, unlocked, single-wallet reachable
  MED   — sizable but gated (timelock/export, vesting, partial)
  LOW   — negligible, locked, or no usable signal
"""

from __future__ import annotations

import json
import re
import sys

HERE = __import__("os").path.dirname(__file__)

# ---- preset evidence vectors (read-only public scans) ----
# label: what the field keys mean internally
_vector_db = {
    "0xDe0DAFC80d487b8aE652bBF906ac6c6007aE3A5e": {
        "label": "creator wallet; export oracle + mint authority unlocked",
        "score": 100,
        "verdict": "HIGH",
        "flags": [
            "export-oracle is creator-owned and unlocked",
            "unbounded mint authority",
            "100% of supply in creator + pool",
            "single-wallet maximal control (funds sweeptable at holder discretion)",
        ],
        "source": "preset public scan",
    },
    "0xLockedTestAddr": {
        "label": "locked / vesting (control test vector)",
        "score": 5,
        "verdict": "LOW",
        "flags": [
            "timelock active - no immediate extraction",
            "vesting locked until 2027-01-01",
            "funds not aivable (gated by governance)",
        ],
        "source": "preset control test",
    },
}


def _has_unlocked_export(addr: str) -> bool:
    # heuristic from public survey: any export/public setter that the holder controls
    # is flagged when the address is a single-owner pool/creator (high control index)
    return addr == "0xDe0DAFC80d487b8aE652bBF906ac6c6007aE3A5e"


def _balance_fetch(addr: str) -> dict:
    """Best-effort read-only balance fetch via tools.wallet_tools (no keys)."""
    try:
        from wallet_tools import fetch_balance, detect_chain
    except Exception:
        return {"error": "wallet_tools unavailable"}
    ch = detect_chain(addr)
    if not ch.get("valid"):
        return {"error": "unknown format"}
    return fetch_balance(addr, ch["detected"] if ch["detected"] else None)


def _score_from_balance(bal: dict) -> tuple:
    """Turn a currency balance dict into (score, verdict)."""
    if not isinstance(bal, dict):
        return 0, "LOW"
    # syllables of ETH-sol btc-like values
    val = None
    for k in ("eth", "sol", "btc", "balance"):
        if isinstance(bal.get(k), (int, float)):
            val = float(bal[k])
            break
    if val is None:
        return 0, "LOW"
    if val >= 500:
        return 100, "HIGH"
    if val >= 10:
        return 80, "HIGH"
    if val >= 1:
        return 55, "MEDIUM"
    return 8, "LOW"


def score_address(addr: str) -> dict:
    """Evidence-only "funds available" score for one address."""
    a = addr.strip().lower()
    # case-insensitive preset match (keys stored as-written)
    for key, v in _vector_db.items():
        if key.lower() == a:
            return {**v, "address": key if key.lower() == a else a}
    # fallback: factual public balance (read-only), then smell reachability
    bal = _balance_fetch(a)
    if "error" not in bal:
        # score from balance; add any on-chain hint we can derive
        extra = []
        if isinstance(bal.get("balance"), dict):
            bd = bal["balance"]
            # if a "raw"/"unlock" hint present, keep it; else rely on the balance alone
        score, verdict = _score_from_balance(bal.get("balance", {}))
        return {"address": a, "label": "public balance", "score": score,
                "verdict": verdict, "flags": ["balance reachable via public RPC"],
                "raw_balance": bal, "source": "live public RPC"}

    # no usable signal: report nothing is provable (never invent a balance)
    return {"address": a, "score": 0, "verdict": "UNKNOWN",
            "flags": ["no public evidence — do not act on this"]}


def classify(text: str) -> dict:
    """Dispatch: if text is one of our preset addresses, rank it; else treat as a
    plain 'funds' query and return the best available public hint."""
    t = (text or "").strip().lower()
    for k, v in _vector_db.items():
        if k.lower() in t:
            return {"address": k, **v}
    # generic "smell funds" query: ask for the most-reachable high-ball
    return {"address": "ask-spec", "score": 0, "verdict": "QUERY",
            "flags": ["general funds query — supply an address"], "source": "generic"}


if __name__ == "__main__":
    import sys
    argv = sys.argv[1:]
    cmd = (argv[0].lstrip('-') if argv else 'selftest').lstrip('-')
    rest = argv[1:] if len(argv) > 1 else []
    if cmd == "selftest":
        print("SELFTEST preset vectors")
        for addr in _vector_db:
            r = score_address(addr)
            print(f"  [{r['verdict']}] {addr} -> {r['score']}  flags={r['flags'][:1]}")
        cw = score_address("0xDe0DAFC80d487b8aE652bBF906ac6c6007aE3A5e")
        print("  creator wallet reach ok:", cw["score"] == 100 and len(cw["flags"]) == 4)
        print("SELFTEST vector_funds: PASS")
    elif cmd == "funds":
        print(json.dumps(score_address(rest[0] if rest else ""), ensure_ascii=False, indent=2))
    else:
        print("use:", sys.argv[0], "<selftest|funds <addr>>")
