"""Environment-backed configuration for the Open Agent API integration."""

from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Dict, Mapping, Optional
from urllib.parse import urlparse


DEFAULT_BASE_URL = "https://superagent.nianxx.cn"
DEFAULT_SESSION_DB = "runtime/agent_sessions.sqlite3"
SUPPORTED_AUTH_MODES = {"bearer", "x-api-key"}
PLACEHOLDER_API_KEYS = {"changeme", "df_open_replace_me", "df_open_xxx"}
LOCAL_HTTP_HOSTS = {"localhost", "127.0.0.1", "::1"}


class AgentConfigurationError(ValueError):
    """Raised when required Agent integration configuration is invalid."""


def _positive_float(name: str, raw_value: str) -> float:
    try:
        value = float(raw_value)
    except (TypeError, ValueError) as exc:
        raise AgentConfigurationError(f"{name} must be a number") from exc
    if value <= 0:
        raise AgentConfigurationError(f"{name} must be greater than zero")
    return value


@dataclass(frozen=True)
class AgentConfig:
    """Validated runtime configuration with no implicit dotenv loading."""

    base_url: str = DEFAULT_BASE_URL
    api_key: Optional[str] = None
    auth_mode: str = "bearer"
    timeout_seconds: float = 60.0
    connect_timeout_seconds: float = 10.0
    session_db: Path = Path(DEFAULT_SESSION_DB)

    def __post_init__(self) -> None:
        base_url = self.base_url.strip().rstrip("/")
        parsed = urlparse(base_url)
        if parsed.scheme not in {"http", "https"} or not parsed.netloc:
            raise AgentConfigurationError("DEERFLOW_BASE_URL must be an absolute http(s) URL")
        if parsed.scheme == "http" and parsed.hostname not in LOCAL_HTTP_HOSTS:
            raise AgentConfigurationError(
                "DEERFLOW_BASE_URL must use HTTPS unless it points to localhost"
            )

        auth_mode = self.auth_mode.strip().lower()
        if auth_mode not in SUPPORTED_AUTH_MODES:
            raise AgentConfigurationError("DEERFLOW_AUTH_MODE must be 'bearer' or 'x-api-key'")

        api_key = self.api_key.strip() if self.api_key else None
        if self.timeout_seconds <= 0:
            raise AgentConfigurationError("DEERFLOW_TIMEOUT_SECONDS must be greater than zero")
        if self.connect_timeout_seconds <= 0:
            raise AgentConfigurationError("DEERFLOW_CONNECT_TIMEOUT_SECONDS must be greater than zero")

        object.__setattr__(self, "base_url", base_url)
        object.__setattr__(self, "auth_mode", auth_mode)
        object.__setattr__(self, "api_key", api_key)
        object.__setattr__(self, "session_db", Path(self.session_db))

    @classmethod
    def from_env(
        cls,
        env: Optional[Mapping[str, str]] = None,
        *,
        require_api_key: bool = True,
    ) -> "AgentConfig":
        source = os.environ if env is None else env
        api_key = source.get("DEERFLOW_OPEN_API_KEY", "").strip() or None
        if require_api_key and not cls._is_real_api_key(api_key):
            raise AgentConfigurationError(
                "DEERFLOW_OPEN_API_KEY is required and must replace the example placeholder"
            )

        return cls(
            base_url=source.get("DEERFLOW_BASE_URL", DEFAULT_BASE_URL),
            api_key=api_key,
            auth_mode=source.get("DEERFLOW_AUTH_MODE", "bearer"),
            timeout_seconds=_positive_float(
                "DEERFLOW_TIMEOUT_SECONDS",
                source.get("DEERFLOW_TIMEOUT_SECONDS", "60"),
            ),
            connect_timeout_seconds=_positive_float(
                "DEERFLOW_CONNECT_TIMEOUT_SECONDS",
                source.get("DEERFLOW_CONNECT_TIMEOUT_SECONDS", "10"),
            ),
            session_db=Path(source.get("DEERFLOW_SESSION_DB", DEFAULT_SESSION_DB)),
        )

    def redacted_summary(self) -> Dict[str, Any]:
        """Return configuration diagnostics without exposing the credential."""

        return {
            "base_url": self.base_url,
            "auth_mode": self.auth_mode,
            "api_key_configured": self.api_key_configured,
            "timeout_seconds": self.timeout_seconds,
            "connect_timeout_seconds": self.connect_timeout_seconds,
            "session_db": str(self.session_db),
        }

    @property
    def api_key_configured(self) -> bool:
        return self._is_real_api_key(self.api_key)

    @staticmethod
    def _is_real_api_key(api_key: Optional[str]) -> bool:
        return bool(api_key and api_key.strip().lower() not in PLACEHOLDER_API_KEYS)
