BareGit
"""Startup configuration for the Firefox RDP MCP server."""

from __future__ import annotations

from dataclasses import dataclass
import ipaddress
import os
import socket

from .errors import ConfigurationError


def _readInt(name: str, default: int, minimum: int = 1) -> int:
    value = os.environ.get(name, str(default))
    try:
        result = int(value)
    except ValueError as error:
        raise ConfigurationError(
            f"{name} must be an integer."
        ) from error
    if result < minimum:
        raise ConfigurationError(
            f"{name} must be at least {minimum}."
        )
    return result


def _requireLoopback(host: str) -> None:
    try:
        addresses = socket.getaddrinfo(
            host,
            None,
            type=socket.SOCK_STREAM,
        )
    except socket.gaierror as error:
        raise ConfigurationError(
            f"FIREFOX_RDP_HOST cannot be resolved: {host}"
        ) from error
    if not addresses:
        raise ConfigurationError(
            f"FIREFOX_RDP_HOST cannot be resolved: {host}"
        )
    for address in addresses:
        value = address[4][0].split("%", 1)[0]
        if not ipaddress.ip_address(value).is_loopback:
            raise ConfigurationError(
                "FIREFOX_RDP_HOST must resolve only to loopback addresses."
            )


@dataclass(frozen=True)
class Config:
    """Hold validated immutable process configuration."""

    host: str
    port: int
    max_file_bytes: int
    max_upload_bytes: int
    upload_chunk_bytes: int
    max_elements: int
    max_text_chars: int
    request_timeout_ms: int
    log_level: str

    @classmethod
    def fromEnvironment(cls) -> "Config":
        """Read and validate all supported environment variables."""
        host = os.environ.get("FIREFOX_RDP_HOST", "127.0.0.1")
        _requireLoopback(host)
        log_level = os.environ.get(
            "FIREFOX_MCP_LOG_LEVEL",
            "info",
        ).lower()
        if log_level not in {"debug", "info", "warning", "error"}:
            raise ConfigurationError(
                "FIREFOX_MCP_LOG_LEVEL must be debug, info, warning, "
                "or error."
            )
        return cls(
            host=host,
            port=_readInt("FIREFOX_RDP_PORT", 6000),
            max_file_bytes=_readInt(
                "FIREFOX_MCP_MAX_FILE_BYTES",
                26_214_400,
            ),
            max_upload_bytes=_readInt(
                "FIREFOX_MCP_MAX_UPLOAD_BYTES",
                52_428_800,
            ),
            upload_chunk_bytes=_readInt(
                "FIREFOX_MCP_UPLOAD_CHUNK_BYTES",
                262_144,
            ),
            max_elements=_readInt("FIREFOX_MCP_MAX_ELEMENTS", 500),
            max_text_chars=_readInt(
                "FIREFOX_MCP_MAX_TEXT_CHARS",
                50_000,
            ),
            request_timeout_ms=_readInt(
                "FIREFOX_MCP_REQUEST_TIMEOUT_MS",
                30_000,
            ),
            log_level=log_level,
        )