from fastapi import APIRouter, Depends, HTTPException, Query, 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.product_type import (
    ProductType,
    ProductTypeRead,
    ProductTypeCreate,
    ProductTypeUpdate,
)
from app.src.db.engine import get_session

router = APIRouter()


# A scopo didattico inserita la validazione di producttype_id con Path:
# - non potrà essere < 1
async def get_producttype_or_404(
    *,
    session: Session = Depends(get_session),
    producttype_id: int = Path(..., ge=1),
    current_user: AppUser = Depends(get_current_user),
):
    start_time = dt.datetime.now()
    try:
        db_pt = session.get(ProductType, producttype_id)
        if db_pt:
            return {
                "db_pt": db_pt,
                "username": current_user.username,
                "start_time": start_time,
            }
        else:
            raise HTTPException(status_code=404, detail="Product type not found")
    except KeyError:
        raise HTTPException(status_code=400, detail="Product type not found")


@router.get("/", response_model=List[ProductTypeRead])
# lte -> less than or equal
async def read_product_types(
    *,
    session: Session = Depends(get_session),
    offset: int = 0,
    limit: int = Query(default=100, lte=100),
    current_user: AppUser = Depends(get_current_user),
):
    """
    Get all the existing product types
    """
    start_time = dt.datetime.now()
    product_types = session.exec(select(ProductType).offset(offset).limit(limit)).all()
    profiling_api("ProductType:get:all", start_time, current_user.username)
    return product_types


@router.get("/{producttype_id}", response_model=ProductTypeRead)
async def read_product_type(
    *, producttype_id: int, db_pt: ProductType = Depends(get_producttype_or_404)
):
    """
    Get the product type by id
    """
    profiling_api(
        f"ProductType:read:by_id:{producttype_id}",
        db_pt["start_time"],
        db_pt["username"],
    )
    return db_pt["db_pt"]


@router.post("/", response_model=ProductTypeRead)
async def create_product_type(
    *,
    session: Session = Depends(get_session),
    product_type: ProductTypeCreate,
    current_user: AppUser = Depends(get_current_user),
):
    """
    Create a product type
    """
    start_time = dt.datetime.now()
    try:
        db_pt = ProductType.from_orm(product_type)
        session.add(db_pt)
        session.commit()
        session.refresh(db_pt)
    except IntegrityError:
        raise HTTPException(
            status_code=404, detail="Impossible to create product type with same name"
        )
    profiling_api("ProductType:insert:single", start_time, current_user.username)
    return db_pt


@router.patch("/{producttype_id}", response_model=ProductTypeRead)
async def update_product_type(
    *,
    producttype_id: int,
    session: Session = Depends(get_session),
    pt: ProductTypeUpdate,
    db_pt: ProductType = Depends(get_producttype_or_404),
):
    """
    Modify a product type
    """
    # exclude_unset=True: it would only include the values
    # that were sent by the client
    existing_pt = db_pt["db_pt"]
    pt_data = pt.dict(exclude_unset=True)
    for key, value in pt_data.items():
        setattr(existing_pt, key, value)
    session.add(existing_pt)
    session.commit()
    session.refresh(existing_pt)
    profiling_api(
        f"ProductType:update:by_id:{producttype_id}",
        db_pt["start_time"],
        db_pt["username"],
    )
    return existing_pt


@router.delete("/{producttype_id}")
async def delete_product_type(
    *,
    producttype_id: int,
    session: Session = Depends(get_session),
    db_pt: ProductType = Depends(get_producttype_or_404),
):
    """
    Delete and remove an existing product type by id; it must be >= 1
    """
    existing_db_pt = db_pt["db_pt"]
    session.delete(existing_db_pt)
    session.commit()
    profiling_api(
        f"ProductType:delete:by_id:{producttype_id}",
        db_pt["start_time"],
        db_pt["username"],
    )
    return {"ok": True}

app.src.models.product_type.ProductType.from_orm fastapi.HTTPException sqlmodel.select datetime.datetime.now fastapi.APIRouter app.src.common.utils.profiling_api fastapi.Query fastapi.Path fastapi.Depends
[((518, 529), 'fastapi.APIRouter', 'APIRouter', ([], {}), '()\n', (527, 529), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((693, 713), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (700, 713), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((741, 756), 'fastapi.Path', 'Path', (['...'], {'ge': '(1)'}), '(..., ge=1)\n', (745, 756), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((786, 811), 'fastapi.Depends', 'Depends', (['get_current_user'], {}), '(get_current_user)\n', (793, 811), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((833, 850), 'datetime.datetime.now', 'dt.datetime.now', ([], {}), '()\n', (848, 850), True, 'import datetime as dt\n'), ((1435, 1455), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (1442, 1455), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((1495, 1522), 'fastapi.Query', 'Query', ([], {'default': '(100)', 'lte': '(100)'}), '(default=100, lte=100)\n', (1500, 1522), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((1552, 1577), 'fastapi.Depends', 'Depends', (['get_current_user'], {}), '(get_current_user)\n', (1559, 1577), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((1654, 1671), 'datetime.datetime.now', 'dt.datetime.now', ([], {}), '()\n', (1669, 1671), True, 'import datetime as dt\n'), ((1764, 1835), 'app.src.common.utils.profiling_api', 'profiling_api', (['"""ProductType:get:all"""', 'start_time', 'current_user.username'], {}), "('ProductType:get:all', start_time, current_user.username)\n", (1777, 1835), False, 'from app.src.common.utils import profiling_api\n'), ((2006, 2037), 'fastapi.Depends', 'Depends', (['get_producttype_or_404'], {}), '(get_producttype_or_404)\n', (2013, 2037), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((2092, 2194), 'app.src.common.utils.profiling_api', 'profiling_api', (['f"""ProductType:read:by_id:{producttype_id}"""', "db_pt['start_time']", "db_pt['username']"], {}), "(f'ProductType:read:by_id:{producttype_id}', db_pt[\n    'start_time'], db_pt['username'])\n", (2105, 2194), False, 'from app.src.common.utils import profiling_api\n'), ((2360, 2380), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (2367, 2380), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((2447, 2472), 'fastapi.Depends', 'Depends', (['get_current_user'], {}), '(get_current_user)\n', (2454, 2472), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((2536, 2553), 'datetime.datetime.now', 'dt.datetime.now', ([], {}), '()\n', (2551, 2553), True, 'import datetime as dt\n'), ((2854, 2931), 'app.src.common.utils.profiling_api', 'profiling_api', (['"""ProductType:insert:single"""', 'start_time', 'current_user.username'], {}), "('ProductType:insert:single', start_time, current_user.username)\n", (2867, 2931), False, 'from app.src.common.utils import profiling_api\n'), ((3104, 3124), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (3111, 3124), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((3178, 3209), 'fastapi.Depends', 'Depends', (['get_producttype_or_404'], {}), '(get_producttype_or_404)\n', (3185, 3209), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((3592, 3696), 'app.src.common.utils.profiling_api', 'profiling_api', (['f"""ProductType:update:by_id:{producttype_id}"""', "db_pt['start_time']", "db_pt['username']"], {}), "(f'ProductType:update:by_id:{producttype_id}', db_pt[\n    'start_time'], db_pt['username'])\n", (3605, 3696), False, 'from app.src.common.utils import profiling_api\n'), ((3870, 3890), 'fastapi.Depends', 'Depends', (['get_session'], {}), '(get_session)\n', (3877, 3890), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((3917, 3948), 'fastapi.Depends', 'Depends', (['get_producttype_or_404'], {}), '(get_producttype_or_404)\n', (3924, 3948), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((4135, 4239), 'app.src.common.utils.profiling_api', 'profiling_api', (['f"""ProductType:delete:by_id:{producttype_id}"""', "db_pt['start_time']", "db_pt['username']"], {}), "(f'ProductType:delete:by_id:{producttype_id}', db_pt[\n    'start_time'], db_pt['username'])\n", (4148, 4239), False, 'from app.src.common.utils import profiling_api\n'), ((2579, 2613), 'app.src.models.product_type.ProductType.from_orm', 'ProductType.from_orm', (['product_type'], {}), '(product_type)\n', (2599, 2613), False, 'from app.src.models.product_type import ProductType, ProductTypeRead, ProductTypeCreate, ProductTypeUpdate\n'), ((1127, 1190), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""Product type not found"""'}), "(status_code=404, detail='Product type not found')\n", (1140, 1190), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((1226, 1289), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(400)', 'detail': '"""Product type not found"""'}), "(status_code=400, detail='Product type not found')\n", (1239, 1289), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((2738, 2832), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""Impossible to create product type with same name"""'}), "(status_code=404, detail=\n    'Impossible to create product type with same name')\n", (2751, 2832), False, 'from fastapi import APIRouter, Depends, HTTPException, Query, Path\n'), ((1705, 1724), 'sqlmodel.select', 'select', (['ProductType'], {}), '(ProductType)\n', (1711, 1724), False, 'from sqlmodel import Session, select\n')]