"""Authentication module for Hikaflow CLI.

This module provides a unified interface to authentication functionality.
Credential storage is handled by `autodebug.config` and OAuth flows by
`autodebug.oauth`.

Public API:
- save_token(token)        - Save a manual JWT token
- save_credentials(data)   - Save credential dict to disk
- get_credentials()        - Load stored credentials
- clear_credentials()      - Delete stored credentials
- is_authenticated()       - Check if user has valid credentials
- load_config()            - Load merged config (env vars + file + creds)
- get_valid_token()        - Get valid token with auto-refresh
- get_api_base()           - Get API base URL
- browser_auth_flow()      - Async PKCE browser OAuth flow
- device_auth_flow()       - Async device code OAuth flow
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Optional

from autodebug.config import (
    clear_credentials,
    get_api_base,
    get_valid_token,
    is_authenticated,
    load_credentials,
)
from autodebug.config import (
    save_credentials as _config_save_credentials,
)

# Re-export path constants for backward compatibility (used by tests)
HIKAFLOW_DIR = Path.home() / ".hikaflow"
CREDENTIALS_FILE = HIKAFLOW_DIR / "credentials.json"
CONFIG_FILE = HIKAFLOW_DIR / "config.json"


def save_credentials(data: dict) -> None:
    """Save credentials to disk.

    Merges with existing credentials before saving.

    Args:
        data: Credentials dict with token, refresh_token, etc.
    """
    _config_save_credentials(data)


def save_token(token: str) -> None:
    """Save a manual JWT token.

    Args:
        token: JWT token string
    """
    save_credentials({"token": token})


def get_credentials() -> Optional[dict]:
    """Get stored credentials.

    Returns:
        Credentials dict or None if no credentials exist.
    """
    creds = load_credentials()
    return creds if creds else None


def load_config() -> dict:
    """Load configuration merged from env vars, config file, and credentials.

    Returns:
        Config dict with api_base, token, email, etc.
    """
    config = {
        "api_base": get_api_base(),
    }

    # Merge config file if it exists
    if CONFIG_FILE.exists():
        try:
            file_config = json.loads(CONFIG_FILE.read_text())
            config.update(file_config)
        except (json.JSONDecodeError, OSError):
            pass

    # Merge credentials
    creds = load_credentials()
    if creds:
        config.update(creds)

    return config


async def browser_auth_flow() -> bool:
    """PKCE browser authentication flow (async wrapper).

    Opens browser for OAuth sign-in, runs local server for callback.

    Returns:
        True if authentication successful.
    """
    import asyncio

    from autodebug.oauth import pkce_browser_flow as _sync_browser_flow

    success, message = await asyncio.to_thread(_sync_browser_flow)
    if not success:
        print(f"Login failed: {message}")
    return success


async def device_auth_flow() -> bool:
    """Device code authentication flow (async wrapper).

    Displays a code for the user to enter on a web page.

    Returns:
        True if authentication successful.
    """
    import asyncio

    from autodebug.oauth import device_auth_flow as _sync_device_flow

    success, message = await asyncio.to_thread(_sync_device_flow)
    if not success:
        print(f"Login failed: {message}")
    return success


async def refresh_token() -> bool:
    """Refresh the access token using refresh token (async wrapper).

    Returns:
        True if refresh successful.
    """
    # Use config's get_valid_token which handles refresh internally
    token = get_valid_token()
    return token is not None
