"""Session configuration for Agent Berlin SDK.

This module provides utilities to persist authentication credentials
for subsequent SDK usage, reducing the need to pass token and project
domain to every script.
"""

import json
import os
from pathlib import Path
from typing import Optional


def _get_config_paths() -> list[Path]:
    """Return config file paths in priority order."""
    paths = []

    # Home directory config (preferred)
    home = Path.home()
    paths.append(home / ".agentberlin" / "config.json")

    # Current working directory config (fallback)
    paths.append(Path.cwd() / ".agentberlin" / "config.json")

    return paths


def _get_writable_config_path() -> Path:
    """Return the first writable config path."""
    for config_path in _get_config_paths():
        try:
            config_path.parent.mkdir(parents=True, exist_ok=True)
            # Test if we can write to this location
            test_file = config_path.parent / ".write_test"
            test_file.touch()
            test_file.unlink()
            return config_path
        except (OSError, PermissionError):
            continue

    # Fallback to CWD if nothing else works
    return Path.cwd() / ".agentberlin" / "config.json"


def configure_session(
    token: str,
    project_domain: str,
    expires_at: Optional[int] = None,
    config_path: Optional[str] = None,
) -> None:
    """Save session credentials to a config file for subsequent SDK usage.

    This function persists the authentication token and project domain to a
    config file. Subsequent calls to AgentBerlin() will automatically load
    these credentials, eliminating the need to pass them explicitly.

    Args:
        token: Authentication token from get_auth_token MCP tool.
        project_domain: The project domain to work with (e.g., "example.com").
        expires_at: Optional Unix timestamp when the token expires. If provided,
                    the SDK will proactively refresh tokens before they expire.
        config_path: Optional custom config file path. If not provided,
                     saves to ~/.agentberlin/config.json (preferred) or
                     falls back to .agentberlin/config.json in CWD.

    Example:
        >>> from agentberlin import configure_session, AgentBerlin
        >>> configure_session("eyJ...", "example.com")
        >>> client = AgentBerlin()  # Token and domain auto-loaded
    """
    if config_path:
        path = Path(config_path)
    else:
        path = _get_writable_config_path()

    # Ensure directory exists
    path.parent.mkdir(parents=True, exist_ok=True)

    # Write config
    config = {
        "token": token,
        "project_domain": project_domain,
    }

    if expires_at is not None:
        config["expires_at"] = expires_at

    with open(path, "w") as f:
        json.dump(config, f, indent=2)


def load_session_config(config_path: Optional[str] = None) -> dict:
    """Load session configuration from config file.

    Args:
        config_path: Optional custom config file path. If not provided,
                     searches in order:
                     1. ~/.agentberlin/config.json
                     2. .agentberlin/config.json (CWD)

    Returns:
        Dict with 'token' and 'project_domain' keys, or empty dict if not found.
    """
    if config_path:
        paths = [Path(config_path)]
    else:
        paths = _get_config_paths()

    for path in paths:
        if path.exists():
            try:
                with open(path) as f:
                    return json.load(f)
            except (json.JSONDecodeError, OSError):
                continue

    return {}


def update_session_token(
    token: str,
    expires_at: int,
    config_path: Optional[str] = None,
) -> None:
    """Update the token and expiry in an existing config file.

    This function is used by the SDK to persist refreshed tokens.

    Args:
        token: New authentication token.
        expires_at: Unix timestamp when the token expires.
        config_path: Optional custom config file path.
    """
    # Load existing config
    config = load_session_config(config_path)
    if not config:
        return  # No existing config to update

    # Determine the config path to write to
    if config_path:
        path = Path(config_path)
    else:
        # Find the existing config file
        for p in _get_config_paths():
            if p.exists():
                path = p
                break
        else:
            path = _get_writable_config_path()

    # Update token and expiry
    config["token"] = token
    config["expires_at"] = expires_at

    with open(path, "w") as f:
        json.dump(config, f, indent=2)
