"""Decode conviction voting events from raw RPC log data."""
import json
import csv
import sys
from collections import defaultdict

DATA_DIR = sys.argv[1] if len(sys.argv) > 1 else "data/onchain"

with open("/tmp/cv_events.json") as f:
    d = json.load(f)
logs = d.get("result", [])

PROPOSAL_ADDED = "0xe180363919da754b2737a8f10869b7d2df0be7ef0e81339d3b5dabba166060ed"
STAKE_CHANGED = "0x28d9b583e0c477691a08f6c1e00fedc0895ed4221487c627fa96a7024119f499"
SUPPORT_CHANGED = "0x16f23283da3097bc9027dcdf31f24863b1520556f04818d406f0e6ecd08580f5"
PROPOSAL_EXECUTED = "0xf758fc91e01b00ea6b4a6138756f7f28e021f9bf21db6dbf8c36c88eb737257a"

by_topic = defaultdict(list)
for l in logs:
    by_topic[l["topics"][0]].append(l)

# --- Decode Proposals ---
proposals = {}
for l in by_topic[PROPOSAL_ADDED]:
    topics = l["topics"]
    prop_id = int(topics[2], 16)
    creator_int = int(topics[1], 16)
    creator = "0x" + hex(creator_int)[2:].zfill(40) if creator_int > 0 else "0x0"
    action_id = int(topics[3], 16)
    block = int(l["blockNumber"], 16)

    data = l["data"][2:]
    chunks = [data[i : i + 64] for i in range(0, len(data), 64)]

    amount = int(chunks[2], 16) / 1e18 if len(chunks) > 2 else 0
    stable = bool(int(chunks[3], 16)) if len(chunks) > 3 else False
    beneficiary_raw = chunks[4] if len(chunks) > 4 else ""
    beneficiary = "0x" + beneficiary_raw[24:] if beneficiary_raw else ""

    # Extract link/metadata
    link = ""
    if len(chunks) > 6:
        link_len = int(chunks[5], 16)
        if 0 < link_len < 200:
            link_hex = "".join(chunks[6 : 6 + (link_len + 31) // 32])
            try:
                link = bytes.fromhex(link_hex[: link_len * 2]).decode(
                    "utf-8", errors="replace"
                )
            except Exception:
                link = ""

    proposals[prop_id] = {
        "id": prop_id,
        "block": block,
        "tx_hash": l["transactionHash"],
        "creator": creator,
        "amount_requested": amount,
        "stable": stable,
        "beneficiary": beneficiary,
        "action_id": action_id,
        "link": link.strip("\x00"),
        "status": "open",
        "executed_block": "",
    }

# --- Executed proposals ---
for l in by_topic.get(PROPOSAL_EXECUTED, []):
    prop_id = int(l["topics"][1], 16)
    block = int(l["blockNumber"], 16)
    if prop_id in proposals:
        proposals[prop_id]["status"] = "executed"
        proposals[prop_id]["executed_block"] = block

# --- Check other event types for cancellation ---
other_topics = set(by_topic.keys()) - {
    PROPOSAL_ADDED,
    STAKE_CHANGED,
    SUPPORT_CHANGED,
    PROPOSAL_EXECUTED,
}
for t in other_topics:
    for l in by_topic[t]:
        if len(l["topics"]) > 1:
            try:
                prop_id = int(l["topics"][1], 16)
                if prop_id in proposals and proposals[prop_id]["status"] == "open":
                    proposals[prop_id]["status"] = "cancelled"
            except (ValueError, IndexError):
                pass

# --- Stakes ---
stakes = []
for l in by_topic[STAKE_CHANGED]:
    staker = "0x" + l["topics"][1][26:]
    prop_id = int(l["topics"][2], 16) if len(l["topics"]) > 2 else -1
    block = int(l["blockNumber"], 16)
    data = l["data"][2:]
    chunks = [data[i : i + 64] for i in range(0, min(len(data), 320), 64)]

    tokens_staked = int(chunks[0], 16) / 1e18 if chunks else 0
    total_staked = int(chunks[1], 16) / 1e18 if len(chunks) > 1 else 0
    conviction = int(chunks[2], 16) / 1e18 if len(chunks) > 2 else 0

    stakes.append(
        {
            "block": block,
            "tx_hash": l["transactionHash"],
            "staker": staker,
            "proposal_id": prop_id,
            "tokens_staked": tokens_staked,
            "total_tokens_staked": total_staked,
            "conviction": conviction,
        }
    )

# --- Support updates ---
supports = []
for l in by_topic[SUPPORT_CHANGED]:
    prop_id = int(l["topics"][1], 16)
    block = int(l["blockNumber"], 16)
    supports.append(
        {
            "block": block,
            "proposal_id": prop_id,
            "tx_hash": l["transactionHash"],
        }
    )

# Print summary
props_list = sorted(proposals.values(), key=lambda x: x["id"])
print("=== CONVICTION VOTING SUMMARY ===")
print(f"Total proposals: {len(props_list)}")
print(
    f"  Executed: {sum(1 for p in props_list if p['status']=='executed')}"
)
print(
    f"  Cancelled: {sum(1 for p in props_list if p['status']=='cancelled')}"
)
print(f"  Open: {sum(1 for p in props_list if p['status']=='open')}")
print(f"Stake events: {len(stakes)}")
print(f"Support updates: {len(supports)}")
print(f"Unique stakers: {len(set(s['staker'] for s in stakes))}")
total_requested = sum(p["amount_requested"] for p in props_list)
total_funded = sum(
    p["amount_requested"] for p in props_list if p["status"] == "executed"
)
print(f"Total requested: {total_requested:,.0f} tokens")
print(f"Total funded (executed): {total_funded:,.0f} tokens")

print(f"\n=== ALL PROPOSALS ===")
for p in props_list:
    if p["status"] == "executed":
        marker = "FUNDED"
    elif p["status"] == "cancelled":
        marker = "CANCEL"
    else:
        marker = "OPEN  "
    print(
        f'  {marker} #{p["id"]:2d} | {p["amount_requested"]:>10,.0f} tokens'
        f' | beneficiary: {p["beneficiary"][:16]}...'
        f' | link: {p["link"][:60]}'
    )

# Save CSVs
fields_p = [
    "id",
    "block",
    "tx_hash",
    "creator",
    "amount_requested",
    "stable",
    "beneficiary",
    "action_id",
    "link",
    "status",
    "executed_block",
]
with open(f"{DATA_DIR}/cv_proposals.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=fields_p, extrasaction="ignore")
    w.writeheader()
    for p in props_list:
        w.writerow(p)

fields_s = [
    "block",
    "tx_hash",
    "staker",
    "proposal_id",
    "tokens_staked",
    "total_tokens_staked",
    "conviction",
]
with open(f"{DATA_DIR}/cv_stakes.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=fields_s)
    w.writeheader()
    for s in stakes:
        w.writerow(s)

fields_u = ["block", "proposal_id", "tx_hash"]
with open(f"{DATA_DIR}/cv_support_updates.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=fields_u)
    w.writeheader()
    for s in supports:
        w.writerow(s)

print(f"\nSaved: cv_proposals.csv ({len(props_list)} rows)")
print(f"Saved: cv_stakes.csv ({len(stakes)} rows)")
print(f"Saved: cv_support_updates.csv ({len(supports)} rows)")
