from typing import Optional
from typing import Sequence

from . import hdf5

DEFAULT_ENTRY_NAME = "results"
DEFAULT_FIT_NAME = "fit"


def compose_full_output_uri(
    output_root_uri: str,
    default_output_data_path: Optional[str] = None,
    extra_data_paths: Optional[Sequence[str]] = None,
) -> str:
    """
    Compose a full HDF5 URI by combining a root URI with optional data path default and extra data paths.

    The function returns a URI in the form `file_path::/data/path`, merging:
    1. The base file path from `output_root_uri`.
    2. Default data path segments if the root path is shorter than expected.
    3. Optional additional path segments from `extra_data_paths`.

    :param output_root_uri: The root HDF5 URI, e.g., "file.h5::/1.1/detector_name/fit".
    :param default_output_data_path: Optional default HDF5 data path to fill in missing segments.
    :param extra_end_path: Optional extra path components to append to the final data path.
    :return: The composed HDF5 URI with file path and full data path.

    Example:

    .. code-block:: python

        uri = compose_full_output_uri(
            "results.h5::/1.1",
            default_output_data_path="results/detector_name",
            extra_data_paths=("fit",),
        )
        # Result: "results.h5::/1.1/detector_name/fit"
    """
    if not default_output_data_path:
        default_output_data_path = DEFAULT_ENTRY_NAME

    file_path, data_path = hdf5.split_h5uri(output_root_uri)

    default_parts = hdf5.split_h5data_path(default_output_data_path)

    data_parts = hdf5.split_h5data_path(data_path)
    n = len(default_parts) - len(data_parts)
    if n > 0:
        data_parts += default_parts[-n:]

    for extra_data_path in extra_data_paths or []:
        if extra_data_path:
            data_parts += hdf5.split_h5data_path(extra_data_path)

    full_data_path = "/".join(data_parts)

    return f"{file_path}::{full_data_path}"
