from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import JSONResponse, Response from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from db_setup import get_session from reports.views import Report from users.permissions import PermissionTag, require_permission router = APIRouter() class SavedReportCreate(BaseModel): name: str report_type: str description: str | None = None filters: dict | None = None class SavedReportUpdate(BaseModel): name: str | None = None report_type: str | None = None description: str | None = None filters: dict | None = None class ReportRunRequest(BaseModel): record_id: str | None = None report_type: str | None = None filters: dict | None = None @router.get("/reports/fetch") async def fetch_reports( current_user: dict = Depends(require_permission(PermissionTag.REPORTS_VIEW)), session: AsyncSession = Depends(get_session), ): try: service = Report(session=session) data, total = await service.get_reports(current_user) return JSONResponse(content={"data": data, "total": total, "status_code": 200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/reports/create") async def create_report( payload: SavedReportCreate, current_user: dict = Depends(require_permission(PermissionTag.REPORTS_CREATE)), session: AsyncSession = Depends(get_session), ): try: service = Report(session=session) data = await service.create_report(payload.model_dump(exclude_unset=True), current_user) return JSONResponse(content={"data": data, "status_code": 200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.patch("/reports/update") async def update_report( payload: SavedReportUpdate, current_user: dict = Depends(require_permission(PermissionTag.REPORTS_EDIT)), record_id: str = Query(...), session: AsyncSession = Depends(get_session), ): try: service = Report(session=session) data = await service.update_report( record_id, payload.model_dump(exclude_unset=True), current_user ) return JSONResponse(content={"data": data, "status_code": 200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.delete("/reports/delete") async def delete_report( current_user: dict = Depends(require_permission(PermissionTag.REPORTS_DELETE)), record_id: str = Query(...), session: AsyncSession = Depends(get_session), ): try: service = Report(session=session) data = await service.delete_report(record_id, current_user) return JSONResponse(content={"data": data, "status_code": 200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post("/reports/run") async def run_report( payload: ReportRunRequest, current_user: dict = Depends(require_permission(PermissionTag.REPORTS_VIEW)), session: AsyncSession = Depends(get_session), ): try: service = Report(session=session) data = await service.run( current_user, record_id=payload.record_id, report_type=payload.report_type, filters=payload.filters, ) return JSONResponse(content={"data": data, "total": data["row_count"], "status_code": 200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/reports/export") async def export_report( current_user: dict = Depends(require_permission(PermissionTag.REPORTS_EXPORT)), record_id: str | None = Query(None), report_type: str | None = Query(None), from_date: str | None = Query(None), to_date: str | None = Query(None), window_days: int | None = Query(None), department: str | None = Query(None), recruiter_id: str | None = Query(None), months: int | None = Query(None), top: int | None = Query(None), session: AsyncSession = Depends(get_session), ): try: service = Report(session=session) filename, body = await service.export_csv( current_user, record_id=record_id, report_type=report_type, filters={ "from_date": from_date, "to_date": to_date, "window_days": window_days, "department": department, "recruiter_id": recruiter_id, "months": months, "top": top, }, ) return Response( content=body, media_type="text/csv; charset=utf-8", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, ) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/reports/runs/fetch") async def fetch_report_runs( current_user: dict = Depends(require_permission(PermissionTag.REPORTS_VIEW)), record_id: str = Query(...), session: AsyncSession = Depends(get_session), ): try: service = Report(session=session) data = await service.get_runs(record_id, current_user) return JSONResponse(content={"data": data, "total": len(data), "status_code": 200}) except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e))