# Copyright (c) 2024, CoSig Contributors
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""Configuration for CoSig library.

CoSig is a cloud-first library that connects to the CoSig cloud service
(or a self-hosted instance) for hardware token approval of AI tool calls.
"""

from dataclasses import dataclass
from typing import Any


class ConfigurationError(Exception):
    """Error in CoSig configuration."""

    pass


@dataclass
class CoSigConfig:
    """Configuration for CoSig.

    Attributes:
        api_url: URL for the CoSig API (cloud or self-hosted)
        api_key: API key for authentication (organization-level)
        webhook_url: Optional webhook URL for approval notifications
        allow_insecure: Allow insecure connections (HTTP, skip TLS verify) for localhost only
    """

    api_url: str = "https://api.cosig.io"
    api_key: str = ""
    webhook_url: str | None = None
    allow_insecure: bool = False

    def __post_init__(self) -> None:
        """Validate configuration."""
        # Ensure api_url doesn't have trailing slash
        self.api_url = self.api_url.rstrip("/")

        # Validate API key format (if provided)
        if self.api_key and not self.api_key.startswith("sk_"):
            raise ConfigurationError(
                "API key must start with 'sk_' prefix. Get your API key from the CoSig dashboard."
            )

        # Enforce HTTPS for non-localhost URLs
        url_lower = self.api_url.lower()
        is_localhost = (
            "://localhost" in url_lower
            or "://127.0.0.1" in url_lower
            or "://host.docker.internal" in url_lower
        )

        if not is_localhost and not url_lower.startswith("https://"):
            raise ConfigurationError(
                f"HTTPS required for remote API URLs. Got: {self.api_url}. "
                "Use 'https://' or set allow_insecure=True for localhost only."
            )

        # Warn about insecure mode
        if self.allow_insecure and not is_localhost:
            raise ConfigurationError(
                "allow_insecure=True is only allowed for localhost URLs. "
                "Remote connections must use HTTPS."
            )

    def to_dict(self) -> dict[str, Any]:
        """Convert config to dictionary."""
        return {
            "api_url": self.api_url,
            "api_key": self.api_key,
            "webhook_url": self.webhook_url,
            "allow_insecure": self.allow_insecure,
        }


# Global configuration instance
_config: CoSigConfig | None = None


def get_config() -> CoSigConfig:
    """Get the current configuration.

    Returns:
        Current CoSig configuration

    Raises:
        RuntimeError: If not configured (no API key set)
    """
    global _config
    if _config is None:
        _config = CoSigConfig()
    return _config


def configure(
    api_url: str = "https://api.cosig.io",
    api_key: str = "",
    webhook_url: str | None = None,
    allow_insecure: bool = False,
) -> CoSigConfig:
    """Configure CoSig.

    Example:
        import cosig

        cosig.configure(
            api_url="https://api.cosig.io",  # or self-hosted URL
            api_key="sk_your_api_key",  # organization API key
        )

    For local development:
        cosig.configure(
            api_url="http://localhost:8000/api/v1",
            api_key="sk_test_key",
            allow_insecure=True,  # Only for localhost
        )

    Args:
        api_url: URL for the CoSig API (default: https://api.cosig.io)
        api_key: API key for authentication (organization-level, must start with 'sk_')
        webhook_url: Optional webhook URL for approval notifications
        allow_insecure: Allow HTTP and skip TLS verification (localhost only)

    Returns:
        The configuration object

    Raises:
        ConfigurationError: If configuration is invalid
    """
    global _config

    _config = CoSigConfig(
        api_url=api_url,
        api_key=api_key,
        webhook_url=webhook_url,
        allow_insecure=allow_insecure,
    )

    return _config


def reset_config() -> None:
    """Reset the configuration to default state.

    Useful for testing.
    """
    global _config
    _config = None
