from fastapi import APIRouter, Depends, HTTPException
from typing import Type, TypeAlias, Callable, Any
from uuid import UUID
from sqlalchemy.ext.asyncio import AsyncSession
from .response_schema import IDeleteResponseBase, IGetResponseBase, IPostResponseBase, IPutResponseBase, IResponseList, create_list_response, create_response
### idea da sviluppare......

def create_crud_router(
    *,
    crud,
    prefix: str = "",
    tags: list[str] | None = None,
    open_db_dependency: Callable = None,
    enable_list: bool = True,
    enable_get: bool = True,
    enable_create: bool = True,
    enable_update: bool = True,
    enable_delete: bool = True,
    enable_soft_delete: bool = False,
):
    """
    Factory per generare router CRUD standardizzati.

    Pensata per:
    - CRUDBase
    - IResponseBase / IGetResponseBase / IResponseList
    - TenantDbConfig.open_db
    """

    router = APIRouter(prefix=prefix, tags=tags or [])

    # fallback dependency (se non passato)
    db_dep = open_db_dependency or (lambda: None)

    # -------------------------
    # LIST
    # -------------------------
    if enable_list:
        @router.get("/", response_model=IResponseList[read_schema])
        async def list_items(_: None = Depends(db_dep)):
            items = await crud.get_multi()
            return create_list_response(items)

    # -------------------------
    # GET
    # -------------------------
    if enable_get:
        @router.get("/{id}", response_model=IGetResponseBase[read_schema])
        async def get_item(
            id: UUID | str | int,
            _: None = Depends(db_dep),
        ):
            obj = await crud.get(id=id)

            if not obj:
                raise HTTPException(status_code=404, detail="Not found")

            return create_response(obj, response_model=IGetResponseBase)

    # -------------------------
    # CREATE
    # -------------------------
    if enable_create:
        @router.post("/", response_model=IPostResponseBase[read_schema])
        async def create_item(
            payload: create_schema,
            db: AsyncSession = Depends(db_dep),
        ):
            obj = await crud.create(obj_in=payload, db=db)

            return create_response(obj, response_model=IPostResponseBase)

    # -------------------------
    # UPDATE
    # -------------------------
    if enable_update:
        @router.put("/{id}", response_model=IGetResponseBase[read_schema])
        async def update_item(
            id: UUID | str | int,
            payload: update_schema,
            db: AsyncSession = Depends(db_dep),
        ):
            obj = await crud.get_required(id=id, db=db)

            obj = await crud.update(
                db_obj=obj,
                obj_in=payload,
                db=db,
            )

            return create_response(obj, response_model=IPutResponseBase)

    # -------------------------
    # DELETE
    # -------------------------
    if enable_delete:
        @router.delete("/{id}", response_model=IDeleteResponseBase[None])
        async def delete_item(
            id: UUID | str | int,
            db: AsyncSession = Depends(db_dep),
        ):
            deleted = await crud.delete(id=id, db=db)

            if not deleted:
                raise HTTPException(status_code=404, detail="Not found")

            return create_response(None, response_model=IDeleteResponseBase)

    # -------------------------
    # SOFT DELETE (opzionale)
    # -------------------------
    if enable_soft_delete:
        @router.delete("/soft/{id}", response_model=IDeleteResponseBase[None])
        async def soft_delete_item(
            id: UUID | str | int,
            db: AsyncSession = Depends(db_dep),
        ):
            deleted = await crud.soft_delete(id=id, db=db)

            if not deleted:
                raise HTTPException(status_code=404, detail="Not found")

            return create_response(None, response_model=IDeleteResponseBase)

    return router