from typing import List, Optional

from pydantic import BaseModel, Field
from fastapi_users import schemas
import uuid
import datetime

{% for link_table in link_tables %}
{%- set right = link_table.right -%}
{%- set left = link_table.left -%}
{% set model = link_table.data_model -%}
class LinkTable{{ link_table.left.name }}To{{ link_table.right.name }}(BaseModel):
    {% for field_name, field in model.fields.items() %}{{field_name}}: {{field.python_type_str}} = Field(
        {%- if field.default_str %}default={{field.default_str}},{%- endif -%}
        {%- if field.default_factory_str %}default_factory={{field.default_factory_str}},{%- endif -%}
    )
    {% endfor %}
    {{ right.snake_name }}: "{{ right.base_schema_name }}"

class LinkTable{{ link_table.right.name }}To{{ link_table.left.name }}(BaseModel):
    {% for field_name, field in model.fields.items() %}{{field_name}}: {{field.python_type_str}} = Field(
        {%- if field.default_str %}default={{field.default_str}},{%- endif -%}
        {%- if field.default_factory_str %}default_factory={{field.default_factory_str}},{%- endif -%}
    )
    {% endfor %}
    {{ left.snake_name }}: "{{ left.base_schema_name }}"
{% endfor -%}

{% for model in models %}
{% if model.is_user %}
class UserSchema(schemas.BaseUser[uuid.UUID]):
    """fields"""
    {% for field_name, field in model.fields.items() %}{{field_name}}: Optional[{{field.python_type_str}}] = Field(
        {%- if field.default_str %}default={{field.default_str}},{%- endif -%}
        {%- if field.default_factory_str %}default_factory={{field.default_factory_str}},{%- endif -%}
    )
    {% endfor %}

class UserCreate(schemas.BaseUserCreate):
    """fields"""
    {% for field_name, field in model.fields.items() %}{{field_name}}: Optional[{{field.python_type_str}}] = Field(
        {%- if field.default_str %}default={{field.default_str}},{%- endif -%}
        {%- if field.default_factory_str %}default_factory={{field.default_factory_str}},{%- endif -%}
    )
    {% endfor %}

class UserUpdate(schemas.BaseUserUpdate):
    """fields"""
    {% for field_name, field in model.fields.items() %}{{field_name}}: Optional[{{field.python_type_str}}] = Field(
        {%- if field.default_str %}default={{field.default_str}},{%- endif -%}
        {%- if field.default_factory_str %}default_factory={{field.default_factory_str}},{%- endif -%}
    )
    {% endfor %}

{% else %}
class {{ model.base_schema_name }}(BaseModel):
    """pk"""
    {% for field_name, field in model.pk.items() %}{{field_name}}: {{field.python_type_str}} = Field(
        {%- if field.default_str %}default={{field.default_str}},{%- endif -%}
        {%- if field.default_factory_str %}default_factory={{field.default_factory_str}},{%- endif -%}
    )
    {% endfor %}
    """fields"""
    {% for field_name, field in model.fields.items() %}{{field_name}}: {{field.python_type_str}} = Field(
        {%- if field.default_str %}default={{field.default_str}},{%- endif -%}
        {%- if field.default_factory_str %}default_factory={{field.default_factory_str}},{%- endif -%}
    )
    {% endfor %}
    class Config:
        from_attributes = True
{% endif %}
{% for combination in model.relationship_combinations %}
class {{ model.base_schema_name }}With{{ combination.name }}({{ model.base_schema_name }}):
    {%- for relation in combination.combination -%}
    {% if relation.side == 'one' %}
    {{ relation.target.snake_name }}: Optional["{{ relation.target.base_schema_name }}"] = Field(alias="relation_one_{{ relation.target.snake_name }}")
    {% elif relation.side == 'many' %}
    {{ relation.target.snake_plural_name }}: List["{{ relation.target.base_schema_name }}"] = Field(alias="relation_many_{{ relation.target.snake_name }}")
    {% elif relation.side == 'both' %}
    {{ relation.target.snake_plural_name }}: List["LinkTable{{ model.name }}To{{ relation.target.name }}"] = Field(alias="{{ relation.target.snake_name }}_associations")
    {%- endif -%}
    {% endfor %}
{% endfor -%}
{%- endfor -%}

{%- for model in models -%}
{% for combination in model.relationship_combinations %}
{{ model.base_schema_name }}With{{ combination.name }}.model_rebuild()
{%- endfor -%}
{% endfor %}

