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

import sqlalchemy.orm
from dynamic_types.class_name import _prepare_class_name

from .abstract import AbstractView
from .utils import get_related_entity_type, get_remote_column
from ..entity import Entity


class RelationView(AbstractView, abc.ABC):
    @classmethod
    def _produce_view(cls, relation: sqlalchemy.orm.RelationshipProperty) -> type:
        if not isinstance(relation, sqlalchemy.orm.RelationshipProperty):
            raise TypeError(f'RelationInsertView subscription requires RelationshipProperty, got: {relation}')
        related_entity_type: type[Entity] = get_related_entity_type(relation)
        relation_remote_column = get_remote_column(relation)
        field_name_to_field = cls._produce_field_name_to_field(related_entity_type, relation_remote_column)
        class_name = _prepare_class_name([part[0].upper() + part[1:] for part in str(relation).split(".")], cls)
        return cls._produce_child_dataclass(class_name, field_name_to_field)

    @classmethod
    @abc.abstractmethod
    def _produce_field_name_to_field(cls, related_entity_type: type[Entity],
                                     relation_remote_column: sqlalchemy.Column) -> dict[str, Field | Any]:
        pass
