"""Configuration loading helpers."""

from __future__ import annotations

import os
from pathlib import Path
from typing import Any, cast

from ruamel.yaml import YAML

from revo_module_installer.config.manifest import ManifestIndex
from revo_module_installer.config.registry import RegistryIndex
from revo_module_installer.config.resources import (
    get_local_example_registry_path,
    load_text_from_location,
    resolve_raw_github_url,
    resolve_registry_index_url,
)
from revo_module_installer.constants import (
    LOCAL_REGISTRY_ENVIRONMENT_VALUE,
    LOCAL_REGISTRY_ENVIRONMENT_VARIABLE,
)


def _load_registry_from_text(registry_text: str) -> RegistryIndex:
    """Parse registry YAML content into a registry index.

    Args:
        registry_text: Raw YAML text.

    Returns:
        Parsed registry index.
    """
    yaml_parser: YAML = YAML(typ="rt")
    data: object = cast(Any, yaml_parser).load(registry_text)
    return RegistryIndex.model_validate(data)


def _load_manifest_from_text(manifest_text: str) -> ManifestIndex:
    """Parse manifest YAML content into a manifest index.

    Args:
        manifest_text: Raw YAML text.

    Returns:
        Parsed manifest index.
    """
    yaml_parser: YAML = YAML(typ="rt")
    data: object = cast(Any, yaml_parser).load(manifest_text)
    return ManifestIndex.model_validate(data)


def _load_local_registry(
    local_registry_path: Path | None,
) -> RegistryIndex:
    """Load the local example registry file.

    Args:
        local_registry_path: Path override for the example registry file.

    Returns:
        Parsed registry index.
    """
    resolved_path: Path = (
        local_registry_path
        if local_registry_path is not None
        else get_local_example_registry_path()
    )
    registry_text: str = load_text_from_location(str(resolved_path))
    return _load_registry_from_text(registry_text)


def _local_registry_allowed(allow_local_fallback: bool) -> bool:
    """Check if the local registry should be used in this environment.

    Args:
        allow_local_fallback: Whether the caller wants to allow local usage.

    Returns:
        True when local registry usage is allowed, otherwise False.
    """
    if not allow_local_fallback:
        return False

    return is_local_registry_environment()


def is_local_registry_environment() -> bool:
    """Return True when the local registry environment is active.

    Returns:
        True when the local registry environment variable is set.
    """
    environment_value: str | None = os.getenv(LOCAL_REGISTRY_ENVIRONMENT_VARIABLE)
    return environment_value == LOCAL_REGISTRY_ENVIRONMENT_VALUE


def load_registry_index(
    registry_repository_url: str,
    *,
    allow_local_fallback: bool = False,
    local_registry_path: Path | None = None,
) -> RegistryIndex:
    """Load a registry index from a URL.

    Args:
        registry_repository_url: URL to the registry git repository.
        allow_local_fallback: Whether to allow a local example registry fallback.
        local_registry_path: Optional path to the local example registry file.

    Returns:
        Parsed registry index.
    """
    registry_index_url: str = resolve_registry_index_url(registry_repository_url)
    if _local_registry_allowed(allow_local_fallback):
        return _load_local_registry(local_registry_path)
    registry_text: str = load_text_from_location(registry_index_url)
    return _load_registry_from_text(registry_text)


def load_manifest_index(
    manifest_url: str,
) -> ManifestIndex:
    """Load a manifest index from a URL or path.

    Args:
        manifest_url: URL or path to the manifest file.

    Returns:
        Parsed manifest index.
    """
    resolved_url: str = resolve_raw_github_url(manifest_url)
    manifest_text: str = load_text_from_location(resolved_url)
    return _load_manifest_from_text(manifest_text)
