"""Filesystem loader for the seed library.

Resolves paths inside the installed ``arautopilot.library`` package and
deserialises actuator profiles (JSON) and default PID tunings (YAML).
"""

from __future__ import annotations

import json
from importlib import resources
from pathlib import Path
from typing import Any

import yaml

from arautopilot.core.actuator_config import ActuatorConfig
from arautopilot.core.pid_config import PidConfig

_ACTUATOR_PACKAGE = "arautopilot.library.actuators"
_TUNINGS_PACKAGE = "arautopilot.library.default_tunings"


def list_actuator_profiles() -> list[str]:
    """Return the IDs (filename stems) of all bundled actuator profiles."""
    return sorted(
        r.name.removesuffix(".json")
        for r in resources.files(_ACTUATOR_PACKAGE).iterdir()
        if r.is_file() and r.name.endswith(".json")
    )


def list_default_tunings() -> list[str]:
    """Return the IDs (filename stems) of all bundled default tunings."""
    return sorted(
        r.name.removesuffix(".yaml")
        for r in resources.files(_TUNINGS_PACKAGE).iterdir()
        if r.is_file() and r.name.endswith(".yaml")
    )


def load_actuator_profile(profile_id: str) -> ActuatorConfig:
    """Load and validate one bundled actuator profile by ID."""
    data = _read_json_resource(_ACTUATOR_PACKAGE, f"{profile_id}.json")
    return ActuatorConfig.model_validate(data)


def load_default_tuning(tuning_id: str) -> PidConfig:
    """Load and validate one bundled default PID tuning by ID."""
    data = _read_yaml_resource(_TUNINGS_PACKAGE, f"{tuning_id}.yaml")
    return PidConfig.model_validate(data)


def load_actuator_profile_from_path(path: Path | str) -> ActuatorConfig:
    """Load an actuator profile from an arbitrary filesystem path (for tests / Studio)."""
    p = Path(path)
    with p.open("r", encoding="utf-8") as f:
        return ActuatorConfig.model_validate(json.load(f))


def load_default_tuning_from_path(path: Path | str) -> PidConfig:
    """Load a default PID tuning from an arbitrary filesystem path (for tests / Studio)."""
    p = Path(path)
    with p.open("r", encoding="utf-8") as f:
        return PidConfig.model_validate(yaml.safe_load(f))


def _read_json_resource(package: str, filename: str) -> dict[str, Any]:
    text = resources.files(package).joinpath(filename).read_text(encoding="utf-8")
    data = json.loads(text)
    if not isinstance(data, dict):
        raise ValueError(f"{package}/{filename}: expected a JSON object at the top level")
    return data


def _read_yaml_resource(package: str, filename: str) -> dict[str, Any]:
    text = resources.files(package).joinpath(filename).read_text(encoding="utf-8")
    data = yaml.safe_load(text)
    if not isinstance(data, dict):
        raise ValueError(f"{package}/{filename}: expected a YAML mapping at the top level")
    return data
