"""Configuration management for aablocks.

Handles reading and writing settings from ~/.aab/config.json.

## Configuration Options

| Key            | Description                    | Values              | Default                                  |
| -------------- | ------------------------------ | ------------------- | ---------------------------------------- |
| `base_url`     | API endpoint URL               | HTTPS URL           | `https://api.atlas.aalphabio.com/api/v1` |
| `web_url`      | Data Portal web app URL        | HTTPS URL           | `https://atlas.aalphabio.com`            |
| `auth_domain`  | Cognito auth domain            | domain string       | `auth.atlas.aalphabio.com`               |
| `pool_id`      | Cognito user pool ID           | pool ID string      | `us-east-2_18ZA7hgrh`                   |
| `client_id`    | Cognito app client ID          | client ID string    | `7vh1h6kfah3qf9inb4q79bfl0c`            |
| `api_format`   | Default format for Python API  | csv, pandas, polars | `pandas`                                 |
| `cli_format`   | Default format for CLI output  | csv, table          | `csv`                                    |
| `progress`     | Show download progress bars    | true, false         | `true`                                   |
| `cli_verbose`  | Echo CLI activity to console   | true, false         | `false`                                  |
| `api_verbose`  | Echo API calls to console      | true, false         | `false`                                  |
| `banners`      | Show site-wide banner notices  | true, false         | `true`                                   |
| `version_check` | Warn when a newer release is on PyPI | true, false   | `true`                                   |

Banners and version warnings are skipped automatically when stderr is not
an interactive terminal (e.g. piped output, scripts, CI).

## Files

| Path                                | Description                                    |
| ----------------------------------- | ---------------------------------------------- |
| `~/.aab/config.json`                | User configuration                             |
| `~/.aab/token.json`                 | Cached authentication tokens (per environment) |
| `~/.aab/banners.json`                | Per-banner date last shown (once-per-day gate) |
| `~/.aab/version_check.json`          | Last PyPI version check (once-per-day gate)    |
| `~/.aab/logs/<domain>/activity.log` | API activity logs (UTC timestamps)             |
"""

from __future__ import annotations

import json
import os
from pathlib import Path
from typing import Any

CONFIG_DIR = Path("~/.aab").expanduser()
CONFIG_FILE_PATH = CONFIG_DIR / "config.json"


def get_config() -> dict[str, Any]:
    """Load config from ~/.aab/config.json."""
    if CONFIG_FILE_PATH.exists():
        with open(CONFIG_FILE_PATH) as f:
            return json.load(f)
    return {}


def write_secure_file(path: Path, data: dict[str, Any]) -> None:
    """Write JSON data to a file with restrictive permissions (0600 on Unix)."""
    path.parent.mkdir(parents=True, exist_ok=True)
    # Set restrictive permissions before writing content to avoid race condition
    # Windows (i.e. `nt`) relies on user directory ACLs
    if os.name != "nt":
        # Create empty file with secure permissions, then write
        fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
        with os.fdopen(fd, "w") as f:
            json.dump(data, f, indent=2)
    else:
        with open(path, "w") as f:
            json.dump(data, f, indent=2)


def set_config(key: str, value: Any) -> None:
    """Set a configuration value.

    Args:
        key: The configuration key (e.g., "api_format", "progress").
        value: The value to set.

    Examples:
        >>> aa.set_config("api_format", "polars")
        >>> aa.set_config("progress", False)
    """
    config = get_config()
    config[key] = value
    write_secure_file(CONFIG_FILE_PATH, config)


def get_api_format() -> str:
    """Get the default Python API format from config, defaults to 'pandas'.

    Valid values: csv, pandas, polars
    """
    return get_config().get("api_format", "pandas")


def get_cli_format() -> str:
    """Get the default CLI format from config, defaults to 'csv'.

    Valid values: csv, table
    """
    return get_config().get("cli_format", "csv")


def get_progress() -> bool:
    """Get whether to show progress bars, defaults to True."""
    return get_config().get("progress", True)


def get_cli_verbose() -> bool:
    """Get whether to show verbose log output in CLI, defaults to False."""
    return get_config().get("cli_verbose", False)


def get_api_verbose() -> bool:
    """Get whether to show verbose log output for API calls, defaults to False."""
    return get_config().get("api_verbose", False)


def get_banners_enabled() -> bool:
    """Get whether to show site-wide banner notices, defaults to True."""
    return get_config().get("banners", True)


def get_version_check_enabled() -> bool:
    """Get whether to warn when a newer aablocks is on PyPI, defaults to True."""
    return get_config().get("version_check", True)


def get_auth_domain() -> str:
    """Get the Cognito auth domain, defaults to production."""
    return get_config().get("auth_domain", "auth.atlas.aalphabio.com")


def get_pool_id() -> str:
    """Get the Cognito user pool ID, defaults to production."""
    return get_config().get("pool_id", "us-east-2_18ZA7hgrh")


def get_client_id() -> str:
    """Get the Cognito app client ID, defaults to production."""
    return get_config().get("client_id", "7vh1h6kfah3qf9inb4q79bfl0c")


def get_base_url() -> str:
    """Get the API base URL from config, defaults to production.

    Valid values: any URL, or use set_config("base_url", url) to configure.
    """
    return get_config().get("base_url", "https://api.atlas.aalphabio.com/api/v1")


def get_web_url() -> str:
    """Get the Data Portal web app URL from config, defaults to production.

    Used as the OAuth redirect target for the manual (``--no-callback``) login
    flow, which lands on the web app's ``/cli-login`` confirmation page instead
    of the local callback server.
    """
    return get_config().get("web_url", "https://atlas.aalphabio.com")
