"""Centralized datatype mapping helpers for ontology + web pipelines."""

from __future__ import annotations

from functools import lru_cache
import json
from pathlib import Path
from typing import Final

_REGISTRY_FILENAME: Final = "type_registry.v0.json"


def _normalize_input(value: str | None) -> str | None:
    if not value:
        return None
    text = value.strip()
    return text or None


def _prefers_iri(value: str) -> bool:
    lowered = value.lower()
    return lowered.startswith("http://") or lowered.startswith("https://")


@lru_cache(maxsize=1)
def _registry() -> dict:
    path = Path(__file__).with_name(_REGISTRY_FILENAME)
    payload = json.loads(path.read_text(encoding="utf-8"))

    parameter_aliases: dict[str, dict] = {}
    port_aliases: dict[str, dict] = {}
    supported_port_types_compact: list[str] = []
    supported_port_types_iri: list[str] = []

    for entry in payload.get("datatypes", []):
        parameter_info = entry.get("parameter")
        port_info = entry["port"]

        supported_port_types_compact.append(port_info["canonical_compact"])
        supported_port_types_iri.append(port_info["canonical_iri"])

        if parameter_info:
            for alias in parameter_info.get("aliases", []):
                parameter_aliases[alias] = entry
        for alias in port_info.get("aliases", []):
            port_aliases[alias] = entry

    payload["_parameter_aliases"] = parameter_aliases
    payload["_port_aliases"] = port_aliases
    payload["_supported_port_types_compact"] = tuple(supported_port_types_compact)
    payload["_supported_port_types_iri"] = tuple(supported_port_types_iri)
    return payload


def _canonical_value(section: dict[str, object], prefer_iri: bool) -> str:
    key = "canonical_iri" if prefer_iri else "canonical_compact"
    return str(section[key])


def normalize_parameter_type(value: str | None) -> str | None:
    text = _normalize_input(value)
    if not text:
        return None
    entry = _registry()["_parameter_aliases"].get(text)
    if not entry:
        return text
    return _canonical_value(entry["parameter"], prefer_iri=_prefers_iri(text))


def normalize_literal_datatype(value: str | None) -> str | None:
    text = _normalize_input(value)
    if not text:
        return None
    entry = _registry()["_port_aliases"].get(text)
    if not entry:
        return text
    return _canonical_value(entry["port"], prefer_iri=_prefers_iri(text))


def parameter_type_to_literal_datatype(parameter_type: str | None) -> str | None:
    text = _normalize_input(parameter_type)
    if not text:
        return None
    entry = _registry()["_parameter_aliases"].get(text)
    if not entry:
        return None
    return _canonical_value(entry["port"], prefer_iri=_prefers_iri(text))


def normalize_port_literal_datatype(port_type: str | None) -> str | None:
    text = _normalize_input(port_type)
    if not text:
        return None
    entry = _registry()["_port_aliases"].get(text)
    if entry:
        return _canonical_value(entry["port"], prefer_iri=_prefers_iri(text))
    mapped = parameter_type_to_literal_datatype(text)
    if mapped:
        return mapped
    return text


def supported_port_literal_datatypes(*, iri: bool = False) -> tuple[str, ...]:
    key = "_supported_port_types_iri" if iri else "_supported_port_types_compact"
    return _registry()[key]

