"""License guard for the tool CLIs.

Every tool CLI (``cli.py``, ``cli_text_clean.py``, ``cli_format.py``,
``cli_missing.py``, ``cli_column_map.py``, ``cli_pipeline.py``,
``cli_analyze.py``) calls :func:`guard` from its ``main()`` before
delegating to Typer. The guard:

1. Lets ``--help`` / ``-h`` through unconditionally so users can
   always see what a command does.
2. Lets the ``DATATOOLS_DEV_MODE=1`` env var bypass the check.
3. Otherwise, verifies a valid license is on disk. If not, prints a
   one-line user-facing message naming the exact ``datatools-license``
   subcommand to run, then exits with status 2.

The exit code (2) is the same Typer uses for argument errors — fits
into ``run_tests.py`` / CI pipelines without special casing.
"""

from __future__ import annotations

import sys
from typing import NoReturn


_HELP_FLAGS = {"--help", "-h", "--version"}


def _is_help_invocation() -> bool:
    """True when the user is asking for help, not running work."""
    return any(arg in _HELP_FLAGS for arg in sys.argv[1:])


def guard(feature: str | None = None) -> None:
    """Block startup if no valid license.

    *feature* — when supplied, also requires that the active license's
    tier unlocks the named feature flag (e.g.
    ``"03_format_standardizer"``). A Lite-tier user running
    ``cli_format`` would pass the global validity check but fail the
    feature check; we surface a clear "upgrade your tier" message
    rather than letting them hit a runtime error halfway through a
    job.

    No-op when license is valid (and the feature is unlocked), when
    called with ``--help`` / ``-h`` / ``--version``, or under
    ``DATATOOLS_DEV_MODE=1``.
    """
    if _is_help_invocation():
        return
    # Lazy import so a broken license module doesn't fail ``--help``.
    from src.license import (
        ExpiredLicenseError,
        InvalidLicenseError,
        LicenseError,
        UnsupportedFeatureError,
        assert_production_safe,
        get_manager,
    )

    # Refuse to run a misconfigured shipped build. No-op in
    # development / pytest runs.
    assert_production_safe()

    mgr = get_manager()
    if mgr.dev_mode:
        return

    try:
        if not mgr.is_valid():
            state = mgr.current_state()
            _exit_with_message(state)
        if feature is not None:
            try:
                mgr.require_feature(feature)
            except UnsupportedFeatureError as e:
                _exit_with_feature_message(feature, str(e))
        return
    except LicenseError:
        state = mgr.current_state()
        _exit_with_message(state)


def _exit_with_feature_message(feature: str, detail: str) -> NoReturn:
    """Print the upgrade-tier diagnostic and exit. Mirrors the
    GUI's ``require_feature_or_render_upgrade`` UX in CLI form."""
    msg = (
        f"This command requires the {feature!r} feature, which is not "
        f"included in your current license tier.\n"
        f"Detail: {detail}\n"
        "Run ``python -m src.license_cli status`` to see your tier, "
        "then activate an upgrade blob with "
        "``python -m src.license_cli renew <blob>``."
    )
    print(f"Error: {msg}", file=sys.stderr)
    raise SystemExit(2)


def _exit_with_message(state) -> NoReturn:
    """Print the right one-liner for the current state and exit."""
    if state.error_kind == "not_activated":
        msg = (
            "DataTools is not activated.\n"
            "Run: python -m src.license_cli activate <license-blob>\n"
            "Or start a 1-year trial: "
            "python -m src.license_cli trial --name 'Your Name' --email you@example.com"
        )
    elif state.error_kind == "expired":
        msg = (
            f"License expired on {state.expires_at[:10]}.\n"
            "Renew with: python -m src.license_cli renew <license-blob>"
        )
    elif state.error_kind == "invalid":
        msg = (
            "License file is present but invalid.\n"
            f"Detail: {state.error_message}\n"
            "Re-paste the blob from your delivery email: "
            "python -m src.license_cli activate <license-blob>"
        )
    else:
        msg = "License is not valid. Run: python -m src.license_cli status"
    print(f"Error: {msg}", file=sys.stderr)
    raise SystemExit(2)
