"""``mgf-cloud explain`` — show the resolved CloudConfig + provenance (OP-05).

The canonical "where did this configuration come from?" answer: which source won
the credential resolution race (explicit ``--clouds-yaml`` path /
``$MGF_CLOUD_CLOUDS_YAML`` / the ``OS_*`` environment / a standard search path),
the provider, and the resolved auth fields. Secrets are held as pydantic
``SecretStr``, so the model's own repr auto-redacts them (``**********``) — this
command never calls ``get_secret_value``, so its output is safe to paste into a
bug report.

Offline + side-effect-free: it parses clouds.yaml / env exactly as the CLI
would, but makes no cloud call.
"""

from __future__ import annotations

import json
import os
from typing import TYPE_CHECKING

from mgf.cloud import __version__, config
from mgf.cloud.exceptions import CredentialsError

if TYPE_CHECKING:
    import argparse

    from mgf.cloud.config import Credentials


def _resolve_with_source(args: argparse.Namespace) -> tuple[Credentials, str]:
    """Resolve credentials and report which source won (config.load order)."""
    if args.clouds_yaml:
        return config.from_clouds_yaml(args.clouds_yaml, args.cloud), (
            f"explicit --clouds-yaml: {args.clouds_yaml}"
        )
    override = os.environ.get(config._ENV_OVERRIDE)
    if override:
        return config.from_clouds_yaml(override, args.cloud), (
            f"${config._ENV_OVERRIDE}: {override}"
        )
    if os.environ.get("OS_AUTH_URL"):
        return config.from_env(), "OS_* environment"
    for candidate in config._default_clouds_yaml_paths():
        if candidate.is_file():
            return config.from_clouds_yaml(candidate, args.cloud), f"search path: {candidate}"
    raise CredentialsError(
        "no credentials resolved — pass --clouds-yaml, set $MGF_CLOUD_CLOUDS_YAML "
        "or OS_*, or place a clouds.yaml in a standard location",
        source="search",
    )


def _facts(args: argparse.Namespace) -> dict[str, object]:
    """The resolved-config payload (also the ``--json`` shape). Secrets redacted."""
    if args.provider == "fake":
        return {"provider": "fake", "source": "(none — fake provider needs no credentials)"}
    creds, source = _resolve_with_source(args)
    return {
        "provider": args.provider,
        "source": source,
        "cloud_entry": args.cloud,
        "auth_url": creds.auth_url,
        "region_name": creds.region_name,
        "interface": creds.interface,
        "identity_api_version": creds.identity_api_version,
        "auth_type": creds.auth_type,
        # str(SecretStr) auto-redacts to '**********'; never get_secret_value().
        "application_credential_id": creds.application_credential_id,
        "application_credential_secret": (
            str(creds.application_credential_secret)
            if creds.application_credential_secret is not None
            else None
        ),
        "username": creds.username,
        "password": str(creds.password) if creds.password is not None else None,
        "project_id": creds.project_id,
        "project_name": creds.project_name,
    }


def run_explain(args: argparse.Namespace) -> int:
    """Argparse-callback wiring for the ``explain`` subcommand."""
    facts = _facts(args)
    if getattr(args, "as_json", False):
        print(json.dumps(facts, indent=2, sort_keys=True))
        return 0
    print(f"mgf-cloud {__version__} — resolved configuration")
    print()
    width = max(len(k) for k in facts)
    for key, value in facts.items():
        print(f"  {key:{width}}  {value if value is not None else '(none)'}")
    return 0


__all__ = ["run_explain"]
