from pathlib import Path
import subprocess


ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "scripts" / "run.ps1"
LIVE_AI_BATCH_BAT = ROOT / "scripts" / "live-ai-trade-batch-once.bat"
README = ROOT / "README.md"


def test_run_script_exists_with_safe_defaults():
    text = SCRIPT.read_text(encoding="utf-8")

    assert (
        "[ValidateSet(\"quote\", \"dry-run-order\", \"orders\", \"trade-loop\", "
        "\"testnet-sell-quote\", \"live-preflight\", \"live-sell-quote-preflight\", \"live-sell-quote\", "
        "\"live-auto-buy-once\", \"live-auto-sell-once\", \"live-ai-trade-once\", \"live-ai-trade-batch-once\", "
        "\"live-futures-ai-trade-batch-once\")]"
    ) in text
    assert '$Action = "dry-run-order"' in text
    assert "-Live" not in text
    assert "TradingMode.DRY_RUN" in text
    assert "Refusing" in text


def test_run_script_explains_binance_451_errors():
    text = SCRIPT.read_text(encoding="utf-8")

    assert "except httpx.HTTPStatusError as exc" in text
    assert "status_code == 451" in text
    assert "restricted location" in text
    assert "proxy" in text


def test_run_script_selects_best_rest_endpoint_from_configured_candidates():
    text = SCRIPT.read_text(encoding="utf-8")

    assert "def select_rest_base_url(settings, http_client=None):" in text
    assert "for base_url in settings.rest_base_urls:" in text
    assert 'base_url = base_url.rstrip("/")' in text
    assert 'base_url + "/v3/time"' in text
    assert "base = select_rest_base_url(settings)" in text
    assert "selected_rest_base_url = client.base_url" in text
    assert "base_urls=settings.rest_base_urls" in text


def test_run_script_does_not_reuse_server_time_for_signed_requests():
    text = SCRIPT.read_text(encoding="utf-8")

    assert "timestamp_ms=server_time_ms" not in text
    assert "client.account(timestamp_ms=server_time_ms)" not in text
    assert "create_market_order_with_server_time" not in text


def test_run_script_clears_proxy_environment():
    text = SCRIPT.read_text(encoding="utf-8")

    for name in ("HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"):
        assert f'"{name}"' in text
    assert 'Remove-Item "Env:$ProxyVariable"' in text
    assert "$env:NO_PROXY" in text
    assert "$env:no_proxy" in text
    assert "testnet.binance.vision" in text
    assert "stream.binance.com" in text


def test_run_script_has_confirmed_testnet_sell_action():
    text = SCRIPT.read_text(encoding="utf-8")

    assert "[switch]$ConfirmTestnetOrder" in text
    assert "[switch]$ConfirmLiveOrder" in text
    assert "[decimal]$SellQuoteAmount = 5" in text
    assert '"testnet-sell-quote"' in text
    assert "OrderSide.SELL" in text
    assert "TradingMode.TESTNET_LIVE" in text
    assert '"/v3/time"' in text
    assert "account = client.account()" in text
    assert "ExecutionEngine(TradingMode.TESTNET_LIVE, client).execute(intent)" in text
    assert "last_price=last_price" in text
    assert '"/v3/ticker/price"' in text
    assert "Refusing Testnet SELL" in text


def test_run_script_has_live_preflight_and_confirmed_sell_actions():
    text = SCRIPT.read_text(encoding="utf-8")

    assert '"live-preflight"' in text
    assert '"live-sell-quote-preflight"' in text
    assert '"live-sell-quote"' in text
    assert "[switch]$UseSystemProxy" in text
    assert "TradingMode.LIVE" in text
    assert "Refusing live preflight" in text
    assert "Refusing live SELL" in text
    assert "/v3/order/test" in text
    assert "accepted_without_matching" in text
    assert "ConfirmLiveOrder is required for live-sell-quote" in text
    assert "https://api.binance.com/api" in text
    assert "wss://stream.binance.com:9443/ws" in text
    assert "client_order_id = \"bqls-\" + uuid.uuid4().hex[:24]" in text
    assert "storage.record_order_result(result)" in text


def test_run_script_has_live_auto_buy_once_action():
    text = SCRIPT.read_text(encoding="utf-8")

    assert '"live-auto-buy-once"' in text
    assert "Invoke-BinanceQuant live-auto-buy-once" in text
    assert "Refusing live auto buy because BINANCE_MODE" in text
    assert "BINANCE_LIVE_AUTO_BUYER_ENABLED is false" in text
    assert text.index("BINANCE_LIVE_AUTO_BUYER_ENABLED is false") < text.index("Invoke-BinanceQuant live-auto-buy-once")


def test_run_script_has_live_auto_sell_once_action():
    text = SCRIPT.read_text(encoding="utf-8")

    assert '"live-auto-sell-once"' in text
    assert "Invoke-BinanceQuant live-auto-sell-once" in text
    assert "Refusing live auto sell because BINANCE_MODE" in text
    assert "BINANCE_LIVE_AUTO_SELLER_ENABLED is false" in text
    assert text.index("BINANCE_LIVE_AUTO_SELLER_ENABLED is false") < text.index("Invoke-BinanceQuant live-auto-sell-once")


def test_run_script_has_live_ai_trade_once_action():
    text = SCRIPT.read_text(encoding="utf-8")

    assert '"live-ai-trade-once"' in text
    assert "Invoke-BinanceQuant live-ai-trade-once" in text
    assert "Refusing live AI trade because BINANCE_MODE" in text
    assert "BINANCE_LIVE_AI_TRADER_ENABLED is false" in text
    assert text.index("BINANCE_LIVE_AI_TRADER_ENABLED is false") < text.index("Invoke-BinanceQuant live-ai-trade-once")


def test_run_script_has_live_ai_trade_batch_once_action():
    text = SCRIPT.read_text(encoding="utf-8")

    assert '"live-ai-trade-batch-once"' in text
    assert "Invoke-BinanceQuant live-ai-trade-batch-once" in text
    assert "uv --project $ProjectRoot run binance-quant @Arguments" in text
    assert "Refusing live AI batch trade because BINANCE_MODE" in text
    assert "BINANCE_LIVE_AI_TRADER_ENABLED is false" in text
    assert text.index("BINANCE_LIVE_AI_TRADER_ENABLED is false") < text.index("Invoke-BinanceQuant live-ai-trade-batch-once")


def test_live_ai_trade_batch_once_bat_preserves_launch_directory():
    text = LIVE_AI_BATCH_BAT.read_text(encoding="utf-8")

    assert "pushd" not in text.lower()
    assert "popd" not in text.lower()
    assert "cd /d" not in text.lower()
    assert 'set "ScriptDir=%~dp0"' in text
    assert 'set "ProjectRoot=%ScriptDir%.."' in text
    assert 'uv --project "%ProjectRoot%" run binance-quant live-ai-trade-batch-once %*' in text
    assert "\nbinance-quant live-ai-trade-batch-once %*" not in text
    assert "exit /b %ExitCode%" in text


def test_testnet_sell_action_sanitizes_signed_http_errors():
    text = SCRIPT.read_text(encoding="utf-8")

    assert "def print_http_status_error(exc):" in text
    assert "binance_code:" in text
    assert "binance_message:" in text
    assert "Testnet SELL order failed before Binance response" in text
    assert "str(exc)" not in text
    assert "signature=" not in text


def test_testnet_sell_action_requires_confirmation():
    result = subprocess.run(
        [
            "powershell",
            "-ExecutionPolicy",
            "Bypass",
            "-File",
            str(SCRIPT),
            "-Action",
            "testnet-sell-quote",
        ],
        capture_output=True,
        timeout=15,
    )
    output = (result.stdout + result.stderr).decode("utf-8", errors="replace")

    assert result.returncode != 0
    assert "ConfirmTestnetOrder" in output


def test_live_sell_action_requires_confirmation():
    result = subprocess.run(
        [
            "powershell",
            "-ExecutionPolicy",
            "Bypass",
            "-File",
            str(SCRIPT),
            "-Action",
            "live-sell-quote",
        ],
        capture_output=True,
        timeout=15,
    )
    output = (result.stdout + result.stderr).decode("utf-8", errors="replace")

    assert result.returncode != 0
    assert "ConfirmLiveOrder" in output


def test_readme_documents_run_script():
    readme = README.read_text(encoding="utf-8")

    assert ".\\scripts\\run.ps1 -Action quote" in readme
    assert ".\\scripts\\run.ps1 -Action dry-run-order" in readme
    assert ".\\scripts\\run.ps1 -Action testnet-sell-quote -SellQuoteAmount 5 -ConfirmTestnetOrder" in readme
    assert ".\\scripts\\run.ps1 -Action live-preflight -UseSystemProxy" in readme
    assert ".\\scripts\\run.ps1 -Action live-sell-quote-preflight -SellQuoteAmount 5 -UseSystemProxy" in readme
    assert ".\\scripts\\run.ps1 -Action live-sell-quote -SellQuoteAmount 5 -UseSystemProxy -ConfirmLiveOrder" in readme
    assert ".\\scripts\\run.ps1 -Action live-auto-buy-once" in readme
    assert ".\\scripts\\run.ps1 -Action live-auto-sell-once" in readme
    assert ".\\scripts\\run.ps1 -Action live-ai-trade-once" in readme
    assert ".\\scripts\\run.ps1 -Action live-ai-trade-batch-once" in readme
    assert "BINANCE_MODE=live" in readme


def test_readme_documents_live_auto_buy_disabled_default():
    readme = README.read_text(encoding="utf-8")

    assert "live-auto-buy-once" in readme
    assert "BINANCE_LIVE_AUTO_BUYER_ENABLED=false" in readme
    assert "5 USDT" in readme
    assert "2% 止损" in readme


def test_readme_documents_live_auto_sell_disabled_default():
    readme = README.read_text(encoding="utf-8")

    assert "live-auto-sell-once" in readme
    assert "BINANCE_LIVE_AUTO_SELLER_ENABLED=false" in readme
    assert "BTCUSDT" in readme
    assert "市价卖出" in readme


def test_readme_documents_live_ai_trader_disabled_default():
    readme = README.read_text(encoding="utf-8")

    assert "live-ai-trade-once" in readme
    assert "live-ai-trade-batch-once" in readme
    assert "BINANCE_LIVE_AI_TRADER_ENABLED=false" in readme
    assert "codex exec" in readme
    assert "本地风控" in readme
    assert "BINANCE_AI_TRADER_CODEX_COMMAND=codex" in readme
    assert "BINANCE_AI_TRADER_MAX_ACTIONS_PER_RUN=5" in readme
    assert "BINANCE_AI_TRADER_KLINES=1h:24,4h:30,1d:14" in readme
    assert "BINANCE_AI_TRADER_AGG_TRADES_LIMIT=500" in readme
    assert "BINANCE_AI_TRADER_WS_ENABLED=true" in readme
    assert "BINANCE_AI_TRADER_WS_SAMPLE_SECONDS=15" in readme
    assert "market[].timeframes" in readme
    assert "market[].aggregate_trades" in readme
    assert "market[].realtime" in readme
    assert "BINANCE_EMAIL_NOTIFICATIONS_ENABLED=false" in readme
    assert "BINANCE_EMAIL_SMTP_SERVER=" in readme
    assert "BINANCE_EMAIL_RECIPIENT=" in readme


def test_run_script_has_live_futures_ai_trade_batch_once_action():
    text = SCRIPT.read_text(encoding="utf-8")

    assert '"live-futures-ai-trade-batch-once"' in text
    assert "Invoke-BinanceQuant live-futures-ai-trade-batch-once" in text
    assert "Refusing live futures AI batch trade because BINANCE_MODE" in text
    assert "BINANCE_LIVE_FUTURES_AI_TRADER_ENABLED is false" in text
    assert "BINANCE_LIVE_FUTURES_CONFIRM_PRODUCTION is false" in text
    assert text.index("BINANCE_LIVE_FUTURES_AI_TRADER_ENABLED is false") < text.index("Invoke-BinanceQuant live-futures-ai-trade-batch-once")


def test_readme_documents_live_futures_ai_trader_disabled_default():
    readme = README.read_text(encoding="utf-8")

    assert "live-futures-ai-trade-batch-once" in readme
    assert "BINANCE_LIVE_FUTURES_AI_TRADER_ENABLED=false" in readme
    assert "BINANCE_LIVE_FUTURES_CONFIRM_PRODUCTION=false" in readme
    assert "BINANCE_FUTURES_MARGIN_AMOUNT=5" in readme
    assert "BINANCE_FUTURES_MAX_LEVERAGE=3" in readme
    assert "BINANCE_FUTURES_MAX_TOTAL_MARGIN=20" in readme
