from __future__ import annotations

import json
from dataclasses import dataclass
from decimal import Decimal
from pathlib import Path
from typing import Any

DEFAULT_POLICY = Path("config/tiny_live_risk_policy_v77_1.json")


@dataclass(frozen=True)
class PolicyValidation:
    valid: bool
    blockers: tuple[str, ...]
    strategy_id: str
    strategy_version: str
    execution_enabled: bool
    mainnet_signed_action_enabled: bool

    def to_dict(self) -> dict[str, Any]:
        return {
            "valid": self.valid,
            "blockers": list(self.blockers),
            "strategy_id": self.strategy_id,
            "strategy_version": self.strategy_version,
            "execution_enabled": self.execution_enabled,
            "mainnet_signed_action_enabled": self.mainnet_signed_action_enabled,
        }


def load_policy(path: str | Path = DEFAULT_POLICY) -> dict[str, Any]:
    target = Path(path)
    try:
        payload = json.loads(target.read_text(encoding="utf-8"))
    except Exception:
        return {}
    return payload if isinstance(payload, dict) else {}


def validate_prepared_disabled_policy(policy: dict[str, Any]) -> PolicyValidation:
    blockers: list[str] = []
    required_true = (
        "no_martingale",
        "no_averaging_down",
        "exchange_stop_required",
        "reconcile_before_every_entry",
        "critical_alerts_required",
        "explicit_user_launch_approval_required",
    )
    if policy.get("schema_version") != "tiny_live_risk_policy.v1":
        blockers.append("policy_schema_invalid")
    if policy.get("mode") != "prepared_disabled":
        blockers.append("policy_mode_not_prepared_disabled")
    if policy.get("execution_enabled") is not False:
        blockers.append("execution_not_disabled")
    if policy.get("mainnet_signed_action_enabled") is not False:
        blockers.append("mainnet_signing_not_disabled")
    if policy.get("direction") != "long_only":
        blockers.append("direction_not_long_only")
    if int(policy.get("default_leverage") or 0) != 1 or int(policy.get("max_leverage") or 0) != 1:
        blockers.append("leverage_not_fixed_1x")
    if int(policy.get("max_open_positions") or 0) != 1:
        blockers.append("max_open_positions_not_one")
    if Decimal(str(policy.get("max_equity_risk_per_trade_pct") or 0)) > Decimal("0.10"):
        blockers.append("risk_per_trade_above_0_10pct")
    if Decimal(str(policy.get("max_daily_loss_equity_pct") or 0)) > Decimal("0.30"):
        blockers.append("daily_loss_above_0_30pct")
    if Decimal(str(policy.get("max_weekly_loss_equity_pct") or 0)) > Decimal("1.00"):
        blockers.append("weekly_loss_above_1_00pct")
    if int(policy.get("max_consecutive_losses") or 0) > 3:
        blockers.append("loss_streak_above_three")
    if policy.get("automatic_size_increase") is not False:
        blockers.append("automatic_size_increase_enabled")
    if any(policy.get(key) is not True for key in required_true):
        blockers.append("mandatory_safety_controls_missing")
    coins = policy.get("allowed_coins")
    if not isinstance(coins, list) or not coins or any(str(coin).upper() not in {"BTC", "ETH"} for coin in coins):
        blockers.append("initial_coin_universe_not_btc_eth")
    return PolicyValidation(
        valid=not blockers,
        blockers=tuple(blockers),
        strategy_id=str(policy.get("strategy_id") or ""),
        strategy_version=str(policy.get("strategy_version") or ""),
        execution_enabled=bool(policy.get("execution_enabled")),
        mainnet_signed_action_enabled=bool(policy.get("mainnet_signed_action_enabled")),
    )
