"""Construct the ``User-Agent`` header sent on outbound WorkIQ requests.

The header identifies traffic as coming from this CLI and carries enough
runtime detail (CLI version, OS platform, Node and Python versions) to let
the service measure adoption and diagnose version-specific regressions,
without leaking any PII.

Format (RFC 9110 §10.1.5):

    m365-copilot-eval/<version> (<platform>; node/<node-version>; python/<py-version>)

The CLI version is read from ``package.json`` (the running install). The Node
version is supplied by the Node.js wrapper via the
``M365_COPILOT_EVAL_NODE_VERSION`` environment variable, since the Python
process cannot otherwise know which Node runtime launched it. The platform and
Python version are resolved locally.
"""

from __future__ import annotations

import functools
import os
import platform
import sys

from version_check import get_cli_version_string

#: Product token identifying this CLI in the User-Agent header.
PRODUCT = "m365-copilot-eval"

#: Set by the Node.js wrapper to the Node runtime version that launched the CLI.
ENV_NODE_VERSION = "M365_COPILOT_EVAL_NODE_VERSION"

#: Substituted whenever a version segment cannot be determined.
_UNKNOWN = "unknown"


def _cli_version() -> str:
    """Return the CLI version from package.json, or ``unknown`` if unavailable.

    Uses the verbatim package.json string so the header matches the published
    version exactly (e.g. ``1.10.2-preview.1``, not the PEP 440-normalized
    ``1.10.2rc1``).
    """
    version = get_cli_version_string()
    return version if version else _UNKNOWN


def _node_version() -> str:
    """Return the Node version passed in by the wrapper, or ``unknown``.

    The wrapper passes a bare semver (e.g. ``20.11.1``); ``process.version``'s
    leading ``v`` is stripped defensively in case a raw value is forwarded.
    """
    raw = (os.environ.get(ENV_NODE_VERSION) or "").strip()
    if not raw:
        return _UNKNOWN
    return raw[1:] if raw.startswith("v") else raw


@functools.lru_cache(maxsize=1)
def build_user_agent() -> str:
    """Build the ``User-Agent`` header value for outbound CLI requests.

    Cached for the process lifetime: every segment is fixed for a given run.
    """
    return (
        f"{PRODUCT}/{_cli_version()} "
        f"({sys.platform}; node/{_node_version()}; python/{platform.python_version()})"
    )
