"""Fail-closed configuration for loopback-only Phase 2A.3 downloads."""

from __future__ import annotations

import os
from types import MappingProxyType
from typing import Mapping

from ..errors import PbfDownloadRejected
from .models import ApprovedTestPbfDownload

PBF_TEST_ENVIRONMENT_VARIABLES: Mapping[str, str] = MappingProxyType(
    {
        "environment": "OSM_LEAD_SOURCE_PBF_DOWNLOAD_ENV",
        "region_id": "OSM_LEAD_SOURCE_TEST_PBF_REGION_ID",
        "url": "OSM_LEAD_SOURCE_TEST_PBF_URL",
        "sha256": "OSM_LEAD_SOURCE_TEST_PBF_SHA256",
        "size_bytes": "OSM_LEAD_SOURCE_TEST_PBF_SIZE_BYTES",
        "max_size_bytes": "OSM_LEAD_SOURCE_TEST_PBF_MAX_SIZE_BYTES",
        "timeout_seconds": "OSM_LEAD_SOURCE_TEST_PBF_TIMEOUT_SECONDS",
    }
)


def _required(values: Mapping[str, str], field_name: str) -> str:
    variable = PBF_TEST_ENVIRONMENT_VARIABLES[field_name]
    value = values.get(variable)
    if value is None or not value.strip():
        raise PbfDownloadRejected(f"{variable} is required")
    return value.strip()


def _parse_int(value: str, variable: str) -> int:
    try:
        return int(value)
    except ValueError:
        raise PbfDownloadRejected(f"{variable} must be an integer") from None


def _parse_float(value: str, variable: str) -> float:
    try:
        return float(value)
    except ValueError:
        raise PbfDownloadRejected(f"{variable} must be a number") from None


def load_test_pbf_download_settings(
    environ: Mapping[str, str] | None = None,
) -> ApprovedTestPbfDownload:
    """Load only explicit non-production test download variables."""

    source = os.environ if environ is None else environ
    values = {
        variable: source[variable]
        for variable in PBF_TEST_ENVIRONMENT_VARIABLES.values()
        if variable in source
    }
    environment_variable = PBF_TEST_ENVIRONMENT_VARIABLES["environment"]
    if values.get(environment_variable) != "test":
        raise PbfDownloadRejected(f"{environment_variable} must be exactly test")

    size_variable = PBF_TEST_ENVIRONMENT_VARIABLES["size_bytes"]
    max_size_variable = PBF_TEST_ENVIRONMENT_VARIABLES["max_size_bytes"]
    timeout_variable = PBF_TEST_ENVIRONMENT_VARIABLES["timeout_seconds"]
    size_bytes = _parse_int(_required(values, "size_bytes"), size_variable)
    max_size_raw = values.get(max_size_variable)
    timeout_raw = values.get(timeout_variable)

    return ApprovedTestPbfDownload(
        region_id=_required(values, "region_id"),
        url=_required(values, "url"),
        expected_sha256=_required(values, "sha256"),
        expected_size_bytes=size_bytes,
        max_size_bytes=(
            8 * 1024 * 1024 if max_size_raw is None else _parse_int(max_size_raw, max_size_variable)
        ),
        timeout_seconds=(
            5.0 if timeout_raw is None else _parse_float(timeout_raw, timeout_variable)
        ),
    )
