from fastapi import APIRouter, Depends, HTTPException, Path
from sqlmodel import Session, select
from sqlalchemy.exc import IntegrityError
from typing import List
import datetime as dt

from app.src.common.security import get_current_user
from app.src.common.utils import profiling_api
from app.src.models.app_user import AppUser
from app.src.models.tag import Tag, TagRead, TagCreate, TagUpdate
from app.src.db.engine import get_session


router = APIRouter()


async def get_tag_or_404(
    *,
    session: Session = Depends(get_session),
    tag_id: int = Path(..., ge=1),
    current_user: AppUser = Depends(get_current_user),
):
    start_time = dt.datetime.now()
    try:
        db_tag = session.get(Tag, tag_id)
        if db_tag:
            return {
                "db_tag": db_tag,
                "username": current_user.username,
                "start_time": start_time,
            }
        else:
            raise HTTPException(status_code=404, detail="Tag not found")
    except KeyError:
        raise HTTPException(status_code=400, detail="Tag not found")


async def get_tag_by_name_or_404(
    *,
    session: Session = Depends(get_session),
    tag_name: str,
    current_user: AppUser = Depends(get_current_user),
):
    start_time = dt.datetime.now()
    try:
        db_tag = session.exec(select(Tag).where(Tag.name == tag_name)).one()
        if db_tag:
            return {
                "db_tag": db_tag,
                "username": current_user.username,
                "start_time": start_time,
            }
        else:
            raise HTTPException(status_code=404, detail="Tag not found by name")
    except KeyError:
        raise HTTPException(status_code=400, detail="Tag not found by name")


@router.get("/", response_model=List[TagRead])
async def read_tags(
    *,
    session: Session = Depends(get_session),
    current_user: AppUser = Depends(get_current_user),
):
    """
    Get all the existing tags
    """
    start_time = dt.datetime.now()
    tags = session.exec(select(Tag)).all()
    profiling_api("Tags:get:all", start_time, current_user.username)
    return tags


@router.get("/{tag_id}", response_model=TagRead)
async def read_tag(*, tag_id: int, db_tag: Tag = Depends(get_tag_or_404)):
    """
    Get the tag by id
    """
    profiling_api(
        f"Tag:read:by_id:{tag_id}",
        db_tag["start_time"],
        db_tag["username"],
    )
    return db_tag["db_tag"]


@router.post("/", response_model=TagRead)
async def create_tags(
    *,
    session: Session = Depends(get_session),
    tag: TagCreate,
    current_user: AppUser = Depends(get_current_user),
):
    """
    Create a tag
    """
    start_time = dt.datetime.now()
    try:
        db_t = Tag.from_orm(tag)
        session.add(db_t)
        session.commit()
        session.refresh(db_t)
    except IntegrityError:
        raise HTTPException(
            status_code=404, detail="Impossible to create tag with same name"
        )
    profiling_api("Tag:insert:single", start_time, current_user.username)
    return db_t


@router.patch("/{tag_id}", response_model=TagRead)
async def update_tag(
    *,
    tag_id: int,
    session: Session = Depends(get_session),
    tag: TagUpdate,
    db_tag: Tag = Depends(get_tag_or_404),
):
    """
    Modify a tag
    """
    # exclude_unset=True: it would only include the values
    # that were sent by the client
    existing_tag = db_tag["db_tag"]
    tag_data = tag.dict(exclude_unset=True)
    for key, value in tag_data.items():
        setattr(existing_tag, key, value)
    session.add(existing_tag)
    session.commit()
    session.refresh(existing_tag)
    profiling_api(
        f"Tag:update:by_id:{tag_id}",
        db_tag["start_time"],
        db_tag["username"],
    )
    return existing_tag


@router.delete("/{tag_id}")
async def delete_tag(
    *,
    tag_id: int,
    session: Session = Depends(get_session),
    db_tag: Tag = Depends(get_tag_or_404),
):
    """
    Delete and remove an existing product type by id; it must be >= 1
    """
    existing_tag = db_tag["db_tag"]
    session.delete(existing_tag)
    session.commit()
    profiling_api(
        f"Tag:delete:by_id:{tag_id}",
        db_tag["start_time"],
        db_tag["username"],
    )
    return {"ok": True}

app.src.common.utils.profiling_api fastapi.HTTPException sqlmodel.select fastapi.Path app.src.models.tag.Tag.from_orm fastapi.Depends datetime.datetime.now fastapi.APIRouter
[((449, 460), 'fastapi.APIRouter', 'APIRouter', ([], {}), '()\n', (458, 460), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((519, 539), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (526, 539), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((559, 574), 'fastapi.Path', 'Path', (['...'], {'ge': '(1)'}), '(..., ge=1)\n', (563, 574), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((604, 629), 'fastapi.Depends', 'Depends', (['get_current_user'], {}), '(get_current_user)\n', (611, 629), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((651, 668), 'datetime.datetime.now', 'dt.datetime.now', ([], {}), '()\n', (666, 668), True, 'import datetime as dt\n'), ((1144, 1164), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (1151, 1164), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((1213, 1238), 'fastapi.Depends', 'Depends', (['get_current_user'], {}), '(get_current_user)\n', (1220, 1238), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((1260, 1277), 'datetime.datetime.now', 'dt.datetime.now', ([], {}), '()\n', (1275, 1277), True, 'import datetime as dt\n'), ((1838, 1858), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (1845, 1858), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((1888, 1913), 'fastapi.Depends', 'Depends', (['get_current_user'], {}), '(get_current_user)\n', (1895, 1913), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((1981, 1998), 'datetime.datetime.now', 'dt.datetime.now', ([], {}), '()\n', (1996, 1998), True, 'import datetime as dt\n'), ((2046, 2110), 'app.src.common.utils.profiling_api', 'profiling_api', (['"""Tags:get:all"""', 'start_time', 'current_user.username'], {}), "('Tags:get:all', start_time, current_user.username)\n", (2059, 2110), False, 'from app.src.common.utils import profiling_api\n'), ((2227, 2250), 'fastapi.Depends', 'Depends', (['get_tag_or_404'], {}), '(get_tag_or_404)\n', (2234, 2250), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((2295, 2383), 'app.src.common.utils.profiling_api', 'profiling_api', (['f"""Tag:read:by_id:{tag_id}"""', "db_tag['start_time']", "db_tag['username']"], {}), "(f'Tag:read:by_id:{tag_id}', db_tag['start_time'], db_tag[\n    'username'])\n", (2308, 2383), False, 'from app.src.common.utils import profiling_api\n'), ((2535, 2555), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (2542, 2555), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((2605, 2630), 'fastapi.Depends', 'Depends', (['get_current_user'], {}), '(get_current_user)\n', (2612, 2630), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((2685, 2702), 'datetime.datetime.now', 'dt.datetime.now', ([], {}), '()\n', (2700, 2702), True, 'import datetime as dt\n'), ((2974, 3043), 'app.src.common.utils.profiling_api', 'profiling_api', (['"""Tag:insert:single"""', 'start_time', 'current_user.username'], {}), "('Tag:insert:single', start_time, current_user.username)\n", (2987, 3043), False, 'from app.src.common.utils import profiling_api\n'), ((3182, 3202), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (3189, 3202), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((3242, 3265), 'fastapi.Depends', 'Depends', (['get_tag_or_404'], {}), '(get_tag_or_404)\n', (3249, 3265), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((3648, 3738), 'app.src.common.utils.profiling_api', 'profiling_api', (['f"""Tag:update:by_id:{tag_id}"""', "db_tag['start_time']", "db_tag['username']"], {}), "(f'Tag:update:by_id:{tag_id}', db_tag['start_time'], db_tag[\n    'username'])\n", (3661, 3738), False, 'from app.src.common.utils import profiling_api\n'), ((3888, 3908), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (3895, 3908), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((3928, 3951), 'fastapi.Depends', 'Depends', (['get_tag_or_404'], {}), '(get_tag_or_404)\n', (3935, 3951), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((4136, 4226), 'app.src.common.utils.profiling_api', 'profiling_api', (['f"""Tag:delete:by_id:{tag_id}"""', "db_tag['start_time']", "db_tag['username']"], {}), "(f'Tag:delete:by_id:{tag_id}', db_tag['start_time'], db_tag[\n    'username'])\n", (4149, 4226), False, 'from app.src.common.utils import profiling_api\n'), ((2727, 2744), 'app.src.models.tag.Tag.from_orm', 'Tag.from_orm', (['tag'], {}), '(tag)\n', (2739, 2744), False, 'from app.src.models.tag import Tag, TagRead, TagCreate, TagUpdate\n'), ((933, 987), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""Tag not found"""'}), "(status_code=404, detail='Tag not found')\n", (946, 987), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((1023, 1077), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(400)', 'detail': '"""Tag not found"""'}), "(status_code=400, detail='Tag not found')\n", (1036, 1077), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((1577, 1639), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""Tag not found by name"""'}), "(status_code=404, detail='Tag not found by name')\n", (1590, 1639), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((1675, 1737), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(400)', 'detail': '"""Tag not found by name"""'}), "(status_code=400, detail='Tag not found by name')\n", (1688, 1737), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((2867, 2952), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""Impossible to create tag with same name"""'}), "(status_code=404, detail='Impossible to create tag with same name'\n    )\n", (2880, 2952), False, 'from fastapi import APIRouter, Depends, HTTPException, Path\n'), ((2023, 2034), 'sqlmodel.select', 'select', (['Tag'], {}), '(Tag)\n', (2029, 2034), False, 'from sqlmodel import Session, select\n'), ((1317, 1328), 'sqlmodel.select', 'select', (['Tag'], {}), '(Tag)\n', (1323, 1328), False, 'from sqlmodel import Session, select\n')]