"""Configuration resolution with CLI > env var > config file > stored > default precedence."""

from __future__ import annotations

import os
from pathlib import Path

from dotenv import load_dotenv

from alice_cli.constants import DEFAULT_ENVIRONMENT, DEFAULT_NAMESPACE, DEFAULT_REGION
from alice_cli.models import CLIConfig
from alice_cli.store import load_stored_credentials

_ALICE_ENV_FILE = Path.home() / ".alice" / ".env"


def _load_alice_env() -> None:
    """Load ~/.alice/.env if it exists.

    Only sets variables not already present in the environment, so
    explicit env vars always take precedence over the config file.
    """
    if _ALICE_ENV_FILE.exists():
        load_dotenv(_ALICE_ENV_FILE, override=False)


def resolve_config(
    profile: str | None,
    region: str | None,
    namespace: str | None,
    environment: str | None,
    quiet: bool,
    debug: bool,
    api_key: str | None = None,
    personality: str | None = None,
) -> CLIConfig:
    """Resolve CLI configuration with precedence: CLI option > env var > stored > default.

    Parameters that are ``None`` were not supplied on the command line, so the
    corresponding environment variable (if set) takes effect before the
    hard-coded default.

    The *api_key* parameter (from ``--api-key`` or ``BEDROCK_SECRET_KEY``)
    enables API-key mode, which bypasses SSO and Secrets Manager entirely.
    ``BEDROCK_ACCESS_KEY`` is also read from the environment when available.

    When no CLI flags or env vars provide auth, stored credentials from
    ``~/.alice/credentials.json`` (written by ``alice auth``) are used.
    """
    # Load ~/.alice/.env before reading environment variables so the file
    # acts as a persistent config layer below explicit env vars.
    _load_alice_env()

    stored = load_stored_credentials()

    resolved_namespace = (
        namespace if namespace is not None else os.environ.get("ALICE_NAMESPACE", DEFAULT_NAMESPACE)
    )

    resolved_environment = (
        environment
        if environment is not None
        else os.environ.get("ALICE_ENVIRONMENT", DEFAULT_ENVIRONMENT)
    )

    resolved_region = region if region is not None else DEFAULT_REGION

    # api_key already resolves from --api-key or BEDROCK_SECRET_KEY via Click envvar
    resolved_secret_key = api_key
    resolved_access_key = os.environ.get("BEDROCK_ACCESS_KEY") if resolved_secret_key else None

    # Fall back to stored credentials when nothing was provided via CLI/env.
    # Prefer stored API keys over stored profile for Bedrock model calls —
    # API keys don't require an active SSO session.  However, the SSO
    # profile is always needed for services like S3 (Cloud Locker), so
    # carry it forward independently of how the Bedrock key was resolved.
    resolved_profile = profile
    if not resolved_profile and not resolved_secret_key and stored.bedrock_secret_key:
        resolved_secret_key = stored.bedrock_secret_key
        resolved_access_key = stored.bedrock_access_key

    # Always load the stored SSO profile when no explicit profile was
    # provided and no explicit API key was given — so that S3 operations
    # can use SSO-scoped credentials.  When an explicit --api-key is
    # provided, skip loading the stored profile so that commands correctly
    # detect API-key mode (bedrock_secret_key set, profile unset).
    if not resolved_profile and not api_key and stored.profile:
        resolved_profile = stored.profile

    if stored.region and region is None:
        resolved_region = stored.region

    # Load stored inference profile ARNs and bearer token when using stored credentials
    resolved_inference_arns: dict[str, str] | None = None
    if not profile and not api_key and stored.inference_profile_arns:
        resolved_inference_arns = stored.inference_profile_arns

    resolved_bearer_token: str | None = (
        os.environ.get("AWS_BEARER_TOKEN_BEDROCK") or stored.bedrock_bearer_token or None
    )

    resolved_personality = (
        personality if personality is not None else os.environ.get("ALICE_PERSONALITY", "alice")
    )

    return CLIConfig(
        profile=resolved_profile,
        region=resolved_region,
        namespace=resolved_namespace,
        environment=resolved_environment,
        quiet=quiet,
        debug=debug,
        personality=resolved_personality,
        bedrock_access_key=resolved_access_key,
        bedrock_secret_key=resolved_secret_key,
        bedrock_bearer_token=resolved_bearer_token,
        inference_profile_arns=resolved_inference_arns,
    )
