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

from frozendict import frozendict
from init_helpers import Jsonable

from openapi_tools.spec.spec_resource import SpecResource, SpecRef
from .schema_format import IntegerSchemaFormat
from .type_schema import TypeSchema

@dataclass(frozen=True, slots=True)
class IntegerSchema(TypeSchema):
    type_: ClassVar[str] = "integer"
    format_: IntegerSchemaFormat | None = None
    exclusive_minimum: int | None = None
    exclusive_maximum: int | None = None

    def get_spec_dict(self, dependency_to_ref: Mapping['SpecResource', SpecRef | dict]) -> frozendict[str, Jsonable]:
        result = {}
        if self.exclusive_minimum is not None:
            result |= {'exclusiveMinimum': self.exclusive_minimum}
        if self.exclusive_maximum is not None:
            result |= {'exclusiveMaximum': self.exclusive_maximum}
        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'exclusive_minimum={self.exclusive_minimum!r}'] if self.exclusive_minimum else []
        parts += [f'exclusive_maximum={self.exclusive_maximum!r}'] if self.exclusive_maximum else []
        return tuple(parts)

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

    __str__ = __repr__

#
# print('ih')
#
#
# def _tuple_str(obj_name, fields):
#     # Return a string representing each field of obj_name as a tuple
#     # member.  So, if fields is ['x', 'y'] and obj_name is "self",
#     # return "(self.x,self.y)".
#
#     # Special case for the 0-tuple.
#     if not fields:
#         return '()'
#     # Note the trailing comma, needed if this turns out to be a 1-tuple.
#     return f'({",".join([f"{obj_name}.{f.name}" for f in fields])},)'
#
# # field_list = [f for f in fields.values() if f._field_type is _FIELD]
#
#
# def _create_fn(name, args, body, *, globals=None, locals=None,
#                return_type=MISSING):
#     # Note that we may mutate locals. Callers beware!
#     # The only callers are internal to this module, so no
#     # worries about external callers.
#     if locals is None:
#         locals = {}
#     return_annotation = ''
#     if return_type is not MISSING:
#         locals['_return_type'] = return_type
#         return_annotation = '->_return_type'
#     args = ','.join(args)
#     body = '\n'.join(f'  {b}' for b in body)
#
#     # Compute the text of the entire function.
#     txt = f' def {name}({args}){return_annotation}:\n{body}'
#
#     local_vars = ', '.join(locals.keys())
#     txt = f"def __create_fn__({local_vars}):\n{txt}\n return {name}"
#     ns = {}
#     exec(txt, globals, ns)
#     return ns['__create_fn__'](**locals)
#
#
# def __create_fn__():
#  def __eq__(self,other):
#   if other.__class__ is self.__class__:
#    return (self.default,self.description,self.examples,self.key,self.enum,self.format_,self.exclusive_minimum,self.exclusive_maximum,)==(other.default,other.description,other.examples,other.key,other.enum,other.format_,other.exclusive_minimum,other.exclusive_maximum,)
#   return NotImplemented
#  return __eq__
#
# def _cmp_fn(name, op, self_tuple, other_tuple, globals):
#     # Create a comparison function.  If the fields in the object are
#     # named 'x' and 'y', then self_tuple is the string
#     # '(self.x,self.y)' and other_tuple is the string
#     # '(other.x,other.y)'.
#
#     return _create_fn(name,
#                       ('self', 'other'),
#                       [ 'if other.__class__ is self.__class__:',
#                        f' return {self_tuple}{op}{other_tuple}',
#                         'return NotImplemented'],
#                       globals=globals)
#
# field_list = dataclasses.fields(IntegerSchema)
#
# # Create __eq__ method.  There's no need for a __ne__ method,
# # since python will call __eq__ and negate it.
# flds = [f for f in field_list if f.compare]
# self_tuple = _tuple_str('self', flds)
# other_tuple = _tuple_str('other', flds)
# _cmp_fn('__eq__', '==', self_tuple, other_tuple, globals=globals)
#
# # IntegerSchema = dataclasses._process_class(
# #     IntegerSchema,
# #     frozen=True,
# #     slots=True,
# #
# #     init=True,
# #     repr=True,
# #     eq=True,
# #     order=False,
# #     unsafe_hash=False,
# #     # frozen=False,
# #     match_args=True,
# #     kw_only=False,
# #     # slots=False,
# #     weakref_slot=False
# # )