#  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, ClassVar

from frozendict import frozendict
from init_helpers import Jsonable

from openapi_tools.spec.spec_resource import SpecResource, SpecRef
from .base_schema import BaseSchema
from .type_schema import TypeSchema


@dataclass(frozen=True, slots=True)
class ArraySchema(TypeSchema):
    type_: ClassVar[str] = "array"
    items_schema: BaseSchema | SpecRef | None = None
    is_uniqueness_required: bool = False

    @functools.cache
    def get_spec_dependencies(self) -> frozenset['SpecResource']:
        return frozenset(BaseSchema.get_spec_dependencies(self) | (
            {self.items_schema} if isinstance(self.items_schema, SpecResource) else set()))

    def get_spec_dict(self, dependency_to_ref: Mapping['SpecResource', SpecRef | dict]) -> frozendict[str, Jsonable]:
        result = {}
        if (sub_schema := self.items_schema) is not None:
            result |= {'items': sub_schema if isinstance(sub_schema, SpecRef) else dependency_to_ref[sub_schema]}
        if self.is_uniqueness_required:
            result |= {'uniqueItems': self.is_uniqueness_required}
        return frozendict(TypeSchema.get_spec_dict(self, dependency_to_ref) | result)

    @functools.cache
    def _get_repr_parts(self) -> tuple[str, ...]:
        parts = list(TypeSchema._get_repr_parts(self))
        parts += [f'items_schema={self.items_schema!r}'] if self.items_schema else []
        parts += [f'is_uniqueness_required={self.is_uniqueness_required!r}'] if self.is_uniqueness_required else []
        return tuple(parts)

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

    __str__ = __repr__
