"""开仓统一管道：定仓 → 兑 USDC → 资金门（fail-closed）。

策略自动开仓与手动开一组共用，避免双路径打架。
基线假设：运行中不在交易所人工开平仓、也不人工手动平仓。
"""

from __future__ import annotations

import logging
from dataclasses import dataclass
from typing import Any

from ..models.db import Database, get_db
from .open_capacity import assess_open_capacity, funds_gate_blocks
from .risk_sizing import apply_risk_sizing_to_ledger

logger = logging.getLogger(__name__)


@dataclass(slots=True)
class OpenPrepResult:
    ok: bool
    detail: str = ""
    capacity: dict[str, Any] | None = None
    sizing_detail: str = ""
    convert_detail: str = ""


def prepare_usdc_while_waiting(db: Database | None = None) -> dict[str, Any]:
    """空仓等待选约：预览名义检测 USDC 并兑换，不落库改写 qty/exit。"""
    from .auto_usdc import prepare_okx_trading_usdc

    return prepare_okx_trading_usdc(db)


def size_and_gate(
    *,
    index_px: float,
    option_ask: float,
    db: Database | None = None,
) -> OpenPrepResult:
    """
    选约成功后：写入以损定仓 → 交易账户兑 USDC → 资金门。
    资金门 fail-closed：异常 / can_open 非 True 一律拦截。
    """
    database = db or get_db()
    try:
        rs = apply_risk_sizing_to_ledger(
            index_px=float(index_px),
            option_ask=float(option_ask),
            db=database,
        )
        if not rs.ok:
            return OpenPrepResult(ok=False, detail=rs.detail, sizing_detail=rs.detail)
    except Exception as e:
        logger.exception("risk sizing failed in open pipeline")
        return OpenPrepResult(ok=False, detail=f"以损定仓计算异常：{e}")

    convert_detail = ""
    try:
        from .auto_usdc import ensure_okx_trading_usdc

        # 选约后名义已更新；仍受冷却约束，禁止 force 砸单
        conv = ensure_okx_trading_usdc(
            database,
            cap=assess_open_capacity(
                database,
                option_ask=float(option_ask),
            ),
            force=False,
        )
        convert_detail = str(conv.get("detail") or "")
        if conv.get("acted"):
            logger.info("open_pipeline auto_usdc: %s", convert_detail)
    except Exception:
        logger.exception("auto USDC in open pipeline failed")
        convert_detail = "自动兑 USDC 异常（已记日志）"

    try:
        cap = assess_open_capacity(database, option_ask=float(option_ask))
    except Exception as e:
        logger.exception("open capacity assess failed")
        return OpenPrepResult(
            ok=False,
            detail=f"资金可开判定失败，拒绝开仓：{e}",
            convert_detail=convert_detail,
        )

    blocked, why = funds_gate_blocks(cap)
    if blocked:
        return OpenPrepResult(
            ok=False,
            detail=why or "资金不足或状态未知，拒绝开仓",
            capacity=cap,
            convert_detail=convert_detail,
        )
    return OpenPrepResult(
        ok=True,
        detail="ready",
        capacity=cap,
        convert_detail=convert_detail,
    )
