from __future__ import annotations

import json
from pathlib import Path
from typing import Any

import config_manager
from runtime_trade_guard import cooldown_remaining_sec, same_side_reentry_veto


def _load_agent_state(project_root: Path) -> dict[str, Any]:
    path = project_root / "data" / "bridge" / "state" / "agent_state.json"
    if not path.exists():
        return {}
    try:
        payload = json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return {}
    return payload if isinstance(payload, dict) else {}


def _coerce_float(value: Any, default: float) -> float:
    try:
        return float(value)
    except (TypeError, ValueError):
        return default


def _resolve_configured_base_lots(project_root: Path) -> float:
    configured = config_manager.get_effective_param("base_lots", 0.05)
    return max(0.01, _coerce_float(configured, 0.05))


def _resolve_rule_cap(project_root: Path) -> tuple[float, list[str]]:
    state = _load_agent_state(project_root)
    reasons: list[str] = []

    hard_cap = _coerce_float(config_manager.get_effective_param("max_open_lots", 1.0), 1.0)
    hard_cap = max(0.01, hard_cap)

    consecutive_losses = int(state.get("consecutive_losses", 0) or 0)
    if consecutive_losses >= 3:
        hard_cap = min(hard_cap, 0.03)
        reasons.append("LOSS_STREAK_CAP")
    elif consecutive_losses >= 2:
        hard_cap = min(hard_cap, 0.05)
        reasons.append("LOSS_PRESSURE_CAP")

    disable_new_open = bool(
        (state.get("incident_controls", {}) if isinstance(state.get("incident_controls", {}), dict) else {}).get(
            "disable_new_open",
            False,
        )
    )
    if disable_new_open:
        hard_cap = 0.0
        reasons.append("DISABLE_NEW_OPEN_ACTIVE")

    return max(0.0, hard_cap), reasons


def resolve_live_volume_plan(requested_volume: float, *, project_root: Path) -> dict[str, Any]:
    requested = max(0.0, _coerce_float(requested_volume, 0.0))
    configured_base_lots = _resolve_configured_base_lots(project_root)
    rule_cap_lots, rule_cap_reasons = _resolve_rule_cap(project_root)
    effective_request = requested if requested > 0 else configured_base_lots
    final_volume_lots = min(effective_request, configured_base_lots, rule_cap_lots or effective_request)
    return {
        "requested_volume_lots": round(requested, 4),
        "configured_base_lots": round(configured_base_lots, 4),
        "rule_cap_lots": round(rule_cap_lots, 4),
        "rule_cap_reasons": list(rule_cap_reasons),
        "final_volume_lots": round(max(0.0, final_volume_lots), 4),
    }


def resolve_live_open_guard(*, project_root: Path, side: str) -> dict[str, Any]:
    state = _load_agent_state(project_root)
    incident_controls = (
        state.get("incident_controls", {})
        if isinstance(state.get("incident_controls", {}), dict)
        else {}
    )
    if bool(incident_controls.get("disable_new_open", False)):
        return {
            "allow_open": False,
            "reason": "DISABLE_NEW_OPEN_ACTIVE",
            "disable_new_open": True,
            "disable_new_open_reason": str(incident_controls.get("disable_new_open_reason", "") or "incident_control"),
            "cooldown_remaining_sec": 0,
            "same_side_reentry_remaining_sec": 0,
        }

    configured_cooldown = int(_coerce_float(config_manager.get_effective_param("post_close_cooldown_sec", 180), 180))
    remaining = cooldown_remaining_sec(state, cooldown_sec=configured_cooldown)
    if remaining > 0:
        return {
            "allow_open": False,
            "reason": "POST_CLOSE_COOLDOWN",
            "cooldown_remaining_sec": int(remaining),
            "same_side_reentry_remaining_sec": 0,
        }

    same_side_remaining, same_side_reason = same_side_reentry_veto(state, side)
    if same_side_remaining > 0:
        return {
            "allow_open": False,
            "reason": same_side_reason or "SAME_SIDE_REENTRY_LOCK",
            "cooldown_remaining_sec": 0,
            "same_side_reentry_remaining_sec": int(same_side_remaining),
        }

    return {
        "allow_open": True,
        "reason": "",
        "cooldown_remaining_sec": 0,
        "same_side_reentry_remaining_sec": 0,
    }
