from typing import Any
from typing import Optional
from typing import Type
from pydantic import BaseModel  # noqa: E0611


def apply_schema(output: Any, schema: Optional[Type[BaseModel]]):
    """
    Apply schema to job outputs.

    Parameters
    ----------
    output
        The job outputs.
    schema
        A pydantic model that defines the schema to apply.

    Raises
    ------
    ValueError
        If a schema is set but there are no outputs.
    ValueError
        If the outputs do not match the schema.

    Returns
    -------
    BaseModel or Any
        Returns an instance of the schema if the schema is set or the original output.
    """
    if schema is None or isinstance(output, schema):
        return output

    if output is None:
        raise ValueError(f"Expected output of type {schema.__name__} but got no output")

    if not isinstance(output, dict):
        raise ValueError(
            f"Expected output to be {schema.__name__} or dict but got output type "
            f"of {type(output).__name__}."
        )

    return schema(**output)