import argparse
import time
import json
from pathlib import Path
import os

from dotenv import load_dotenv

from .info import query_info
from .exchange import exchange_order
from .wallet import init_wallet
from .secrets import get_env_path, init_env_file

def load_env(override: bool = False) -> bool:
    """
    Load the OpenClaw state `.env` file (path来自 `secrets.get_env_path()`).
    """

    # Ensure state directory + .env exists (create empty file if needed).
    init_env_file()
    env_path = get_env_path()

    # Load via python-dotenv (supports override/interpolation)
    success = load_dotenv(env_path, override=override)

    if success:
        print(f"Loaded OpenClaw env: {env_path}")
    else:
        print(f"Failed to load or empty: {env_path}")

    return success


def str2bool(v):
    if isinstance(v, bool):
        return v
    if v.lower() in ("yes", "true", "t", "1"):
        return True
    elif v.lower() in ("no", "false", "f", "0"):
        return False
    else:
        raise argparse.ArgumentTypeError("Boolean value expected.")


def main():
    parser = argparse.ArgumentParser(description="Hyperliquid SDK full-feature CLI (HIP-3 supported)")
    parser.add_argument("--testnet", action="store_true", help="Use testnet")

    subparsers = parser.add_subparsers(dest="command", required=True)

    # ==================== query cli params====================
    subparsers.add_parser("query-user-state", help="Query user state (positions + balances)").add_argument(
        "--address", help="Optional address (derived from private key by default)"
    )
    subparsers.add_parser("query-open-orders", help="Query open orders")
    subparsers.add_parser("query-fills", help="Query fills / trade history")
    subparsers.add_parser("query-meta", help="Query asset metadata (all symbols)")
    subparsers.add_parser("query-mids", help="Query mid prices (all symbols)")

    # define K line params
    query_kline = subparsers.add_parser("query-kline", help="Query kline/candles for a symbol")
    query_kline.add_argument("--coin", required=True, help="Symbol, e.g. BTC or xyz:TSLA")
    query_kline.add_argument(
        "--period",
        required=True,
        help="Kline period: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 8h, 12h, 1d, 3d, 1w, 1M",
    )
    # default start and end
    end = int(time.time() * 1000)
    start = end - 86400000
    query_kline.add_argument("--start", default=start, type=int, help="Start time (ms). Default: last 24 hours")
    query_kline.add_argument("--end", type=int, default=end, help="End time (ms). Default: now")

    # ==================== trade cli params ====================
    order_parser = subparsers.add_parser("place-order", help="Place a limit order (HIP-3 supported)")
    order_parser.add_argument("--coin", required=True, help="Symbol, e.g. BTC or xyz:TSLA")
    order_parser.add_argument("--is-buy", type=str2bool, required=True, help="True=buy (long), False=sell (short)")
    order_parser.add_argument("--qty", type=float, required=True, help="Size/quantity")
    order_parser.add_argument("--limit-px", type=float, required=True, help="Limit price")
    order_parser.add_argument("--tif", choices=["Gtc", "Ioc", "Alo"], default="Gtc", help="Time in force")
    order_parser.add_argument("--reduce-only", action="store_true", help="Reduce-only")

    market_parser = subparsers.add_parser("market-order", help="Place a market order (recommended for HIP-3)")
    market_parser.add_argument("--coin", required=True, help="Symbol, e.g. BTC or xyz:TSLA")
    market_parser.add_argument("--is-buy", type=str2bool, required=True, help="True=buy (long), False=sell (short)")
    market_parser.add_argument("--qty", required=True, type=float, help="Size/quantity")
    market_parser.add_argument("--slippage", type=float, default=0.02, help="Slippage tolerance (default: 2%)")

    market_close_parser = subparsers.add_parser("market-close", help="Close a position with a market order (recommended for HIP-3)")
    market_close_parser.add_argument("--coin", required=True, help="Symbol, e.g. BTC or xyz:TSLA")
    market_close_parser.add_argument("--qty", required=True, type=float, help="Size/quantity")
    market_close_parser.add_argument("--slippage", type=float, default=0.02, help="Slippage tolerance (default: 2%)")

    cancel_parser = subparsers.add_parser("cancel-order", help="Cancel orders")
    cancel_parser.add_argument("--oid", type=int, help="Order ID")
    cancel_parser.add_argument("--coin", help="Symbol, e.g. BTC or xyz:TSLA")

    lev_parser = subparsers.add_parser("update-leverage", help="Update leverage")
    lev_parser.add_argument("--coin", required=True, help="Symbol")
    lev_parser.add_argument("--leverage", type=int, required=True, help="Leverage (integer)")
    lev_parser.add_argument("--is-cross", type=str2bool, default=True, help="True=cross margin")

    iso_margin_parser = subparsers.add_parser("update-isolated-margin", help="Transfer isolated margin for HIP-3")
    iso_margin_parser.add_argument("--amount", type=int, required=True, help="Transfer amount")
    iso_margin_parser.add_argument("--coin", required=True, help="Symbol, e.g. BTC or xyz:TSLA")

    # ==================== wallet cli params ====================
    init_wallet_parser = subparsers.add_parser("init-wallet", help="Init wallet with user-provided address + private key")
    init_wallet_parser.add_argument("--address", required=False, help="Optional wallet public address (0x...). If omitted, derive from --pri_key")
    init_wallet_parser.add_argument("--pri_key", required=True, help="Wallet private key (0x...)")

    # Backward/compat alias (underscore version)
    init_wallet_alias_parser = subparsers.add_parser("init_wallet", help="Alias of init-wallet")
    init_wallet_alias_parser.add_argument("--address", required=False, help="Optional wallet public address (0x...). If omitted, derive from --pri_key")
    init_wallet_alias_parser.add_argument("--pri_key", required=True, help="Wallet private key (0x...)")

    args = parser.parse_args()
    needs_env = args.command not in {"init-wallet", "init_wallet"}
    env_loaded = True
    if needs_env:
        env_loaded = load_env()

    # about query
    if args.command.startswith("query-"):
        if env_loaded is False:
            print("Warning: env file not found (required for querying)")
            return
        result = query_info(parser=parser)
        print(json.dumps(result, indent=2, default=str))
        return

    # about trade
    if args.command in [
        "place-order",
        "market-order",
        "cancel-order",
        "update-leverage",
        "market-close",
        "update-isolated-margin",
    ]:
        if env_loaded is False:
            print("Warning: env file not found (required for trading)")
            return
        result = exchange_order(parser)
        print(json.dumps(result, indent=2, default=str))
        return

    # about wallet
    if args.command in {"init-wallet", "init_wallet"}:
        init_wallet(args.address, args.pri_key)
        return

if __name__ == "__main__":
    main()

