""":term:`GSO` settings.

Ensuring that the required parameters are set correctly.
"""

import ipaddress
import json
import logging
import os

from pydantic import BaseSettings, NonNegativeInt

logger = logging.getLogger(__name__)


class GeneralParams(BaseSettings):
    """General parameters for a :term:`GSO` configuration file."""

    public_hostname: str
    """The hostname that :term:`GSO` is publicly served at, used for building the callback URL that the provisioning
    proxy uses."""


class InfoBloxParams(BaseSettings):
    """Parameters related to InfoBlox."""

    scheme: str
    wapi_version: str
    host: str
    username: str
    password: str


class V4Netmask(NonNegativeInt):
    le = 32


class V6Netmask(NonNegativeInt):
    le = 128


class V4NetworkParams(BaseSettings):
    """A set of parameters that describe an IPv4 network in InfoBlox."""

    containers: list[ipaddress.IPv4Network]
    networks: list[ipaddress.IPv4Network]
    mask: V4Netmask


class V6NetworkParams(BaseSettings):
    """A set of parameters that describe an IPv6 network in InfoBlox."""

    containers: list[ipaddress.IPv6Network]
    networks: list[ipaddress.IPv6Network]
    mask: V6Netmask


class ServiceNetworkParams(BaseSettings):
    """Parameters for InfoBlox.

    The parameters describe IPv4 and v6 networks, and the corresponding domain name that should be used as a suffix.
    """

    V4: V4NetworkParams
    V6: V6NetworkParams
    domain_name: str
    dns_view: str


class IPAMParams(BaseSettings):
    """A set of parameters related to :term:`IPAM`."""

    INFOBLOX: InfoBloxParams
    LO: ServiceNetworkParams
    TRUNK: ServiceNetworkParams
    GEANT_IP: ServiceNetworkParams
    SI: ServiceNetworkParams
    LT_IAS: ServiceNetworkParams


class ProvisioningProxyParams(BaseSettings):
    """Parameters for the provisioning proxy."""

    scheme: str
    api_base: str
    auth: str  # FIXME: unfinished
    api_version: int


class NetBoxParams(BaseSettings):
    """Parameters for NetBox."""

    token: str
    api: str


class OSSParams(BaseSettings):
    """The set of parameters required for running :term:`GSO`."""

    GENERAL: GeneralParams
    IPAM: IPAMParams
    NETBOX: NetBoxParams
    PROVISIONING_PROXY: ProvisioningProxyParams


def load_oss_params() -> OSSParams:
    """Look for OSS_PARAMS_FILENAME in the environment and load the parameters from that file."""
    with open(os.environ["OSS_PARAMS_FILENAME"], encoding="utf-8") as file:
        return OSSParams(**json.loads(file.read()))


if __name__ == "__main__":
    logger.debug(load_oss_params())