from typing import Any
from typing import Dict

from .... import errors
from ...utils import constants
from .fallback import fallback_serialization
from .pydantic import pydantic_serialization


def serialize_dataset_parameters(
    parameters: Dict[str, Any], strict: bool = False
) -> Dict[str, str]:
    """In the XSD dataset schema the parameters are all strings.

    This method serializes parameter values with Pydantic validation and type coercion.

    :raises IcatMetadataSerializationError: If metadata serialization fails.
    :raises IcatMetadataValidationError: If ``strict=True`` and the metadata is invalid.
    :emits IcatMetadataValidationWarning: If ``strict=False`` and the metadata is invalid.
    :emits IcatMetadataDeprecatedWarning: If metadata is deprecated.
    """
    parsed_parameters, unknown_keys, error = pydantic_serialization(
        parameters, strict=strict
    )

    issues = []
    if error is not None:
        issues.append(f"{type(error).__name__}: {error}")
    if unknown_keys:
        issues.append(f"Unknown ICAT fields: {unknown_keys}")
    if issues:
        issues.append(
            f"Documentation on ICAT fields: https://icat-esrf-definitions.readthedocs.io/en/v{constants.definitions_release}/icat.html"
        )

        message = "\n\n".join(issues)
        if strict:
            raise errors.IcatMetadataValidationError(message) from error

        errors.warn(message, errors.IcatMetadataValidationWarning)

    if unknown_keys:
        unknown_parameters = {k: v for k, v in parameters.items() if k in unknown_keys}
        parsed_parameters.update(unknown_parameters)

    # Ensure all values are strings
    return fallback_serialization(parsed_parameters)
