"""Operational mode flags read from the environment.

Cerbero Bite supports two independent runtime switches:

* ``CERBERO_BITE_ENABLE_DATA_ANALYSIS`` — when ``true``, the periodic
  market-snapshot job is scheduled and writes 15-minute snapshots to
  ``market_snapshots``; when ``false``, the bot still pings MCP for
  health and reconciliation but does not record any market dataset.
* ``CERBERO_BITE_ENABLE_STRATEGY`` — when ``true``, the entry and
  monitor cycles are scheduled and may propose/execute trades; when
  ``false``, no entry or monitor logic runs autonomously (the methods
  remain callable from the CLI ``dry-run`` and via manual actions, so
  the operator can still test code paths on demand).

The default profile is "analysis only": data analysis on, strategy off.
This is the mode used during the post-deploy soak window where the
team observes data quality before opening any position.
"""

from __future__ import annotations

import os
from dataclasses import dataclass

__all__ = [
    "DATA_ANALYSIS_ENV",
    "STRATEGY_ENV",
    "RuntimeFlags",
    "load_runtime_flags",
]

DATA_ANALYSIS_ENV = "CERBERO_BITE_ENABLE_DATA_ANALYSIS"
STRATEGY_ENV = "CERBERO_BITE_ENABLE_STRATEGY"

_TRUE_TOKENS = frozenset({"1", "true", "yes", "on", "enabled"})
_FALSE_TOKENS = frozenset({"0", "false", "no", "off", "disabled"})


@dataclass(frozen=True)
class RuntimeFlags:
    """Boolean switches that gate optional cycles.

    Both fields default to the canonical "analysis only" profile.
    """

    data_analysis_enabled: bool = True
    strategy_enabled: bool = False


def _parse_bool(raw: str, *, var: str, default: bool) -> bool:
    cleaned = raw.strip().lower()
    if not cleaned:
        return default
    if cleaned in _TRUE_TOKENS:
        return True
    if cleaned in _FALSE_TOKENS:
        return False
    raise ValueError(
        f"{var}: expected one of "
        f"{sorted(_TRUE_TOKENS | _FALSE_TOKENS)}, got {raw!r}"
    )


def load_runtime_flags(env: dict[str, str] | None = None) -> RuntimeFlags:
    """Build a :class:`RuntimeFlags` from environment variables."""
    e = env if env is not None else os.environ
    return RuntimeFlags(
        data_analysis_enabled=_parse_bool(
            e.get(DATA_ANALYSIS_ENV, ""),
            var=DATA_ANALYSIS_ENV,
            default=True,
        ),
        strategy_enabled=_parse_bool(
            e.get(STRATEGY_ENV, ""),
            var=STRATEGY_ENV,
            default=False,
        ),
    )
