"""
Shared credential resolution for Google Drive and Sheets APIs.

Credential resolution order (same logic as toolsbq, duplicated to avoid heavy dependency):
  1) Pre-resolved credentials object (e.g. from toolsbq via bq_client._credentials)
  2) Explicit keyfile_json (SA key as dict)
  3) Explicit path_keyfile (path to SA JSON file)
  4) GOOGLE_APPLICATION_CREDENTIALS env var
  5) Local RAM-ADC fast path (macOS ramdisk / Linux /dev/shm)
  6) Application Default Credentials (Cloud Run metadata, gcloud auth, etc.)
"""

from __future__ import annotations

import logging
import os
import platform
from pathlib import Path
from typing import Any

import google.auth
from google.auth.exceptions import DefaultCredentialsError
from google.oauth2 import service_account

logger = logging.getLogger(__name__)


def _normalize_path(path: str) -> str:
    """Expand '~' and environment variables like '$HOME' and return a usable path."""
    p = Path(os.path.expandvars(path)).expanduser()
    return str(p)


def _is_running_on_gcp() -> bool:
    return any(
        os.environ.get(k)
        for k in (
            "K_SERVICE",  # Cloud Run
            "CLOUD_RUN_JOB",  # Cloud Run Jobs / Cloud Functions
        )
    )


def _ram_adc_key_path() -> Path:
    if platform.system() == "Darwin":
        return Path("/Volumes/GCLOUD_SA_RAM/sa.json")
    return Path("/dev/shm/sa.json")


def _ensure_ram_adc_env_if_present() -> None:
    """
    Local-only "temporary ADC replacement":
      - If GOOGLE_APPLICATION_CREDENTIALS already points to an existing file: do nothing
      - If running on GCP: skip RAM checks (use real ADC)
      - Otherwise: if RAM key exists, set GOOGLE_APPLICATION_CREDENTIALS
    """
    gac = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS")
    if gac and Path(gac).expanduser().is_file():
        return
    if _is_running_on_gcp():
        return
    ram_key = _ram_adc_key_path()
    if ram_key.is_file():
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = str(ram_key)


def get_credentials(
    *,
    path_keyfile: str | None = None,
    keyfile_json: dict | None = None,
    credentials: Any | None = None,
    scopes: list[str] | None = None,
) -> Any:
    """
    Resolve Google credentials and return a scoped credentials object.

    This is the single source of truth for credential resolution in toolsgdrivegsheet.
    Can also be called directly to get credentials for passing to other Google clients.

    Args:
        credentials:   Pre-resolved google credentials object (highest priority).
        keyfile_json:  Parsed service account JSON as dict.
        path_keyfile:  Path to a service account JSON key file (supports ~ and $HOME).
        scopes:        OAuth scopes to request.

    Returns:
        A scoped Google credentials object.
    """
    # 1) Pre-resolved credentials
    if credentials is not None:
        logger.debug("Using pre-resolved credentials")
        if hasattr(credentials, "with_scopes"):
            return credentials.with_scopes(scopes)
        return credentials

    # 2) Explicit JSON dict
    if keyfile_json:
        logger.debug("Using credentials from keyfile_json")
        creds = service_account.Credentials.from_service_account_info(keyfile_json)
        return creds.with_scopes(scopes)

    # 3) Explicit file path
    if path_keyfile:
        norm = _normalize_path(path_keyfile)
        if not Path(norm).is_file():
            raise FileNotFoundError(f"Service account file not found: {norm}")
        logger.debug("Using credentials from keyfile: %s", norm)
        creds = service_account.Credentials.from_service_account_file(norm)
        return creds.with_scopes(scopes)

    # 4/5/6) Env / RAM-ADC / true ADC
    _ensure_ram_adc_env_if_present()

    try:
        creds, _ = google.auth.default(scopes=scopes)
        logger.debug("Using ADC credentials")
        return creds
    except DefaultCredentialsError as e:
        hint = (
            "\n\nNo Google credentials found.\n"
            "Local options:\n"
            f" - Start your RAM-ADC session (creates {_ram_adc_key_path()})\n"
            " - Or run: gcloud auth application-default login\n"
            " - Or pass path_keyfile/keyfile_json/credentials\n"
        )
        raise DefaultCredentialsError(str(e) + hint) from e
