"""OKX 资金：余额 / USDT↔USDC 现货兑换 / 账户划转（对齐 crypto_monitor）。"""

from __future__ import annotations

import logging
from typing import Any

from .okx_trade import OkxTradeClient

logger = logging.getLogger(__name__)

# OKX acct: 6=资金, 18=交易
_ACCT_CODE = {
    "funding": "6",
    "trading": "18",
    "spot": "18",
}


def _f(v: Any) -> float | None:
    try:
        if v is None or v == "":
            return None
        return float(v)
    except (TypeError, ValueError):
        return None


class OkxFundsClient:
    def __init__(self, trade: OkxTradeClient | None = None) -> None:
        self.trade = trade or OkxTradeClient()

    def close(self) -> None:
        self.trade.close()

    def fetch_balances(self) -> dict[str, float | None]:
        """
        拉取资金账户 + 交易账户 USDT/USDC。
        资金：GET /api/v5/asset/balances
        交易：GET /api/v5/account/balance
        """
        out: dict[str, float | None] = {
            "funding_usdt": None,
            "funding_usdc": None,
            "trading_usdt": None,
            "trading_usdc": None,
        }
        try:
            rows = self.trade._request("GET", "/api/v5/asset/balances")
            for row in rows:
                ccy = str(row.get("ccy") or "").upper()
                bal = _f(row.get("bal")) or _f(row.get("availBal"))
                if ccy == "USDT":
                    out["funding_usdt"] = bal
                elif ccy == "USDC":
                    out["funding_usdc"] = bal
        except Exception as e:
            logger.warning("OKX asset balances failed: %s", e)

        try:
            rows = self.trade._request("GET", "/api/v5/account/balance")
            for block in rows:
                details = block.get("details") or []
                if not isinstance(details, list):
                    continue
                for row in details:
                    if not isinstance(row, dict):
                        continue
                    ccy = str(row.get("ccy") or "").upper()
                    eq = _f(row.get("eq")) or _f(row.get("cashBal")) or _f(row.get("availBal"))
                    if ccy == "USDT":
                        out["trading_usdt"] = eq
                    elif ccy == "USDC":
                        out["trading_usdc"] = eq
        except Exception as e:
            logger.warning("OKX account balance failed: %s", e)

        return out

    def spot_swap_usdt_usdc(self, *, direction: str, amount: float) -> dict[str, Any]:
        """现货市价兑换 USDC-USDT（与 crypto_monitor spot_market_swap_usdt_usdc 同口径）。"""
        amt = float(amount)
        if amt <= 0:
            return {"ok": False, "detail": "数量须大于 0"}
        d = (direction or "").strip().lower()
        inst_id = "USDC-USDT"
        if d == "usdt_to_usdc":
            body = {
                "instId": inst_id,
                "tdMode": "cash",
                "side": "buy",
                "ordType": "market",
                "sz": str(amt),
                "tgtCcy": "quote_ccy",
            }
        elif d == "usdc_to_usdt":
            body = {
                "instId": inst_id,
                "tdMode": "cash",
                "side": "sell",
                "ordType": "market",
                "sz": str(amt),
                "tgtCcy": "base_ccy",
            }
        else:
            return {"ok": False, "detail": "direction 须为 usdt_to_usdc 或 usdc_to_usdt"}
        try:
            rows = self.trade._request("POST", "/api/v5/trade/order", body)
            if not rows:
                return {"ok": False, "detail": "兑换下单无返回"}
            row = rows[0]
            if str(row.get("sCode") or "0") not in ("0", ""):
                return {
                    "ok": False,
                    "detail": str(row.get("sMsg") or row.get("sCode") or "兑换失败"),
                    "raw": row,
                }
            return {"ok": True, "detail": "converted", "data": row}
        except Exception as e:
            return {"ok": False, "detail": str(e)}

    def transfer(
        self,
        *,
        ccy: str,
        amount: float,
        from_account: str,
        to_account: str,
    ) -> dict[str, Any]:
        """同一 API Key 下资金↔交易划转。"""
        amt = float(amount)
        if amt <= 0:
            return {"ok": False, "detail": "划转金额须大于 0"}
        fa = (from_account or "").strip().lower()
        ta = (to_account or "").strip().lower()
        if fa == ta:
            return {"ok": False, "detail": "来源与目标账户不能相同"}
        from_code = _ACCT_CODE.get(fa)
        to_code = _ACCT_CODE.get(ta)
        if not from_code or not to_code:
            return {"ok": False, "detail": "账户须为 funding / trading"}
        body = {
            "ccy": str(ccy).upper(),
            "amt": str(amt),
            "from": from_code,
            "to": to_code,
            "type": "0",
        }
        try:
            rows = self.trade._request("POST", "/api/v5/asset/transfer", body)
            if not rows:
                return {"ok": False, "detail": "划转无返回"}
            return {"ok": True, "detail": "transferred", "data": rows[0]}
        except Exception as e:
            return {"ok": False, "detail": str(e)}


def usdc_usdt_mid_rate() -> float:
    """公共盘口中间价：1 USDC ≈ ? USDT；失败则 1.0。"""
    try:
        import httpx
        from ..config import get_settings

        s = get_settings()
        proxy = (s.okx_http_proxy or "").strip() or None
        with httpx.Client(base_url=s.okx_rest_base.rstrip("/"), timeout=8.0, proxy=proxy) as c:
            r = c.get("/api/v5/market/ticker", params={"instId": "USDC-USDT"})
            r.raise_for_status()
            rows = (r.json() or {}).get("data") or []
            if not rows:
                return 1.0
            bid = _f(rows[0].get("bidPx"))
            ask = _f(rows[0].get("askPx"))
            last = _f(rows[0].get("last"))
            if bid and ask and bid > 0 and ask > 0:
                return (bid + ask) / 2.0
            if last and last > 0:
                return last
    except Exception as e:
        logger.warning("USDC-USDT mid failed: %s", e)
    return 1.0
