from __future__ import annotations

import argparse
import json
from datetime import datetime, timezone
from decimal import Decimal
from pathlib import Path

from src.execution.size_impact_curve import analyze_size_curve
from src.hyperliquid.market_data import HyperliquidMarketData

DEFAULT_OUTPUT = Path("runtime/research/l2_size_impact_latest.json")
DEFAULT_HISTORY = Path("runtime/research/l2_size_impact_history.jsonl")


def collect(*, coins: list[str], notionals: tuple[Decimal, ...], expected_move_pct: Decimal, risk_budget_usd: Decimal, stop_distance_pct: Decimal, md: HyperliquidMarketData | None = None) -> dict:
    source = md or HyperliquidMarketData("mainnet")
    reports, errors = {}, {}
    for coin in coins:
        try:
            reports[coin] = analyze_size_curve(source.get_l2_book(coin), notionals=notionals, expected_move_pct=expected_move_pct, risk_budget_usd=risk_budget_usd, stop_distance_pct=stop_distance_pct)
        except Exception as exc:
            errors[coin] = type(exc).__name__
    return {"schema_version": "l2_size_impact_collection.v1", "timestamp": datetime.now(timezone.utc).isoformat(), "source_id": "hyperliquid_mainnet_readonly_l2", "coins": reports, "errors": errors, "read_only": True, "paper_research_only": True, "live_order_allowed": False, "mainnet_signed_action": False}


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description="Collect read-only L2 size-impact curves; never places orders.")
    parser.add_argument("--coins", default="BTC,ETH,SOL,LINK")
    parser.add_argument("--notionals", default="10,15,25,50,100")
    parser.add_argument("--expected-move-pct", default="0.80")
    parser.add_argument("--risk-budget-usd", default="0.075")
    parser.add_argument("--stop-distance-pct", default="0.75")
    parser.add_argument("--output", default=str(DEFAULT_OUTPUT))
    parser.add_argument("--history", default=str(DEFAULT_HISTORY))
    parser.add_argument("--json", action="store_true")
    args = parser.parse_args(argv)
    payload = collect(coins=[value.strip().upper() for value in args.coins.split(",") if value.strip()], notionals=tuple(Decimal(value.strip()) for value in args.notionals.split(",") if value.strip()), expected_move_pct=Decimal(args.expected_move_pct), risk_budget_usd=Decimal(args.risk_budget_usd), stop_distance_pct=Decimal(args.stop_distance_pct))
    output, history = Path(args.output), Path(args.history)
    output.parent.mkdir(parents=True, exist_ok=True)
    tmp = output.with_suffix(output.suffix + ".tmp")
    tmp.write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8")
    tmp.replace(output)
    history.parent.mkdir(parents=True, exist_ok=True)
    with history.open("a", encoding="utf-8") as handle:
        handle.write(json.dumps(payload, sort_keys=True) + "\n")
    if args.json:
        print(json.dumps(payload, sort_keys=True))
    return 0 if payload["coins"] else 1


if __name__ == "__main__":
    raise SystemExit(main())
