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

from frozendict import frozendict
from init_helpers import raise_if, Jsonable

from .spec_ref import SpecRef
from .referencable_resource import ReferencableResource, SpecResource


@dataclass(frozen=True, slots=True)
class Tag(ReferencableResource):
    can_be_inlined: ClassVar[bool] = False
    spec_path: ClassVar[list[str]] = ['tags']
    name: str
    description: str = ''
    docs_url: str = ''
    docs_description: str = ''

    def __post_init__(self):
        raise_if(not self.name, ValueError('Tag name nust be non empty string'))
        raise_if(self.docs_description and not self.docs_url, ValueError('Got docs_description without docs url'))

    @functools.cache
    def get_spec_dependencies(self) -> frozenset['SpecResource']:
        # print('get_spec_dependencies', self)
        return frozenset()

    def get_spec_dict(self, dependency_to_ref: Mapping['SpecResource', SpecRef]) -> frozendict[str, Jsonable]:
        result = {'name': self.name}
        if description := self.description:
            result['description'] = description
        if docs_url := self.docs_url:
            docs = result['externalDocs'] = {'url': docs_url}
            if docs_description := self.docs_description:
                docs['description'] = docs_description
        return frozendict(result)

    def get_spec_ref(self, key: str = '') -> str:
        return self.name

    def get_key(self) -> str:
        return self.name

    @functools.cache
    def _get_repr_parts(self) -> tuple[str, ...]:
        parts = [f'{self.name!r}']
        parts += [f'description={self.description!r}'] if self.description else []
        parts += [f'docs_url={self.docs_url!r}'] if self.docs_url else []
        parts += [f'docs_description={self.docs_description!r}'] if self.docs_description else []
        return tuple(parts)

    def merge_spec_dict(
            self,
            dependency_to_ref: Mapping['SpecResource', SpecRef],
            present_value: frozendict[str, Jsonable]
    ) -> frozendict[str, Jsonable]:
        return frozendict(present_value | self.get_spec_dict(dependency_to_ref))

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

    __str__ = __repr__
