from dataclasses import dataclass
import enum
import typing
from datetime import date, datetime

from dataclasses_avroschema.pydantic import AvroBaseModel
from pydantic.dataclasses import dataclass
from pydantic import Field, computed_field, PrivateAttr

{% macro do_enum(current_enum) -%}
class {{ current_enum.name | case_class }}(enum.Enum):{% for attr in current_enum.values %}
    {{ attr | case_class | replace("/", "_") | replace("-", "_") }} = '{{ attr | pascalcase | replace("/", "_") | replace("-", "_") }}'{% endfor -%}

{% endmacro -%}

{% macro do_class(current_class, root=False) -%}
class {{ current_class.name | case_class }}({% if current_class.generalization %}{{ current_class.generalization.name | case_class }}):{% else %}AvroBaseModel):
    _last_updated_by: str = PrivateAttr( default = None )
    _last_updated_datetime: datetime = PrivateAttr( default = None )
    _created_by: str = PrivateAttr( default = None )
    _created_datetime: datetime =  PrivateAttr( default = None )
    _source_transation_timestamp: datetime = PrivateAttr( default = None )
    _is_deleted = PrivateAttr( default = False ){% endif %}{% if current_class.id_attribute.parent == current_class %}
    {{ current_class.id_attribute.name | snakecase }}: {{current_class.id_attribute.dest_type}}{% elif current_class.generalization and not current_class.generalization.is_abstract %}
    @computed_field
    def {{ current_class.generalization.name.lower().replace(" ", "") }}_ptr_id(self) -> {{ current_class.generalization.id_attribute.dest_type }}:
        return self.{{ current_class.generalization.id_attribute.name | snakecase }}
{% endif %}
{% for attr in current_class.attributes %}{% if not attr.is_id %}    {{ attr.name | snakecase }}: {% if attr.classification %}str | {{ attr.classification.name | case_class }} = "__"
{% else %}str | None{% if attr.dest_type != 'str' %} | {% if attr.dest_type != "boolean" %}{{attr.dest_type}}{%else%}bool{%endif%}{% endif %} = "__"
{% endif %}{% endif %}{% endfor %}{% for rel in current_class.associations_from %}
    {{ rel.destination_name | snakecase }}_id: str | None{% if rel.destination.id_attribute.dest_type != 'str' %} | {{ rel.destination.id_attribute.dest_type }}{% endif %} = "__"
{% endfor %}{% if root %}{% for rel in current_class.associations_to %}
    {{ rel.source.name | snakecase }}_ids: str | typing.List[{% if "aggregate root" not in rel.source.stereotypes %}{{ rel.source.name | case_class }}{% else %}str{% endif %}] = "__"
{% endfor %}{% endif %}
    def get_field_metadata(self, attribute_name: str) -> dict:
        return self.__dataclass_fields__[attribute_name].metadata
    
    class Meta:
        namespace = "customer_core.{{ current_class.package.name | snakecase }}"

{% endmacro -%}
{% for cls in package.classes %}
{% for attr in cls.attributes %}{% if attr.classification %}
{{ do_enum(attr.classification) }}
{% endif %}{% endfor %}{% for assoc in cls.associations_to %}{% for attr in assoc.source.attributes %}{% if attr.classification %}

{{ do_enum(attr.classification) }}{% endif %}{% endfor %}{% endfor %}{% if cls.generalization %}{% for attr in cls.generalization.attributes %}{% if attr.classification %}

{{ do_enum(attr.classification) }}
{% endif %}{% endfor %}{% endif %}

{{ do_class(cls, True) }}
{% endfor %}
