"""Generate delivery metadata logic.""" from fastapi import Response from delivery_metadata.constants import ( DEFAULT_FORMAT, DeliveryType, MetadataFormatVersion, StoreIds, ) from delivery_metadata.exceptions import IncompatibleXMLValue from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.amazon.amazon_formatter_audio import ( AmazonDdexErn43FormatterAudio, ) from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.amazon.amazon_formatter_video import ( AmazonDdexErn43FormatterVideo, ) from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.formatter_audio import ( DdexErn43FormatterAudio, ) from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.formatter_video import ( DdexErn43FormatterVideo, ) from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.library_ideas_freegal.library_ideas_freegal_formatter_audio import ( LibraryIdeasFreegalDdexErn43FormatterAudio, ) from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.library_ideas_freegal.library_ideas_freegal_formatter_video import ( LibraryIdeasFreegalDdexErn43FormatterVideo, ) from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.spotify.spotify_formatter_audio import ( SpotifyDdexErn43FormatterAudio, ) from delivery_metadata.logic.metadata_formatters.ddex.ddex_ern_4_3.spotify.spotify_formatter_video import ( SpotifyDdexErn43FormatterVideo, ) from delivery_metadata.logic.metadata_formatters.metadata_formatter import ( DeliveryMetadataFormatter, ) from delivery_metadata.logic.metadata_formatters.raw.formatter import RawFormatter from delivery_metadata.models import delivery_metadata as delivery_metadata_model from delivery_metadata.models.delivery_rights import ( get_delivery_rights, ) from delivery_metadata.models.schemas import ( Product, ProductAudio, ProductBundle, ProductVideo, ) store_delivery_format_version_to_metadata_formatter: dict[ MetadataFormatVersion, dict[int, dict[type[Product], type[DeliveryMetadataFormatter]]], ] = { MetadataFormatVersion.RAW: { DEFAULT_FORMAT: { ProductAudio: RawFormatter, ProductVideo: RawFormatter, ProductBundle: RawFormatter, } }, MetadataFormatVersion.DDEX_ERN_4_3: { DEFAULT_FORMAT: { ProductAudio: DdexErn43FormatterAudio, ProductVideo: DdexErn43FormatterVideo, }, StoreIds.SPOTIFY: { ProductAudio: SpotifyDdexErn43FormatterAudio, ProductVideo: SpotifyDdexErn43FormatterVideo, }, StoreIds.LIBRARY_IDEAS_FREEGAL: { ProductAudio: LibraryIdeasFreegalDdexErn43FormatterAudio, ProductVideo: LibraryIdeasFreegalDdexErn43FormatterVideo, }, StoreIds.AMAZON: { ProductAudio: AmazonDdexErn43FormatterAudio, ProductVideo: AmazonDdexErn43FormatterVideo, }, }, } async def generate( *, upc: int, store_id: int, delivery_type: DeliveryType, delivery_format_version: MetadataFormatVersion, ) -> Response: """Generate delivery metadata.""" formatter_class_dict = store_delivery_format_version_to_metadata_formatter.get( delivery_format_version ) if not formatter_class_dict: raise NotImplementedError( f"Format {delivery_format_version.value} not implemented" ) metadata = await delivery_metadata_model.get_delivery_metadata( upc=upc, store_id=store_id, delivery_type=delivery_type, ) formatter_class = get_formatter_class( delivery_format_version, type(metadata.product), store_id ) delivery_rights = get_delivery_rights(metadata) formatter = formatter_class(metadata, delivery_rights) try: return Response( content=formatter.format(), media_type=formatter.media_type, ) except ValueError as e: if ( str(e) == "All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters" ): raise IncompatibleXMLValue() from e raise e def get_formatter_class( metadata_format_version: MetadataFormatVersion, metadata_format_type: type[Product], store_id: int, ) -> type[DeliveryMetadataFormatter]: """Get formatter class.""" format_versions = store_delivery_format_version_to_metadata_formatter.get( metadata_format_version ) if not format_versions: raise NotImplementedError( f"Format {metadata_format_version.format.value} " f"for version {metadata_format_version.version} not implemented" ) formatter_class = format_versions[ store_id if store_id in format_versions.keys() else DEFAULT_FORMAT ].get(metadata_format_type) if not formatter_class: raise NotImplementedError( f"Format {metadata_format_version.format.value} " f"for version {metadata_format_version.version} " f"for {metadata_format_type.__name__} not implemented" ) return formatter_class