#  Copyright (C) 2025
#  ABM, Moscow
#
#  UNPUBLISHED PROPRIETARY MATERIAL.
#  ALL RIGHTS RESERVED.
#
#  Authors: Mike Orlov <m.orlov@abm-jsc.ru>
import functools
from dataclasses import dataclass
from typing import Mapping

from frozendict import frozendict
from http_tools import ContentType
from init_helpers import Jsonable

from .content_schema import ContentSchema
from .spec_ref import SpecRef
from .spec_resource import SpecResource


@dataclass(frozen=True, slots=True)
class RequestBody(SpecResource):
    """Request Body https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#request-body-object"""
    content_type_to_schema: Mapping[ContentType, ContentSchema]
    description: str = ''
    required: bool = True

    def __post_init__(self):
        object.__setattr__(self, 'content_type_to_schema', frozendict(self.content_type_to_schema))

    def get_spec_dependencies(self) -> frozenset['SpecResource']:
        return frozenset(schema for schema in self.content_type_to_schema.values())

    def get_spec_dict(self, dependency_to_ref: Mapping['SpecResource', SpecRef]) -> frozendict[str, Jsonable]:
        result: dict[str, Jsonable] = {'required': self.required} if self.required else {}
        # noinspection PyTypeChecker
        result['content'] = frozendict({t: dependency_to_ref[s] for t, s in self.content_type_to_schema.items()})
        result |= {'description': self.description} if self.description else {}
        return frozendict(result)

    @functools.cache
    def _get_repr_parts(self) -> tuple[str, ...]:
        parts = [repr({content_type.value: schema for content_type, schema in self.content_type_to_schema.items()})]
        parts += [f'description={self.description!r}'] if self.description else []
        parts += [f'required={self.required!r}'] if not self.required else []
        return tuple(parts)

    def __repr__(self):
        return f'{self.__class__.__name__}({", ".join(self._get_repr_parts())})'

    __str__ = __repr__
