from __future__ import annotations

import time
from dataclasses import dataclass
from typing import Any

EXIT_MODE_FIXED = "fixed_usdt"
EXIT_MODE_PREMIUM = "premium_multiple"


@dataclass(slots=True)
class ExitDecision:
    should_close: bool
    reason: str = ""
    target: float = 0.0


def resolve_exit_target(
    *,
    exit_mode: str,
    net_profit_target: float,
    premium_exit_multiple: float,
    initial_premium: float,
) -> tuple[float, str]:
    """返回 (出场目标金额 USDT, 模式标记)。"""
    mode = (exit_mode or EXIT_MODE_FIXED).strip().lower()
    if mode == EXIT_MODE_PREMIUM:
        mult = max(0.0, float(premium_exit_multiple))
        return float(initial_premium) * mult, EXIT_MODE_PREMIUM
    return float(net_profit_target), EXIT_MODE_FIXED


def lock_trade_exit_target(
    db: Any,
    *,
    group_id: str,
    initial_premium: float,
) -> float:
    """
    开仓成交后锁定本组成交出场目标到 groups/positions。
    持仓期间盯盘与展示均用该值，不再跟随时价重算以损定仓/出场。
    """
    from ..config import get_settings
    from ..sim.ledger import Ledger

    s = get_settings()
    ledger = Ledger(db)
    exit_mode = ledger.get_setting_str("exit_mode", s.exit_mode) or EXIT_MODE_FIXED
    net_target = float(
        ledger.get_setting_float("net_profit_target", s.net_profit_target)
        or s.net_profit_target
    )
    prem_mult = float(
        ledger.get_setting_float("premium_exit_multiple", s.premium_exit_multiple)
        or s.premium_exit_multiple
    )
    target, _mode = resolve_exit_target(
        exit_mode=str(exit_mode),
        net_profit_target=net_target,
        premium_exit_multiple=prem_mult,
        initial_premium=float(initial_premium or 0),
    )
    target = float(target)
    db.execute(
        "UPDATE groups SET exit_target_usdt=? WHERE group_id=?",
        (target, group_id),
    )
    db.execute(
        "UPDATE positions SET exit_target_usdt=? WHERE id=1",
        (target,),
    )
    return target


def read_locked_exit_target(pos: dict[str, Any] | None) -> float | None:
    """持仓行上的锁定目标；无则 None（旧仓回退设置值）。"""
    if not pos:
        return None
    v = pos.get("exit_target_usdt")
    if v is None or v == "":
        return None
    try:
        f = float(v)
    except (TypeError, ValueError):
        return None
    return f if f > 0 else None


def check_expiry_close(
    *,
    expiry_ms: int | None,
    now_ms: int | None = None,
) -> ExitDecision:
    """期权到期时刻（含）→ 强制全平。"""
    if expiry_ms is None:
        return ExitDecision(False, "", 0.0)
    now = int(time.time() * 1000) if now_ms is None else int(now_ms)
    if now >= int(expiry_ms):
        return ExitDecision(True, "expiry", 0.0)
    return ExitDecision(False, "", 0.0)


def check_exits(
    *,
    net_pnl: float,
    exit_mode: str,
    net_profit_target: float,
    premium_exit_multiple: float,
    initial_premium: float,
    locked_exit_target: float | None = None,
) -> ExitDecision:
    """净盈利（预估全平后）≥ 所选模式目标则全平。持仓锁定目标优先。"""
    if locked_exit_target is not None and float(locked_exit_target) > 0:
        target = float(locked_exit_target)
        mode = EXIT_MODE_FIXED
    else:
        target, mode = resolve_exit_target(
            exit_mode=exit_mode,
            net_profit_target=net_profit_target,
            premium_exit_multiple=premium_exit_multiple,
            initial_premium=initial_premium,
        )
    if target > 0 and net_pnl + 1e-9 >= target:
        reason = "premium_multiple" if mode == EXIT_MODE_PREMIUM else "fixed_usdt"
        return ExitDecision(True, reason, target)
    return ExitDecision(False, "", target)
