"""Author-facing types: the path-role type and the UI presentation marker."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Annotated, Optional

from pydantic import Field, StringConstraints

# A path-role value. Always a string on the wire; may be a local path OR a
# remote PlayMolecule URI (slpm://, app://, bck://). Modeled as a tagged string
# (never pathlib.Path, which would normalize "slpm://x" to "slpm:/x"). Authors
# rarely use this directly — func_to_manifest auto-substitutes any pathlib.Path
# annotation with it (see _generate._substitute_paths).
PMPath = Annotated[
    str,
    StringConstraints(min_length=1),
    Field(json_schema_extra={"format": "path"}),
]


@dataclass(frozen=True)
class UI:
    """Presentation metadata attached to a parameter via ``Annotated[T, UI(...)]``.

    Collected into the manifest's ``uiSchema`` (RJSF conventions) and stripped
    out before the annotation reaches Pydantic, so it never appears in the
    JSON Schema (``inputSchema``).
    """

    group: Optional[str] = None          # -> ui:options.group (accordion section)
    widget: Optional[str] = None         # -> ui:widget (e.g. "file", "textarea")
    title: Optional[str] = None          # -> ui:title (human label)
    help: Optional[str] = None           # -> ui:help
    labels: Optional[dict] = None        # -> ui:options.labels (e.g. {"key": "Residue name"})
    hidden: bool = False                 # -> ui:widget = "hidden"
    enabled_by: Optional[str] = None     # -> ui:options.enabledBy; grayed out when that field is falsy
