{# This template generates FastAPI router code for CRUD operations on entities and their relationships. #}
{% set e = entity %}
{% set name_lower = e.name | lower %}
from app import crud
from fastapi import APIRouter, HTTPException, UploadFile

from app.deps import SessionDep
from app.schemas import {{ e.name }}Create,{{ e.name }}Update,{{ e.name }}Out,{{ e.name }}Patch
from typing import List, Optional
{% for entity in app.entities %}
from app.models import {{ entity.name }}
from app.schemas import {{ entity.name }}Out
{% endfor %}

router = APIRouter(tags=["{{ e.name |lower }}s"])


@router.get("/")
async def read_all(
    db: SessionDep, skip: int = 0, limit: int = 100
) -> list[{{ e.name }}Out]:
    return await crud.{{ name_lower }}.get_all(db,skip=skip,limit=limit)


@router.get("/{id}")
async def read_one(db: SessionDep, id: int) -> {{ e.name }}Out:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return {{name_lower}}

@router.post("/", status_code=201)
async def create(
    *, db: SessionDep, {{ name_lower }}_in: {{ e.name }}Create
) -> {{ e.name }}Out:
    return await crud.{{ name_lower }}.create(db, obj_in={{ name_lower }}_in)


@router.put("/{id}")
async def update(
    *, db: SessionDep, id: int, {{ name_lower }}_in: {{ e.name }}Update
) -> {{ e.name }}Out:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return await crud.{{ name_lower }}.update(db, db_obj={{name_lower}}, obj_in={{ name_lower }}_in)

@router.patch("/{id}")
async def patch(
    *, db: SessionDep, id: int, {{ name_lower }}_in: {{ e.name }}Patch
) -> {{ e.name }}Out:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return await crud.{{ name_lower }}.update(db, db_obj={{name_lower}}, obj_in={{ name_lower }}_in)

@router.delete("/{id}", status_code=204)
async def delete(
    *, db: SessionDep, id: int
) -> None:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return await crud.{{ name_lower }}.delete(db, db_obj={{name_lower}})


{% for field in e.fields if field.is_file()%}

{% if loop.first %}
# Handle files
{% endif %}

@router.put("/{id}/{{ field.name }}")
async def set_{{ field.name }}(
    *, db: SessionDep, id: int, file: UploadFile
) -> {{ e.name }}Out:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    {{name_lower}}.{{ field.name }} = file
    return await crud.{{ name_lower }}.save(db, db_obj={{name_lower}})



@router.delete("/{id}/{{ field.name }}", status_code=204)
async def remove_{{ field.name }}(
    *, db: SessionDep, id: int
) -> None:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    {{name_lower}}.{{ field.name }} = None
    await crud.{{ name_lower }}.save(db, db_obj={{name_lower}})


{% endfor %}

# Handle relationships

{% for r in app.relations if entity.name in [r.to, r.from_] %}
    {% if r.type_ == 'ONE_TO_MANY'  %}

        {% if r.from_ == entity.name %}

@router.get("/{id}/{{r.field_name}}")
async def get_associated_{{r.field_name}}(db: SessionDep, id: int) -> List[{{ r.to }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return {{name_lower}}.{{r.field_name}}

@router.put("/{id}/{{r.field_name}}")
async def add_{{r.field_name}}_by_ids(db: SessionDep, id: int, ids: List[int]) -> List[{{ r.to }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    for _id in ids:
        {{name_lower}}.{{r.field_name}}.append(await crud.{{ r.to | lower }}.getOr404(db, _id))
    {{name_lower}} = await crud.{{name_lower}}.save(db, {{name_lower}})
    return {{name_lower}}.{{r.field_name}}

        {% else %}

@router.get("/{id}/{{r.backref_field_name}}")
async def get_associated_{{r.backref_field_name}}(db: SessionDep, id: int) -> Optional[{{ r.from_ }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return {{name_lower}}.{{r.backref_field_name}}

@router.put("/{id}/{{r.backref_field_name}}/{{ '{' }}{{r.backref_field_name}}_id}")
async def set_{{r.backref_field_name}}_by_id(db: SessionDep, id: int, {{r.backref_field_name}}_id: int) -> Optional[{{ r.from_ }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    {{name_lower}}.{{r.backref_field_name}} = await crud.{{ r.from_ | lower }}.getOr404(db, {{r.backref_field_name}}_id)
    {{name_lower}} = await crud.{{name_lower}}.save(db, {{name_lower}})
    return {{name_lower}}.{{r.backref_field_name}}

        {% endif %}
    {% endif %}

    {% if r.type_ == 'ONE_TO_ONE'  %}

        {% if r.from_ == entity.name %}

@router.get("/{id}/{{r.field_name}}")
async def get_associated_{{r.field_name}}(db: SessionDep, id: int) -> Optional[{{ r.to }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return {{name_lower}}.{{r.field_name}}

@router.put("/{id}/{{r.field_name}}/{{ '{' }}{{r.field_name}}_id}")
async def set_{{r.field_name}}_by_id(db: SessionDep, id: int, {{r.field_name}}_id: int) -> Optional[{{ r.to }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    {{name_lower}}.{{r.field_name}} = await crud.{{ r.to | lower }}.getOr404(db, {{r.field_name}}_id)
    {{name_lower}} = await crud.{{name_lower}}.save(db, {{name_lower}})
    return {{name_lower}}.{{r.field_name}}

        {% else %}

@router.get("/{id}/{{r.backref_field_name}}")
async def get_associated_{{r.backref_field_name}}(db: SessionDep, id: int) -> Optional[{{ r.from_ }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return {{name_lower}}.{{r.backref_field_name}}

@router.put("/{id}/{{r.backref_field_name}}/{{ '{' }}{{r.backref_field_name}}_id}")
async def set_{{r.backref_field_name}}_by_id(db: SessionDep, id: int, {{r.backref_field_name}}_id: int) -> Optional[{{ r.from_ }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    {{name_lower}}.{{r.backref_field_name}} = await crud.{{ r.from_ | lower }}.getOr404(db, {{r.backref_field_name}}_id)
    {{name_lower}} = await crud.{{name_lower}}.save(db, {{name_lower}})
    return {{name_lower}}.{{r.backref_field_name}}

        {% endif %}
    {% endif %}

{% if r.type_ == 'MANY_TO_MANY'  %}

        {% if r.from_ == entity.name %}

@router.get("/{id}/{{r.field_name}}")
async def get_associated_{{r.field_name}}(db: SessionDep, id: int) -> List[{{ r.to }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return {{name_lower}}.{{r.field_name}}

@router.put("/{id}/{{r.field_name}}")
async def add_{{r.field_name}}_by_ids(db: SessionDep, id: int, ids: List[int]) -> List[{{ r.to }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    for _id in ids:
        {{name_lower}}.{{r.field_name}}.append(await crud.{{ r.to | lower }}.getOr404(db, _id))
    {{name_lower}} = await crud.{{name_lower}}.save(db, {{name_lower}})
    return {{name_lower}}.{{r.field_name}}

        {% else %}

@router.get("/{id}/{{r.backref_field_name}}")
async def get_associated_{{r.backref_field_name}}(db: SessionDep, id: int) -> List[{{ r.from_ }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    return {{name_lower}}.{{r.backref_field_name}}

@router.put("/{id}/{{r.backref_field_name}}")
async def add_{{r.backref_field_name}}_by_ids(db: SessionDep, id: int, ids: List[int]) -> List[{{ r.from_ }}Out]:
    {{name_lower}} = await crud.{{ name_lower }}.getOr404(db, id)
    for _id in ids:
        {{name_lower}}.{{r.backref_field_name}}.append(await crud.{{ r.from_ | lower }}.getOr404(db, _id))
    {{name_lower}} = await crud.{{name_lower}}.save(db, {{name_lower}})
    return {{name_lower}}.{{r.backref_field_name}}
        {% endif %}
    {% endif %}
{% endfor %}