import uuid
from typing import List

import sqlalchemy
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from sqlalchemy import ForeignKey
from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase
import datetime
import enum


class Base(DeclarativeBase):
    pass

{% for link_table in link_tables %}
class {{ link_table.name }}(Base):
    __tablename__ = "{{ link_table.table_name }}"
    _id: Mapped[int] = mapped_column(sqlalchemy.sql.sqltypes.INT, primary_key=True, autoincrement=True)
    {%- for field_name, field in link_table.left.pk.items() %}
    {{ link_table.left.snake_name }}_{{ field_name }}: Mapped[{{ field.python_type_str }}] = mapped_column(
        ForeignKey("{{ link_table.left.table_name }}.{{ field_name }}"))
    {% endfor -%}
    {{ link_table.left.snake_name }}: Mapped["{{ link_table.left.name }}"] = relationship(
        back_populates="{{ link_table.right.snake_name }}_associations"
    )
    {%- for field_name, field in link_table.right.pk.items() %}
    {{ link_table.right.snake_name }}_{{ field_name }}: Mapped[{{ field.python_type_str }}] = mapped_column(
        ForeignKey("{{ link_table.right.table_name }}.{{ field_name }}"))
    {% endfor -%}
    {{ link_table.right.snake_name }}: Mapped["{{ link_table.right.name }}"] = relationship(
        back_populates="{{ link_table.left.snake_name }}_associations"
    )

    {%- set  metadata=link_table.data_model -%}
    {%- for field_name, field in metadata.fields.items() %}
    {{ field_name }}: Mapped[{{ field.python_type_str }}] = mapped_column({{ field.sql_type_str }}, nullable=True)
    {% endfor -%}
{% endfor %}


{% for name, metadata in models.items() %}
{% if metadata.is_user %}
class User(SQLAlchemyBaseUserTableUUID, Base):
{% else %}
class {{ name }}(Base):
{% endif %}
    __tablename__ = "{{ metadata.table_name }}"
    """pk"""
    {% if not metadata.is_user %}
    {%- for field_name, field in metadata.pk.items() %}
    {{ field_name }}: Mapped[{{ field.python_type_str }}] = mapped_column({{ field.sql_type_str }}, primary_key=True)
    {% endfor -%}
    {% endif %}
    """"""

    """fields"""
    {%- for field_name, field in metadata.fields.items() %}
    {{ field_name }}: Mapped[{{ field.python_type_str }}] = mapped_column({{ field.sql_type_str }}, nullable=True)
    {% endfor -%}
    """"""

    """fk"""
    {%- for fk_name, fk in metadata.fk.items() %}
    {{ fk_name }}: Mapped[{{ fk.field.python_type_str }}] = mapped_column(ForeignKey("{{fk.other_model.table_name}}.{{ fk.other_model.require_one_pk()[0] }}"), nullable=True)
    {% endfor -%}
    """"""

    """relationship"""
    {%- for relation in metadata.relationship %}
    {% if relation.side == 'one' -%}
    relation_one_{{ relation.target.snake_name }}: Mapped["{{ relation.target.name }}"] = relationship("{{ relation.target.name }}", back_populates="relation_many_{{metadata.snake_name}}")
    {%- endif -%}
    {%- if relation.side == 'many' -%}
    relation_many_{{ relation.target.snake_name }}: Mapped[List["{{ relation.target.name }}"]] = relationship("{{ relation.target.name }}", back_populates="relation_one_{{metadata.snake_name}}")
    {%- endif -%}
    {%- if relation.side == 'both' -%}
    relation_many_{{ relation.target.snake_name }}: Mapped[List["{{ relation.target.name }}"]] = relationship(
        secondary="{{ relation.link_table.table_name }}", back_populates="relation_many_{{metadata.snake_name}}")
    {{ relation.target.snake_name }}_associations: Mapped[List["{{ relation.link_table.name }}"]] = relationship(
        back_populates="{{metadata.snake_name}}")
    {%- endif %}
    {% endfor -%}
    """"""

{% endfor %}
