from fastapi import APIRouter, Depends, HTTPException, Query, status from app.dependencies import get_current_user from app.models.user import User from app.schemas.dashboard import ( DashboardBaselineResponse, DashboardCheckDefinitionPatchItem, DashboardChecksResponse, DashboardHomeSummaryResponse, DashboardMonitorStatus, DashboardObjectAvailabilityResponse, DashboardObjectDevicesResponse, DashboardObjectOverridePatchItem, DashboardObjectPolicyPatchItem, DashboardObjectSummaryResponse, DashboardPolicyResponse, DashboardRunRequest, DashboardRunResponse, DashboardTagPolicyPatchItem, ) from app.services import dashboard_monitor as dashboard_service router = APIRouter(prefix="/api/v1/dashboard", tags=["dashboard"]) @router.get("/home-summary", response_model=DashboardHomeSummaryResponse) async def home_summary( city: str | None = None, client: str | None = None, object_ids: list[int] | None = None, tag_ids: list[int] | None = None, _: User = Depends(get_current_user), ): scope = { "city": city, "client": client, "object_ids": object_ids or [], "tag_ids": tag_ids or [], } data = await dashboard_service.get_home_summary(scope) return DashboardHomeSummaryResponse.model_validate(data) @router.get("/object/{object_id}/summary", response_model=DashboardObjectSummaryResponse) async def object_summary( object_id: int, city: str | None = None, client: str | None = None, object_ids: list[int] | None = None, tag_ids: list[int] | None = None, _: User = Depends(get_current_user), ): scope = { "city": city, "client": client, "object_ids": object_ids or [], "tag_ids": tag_ids or [], } data = await dashboard_service.get_object_summary(object_id, scope) if data is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Object not found") return DashboardObjectSummaryResponse.model_validate(data) @router.get("/object/{object_id}/devices", response_model=DashboardObjectDevicesResponse) async def object_devices( object_id: int, city: str | None = None, client: str | None = None, object_ids: list[int] | None = None, tag_ids: list[int] | None = None, _: User = Depends(get_current_user), ): scope = { "city": city, "client": client, "object_ids": object_ids or [], "tag_ids": tag_ids or [], } data = await dashboard_service.get_object_devices(object_id, scope) if data is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Object not found") return DashboardObjectDevicesResponse.model_validate(data) @router.get("/object/{object_id}/availability", response_model=DashboardObjectAvailabilityResponse) async def object_availability( object_id: int, window: str = Query("24h"), device_ids: list[int] | None = None, compact: bool = Query(False), _: User = Depends(get_current_user), ): data = await dashboard_service.get_object_availability( object_id, window=window, device_ids=device_ids, compact=compact, ) if data is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Object not found") return DashboardObjectAvailabilityResponse.model_validate(data) @router.get("/monitor/status", response_model=DashboardMonitorStatus) async def monitor_status(_: User = Depends(get_current_user)): row = await dashboard_service.get_monitor_status() return DashboardMonitorStatus.model_validate(row, from_attributes=True) @router.post("/monitor/run", response_model=DashboardRunResponse) async def monitor_run(body: DashboardRunRequest, _: User = Depends(get_current_user)): accepted, running, detail = await dashboard_service.request_manual_run( scope=body.model_dump(exclude={"force"}), force=body.force, ) return DashboardRunResponse(accepted=accepted, running=running, detail=detail) @router.get("/monitor/policy", response_model=DashboardPolicyResponse) async def monitor_policy(_: User = Depends(get_current_user)): object_policies, tag_policies = await dashboard_service.get_policy() return DashboardPolicyResponse(object_policies=object_policies, tag_policies=tag_policies) @router.patch("/monitor/policy/objects", response_model=DashboardPolicyResponse) async def patch_object_policy(body: list[DashboardObjectPolicyPatchItem], _: User = Depends(get_current_user)): await dashboard_service.patch_object_policy([i.model_dump() for i in body]) object_policies, tag_policies = await dashboard_service.get_policy() return DashboardPolicyResponse(object_policies=object_policies, tag_policies=tag_policies) @router.patch("/monitor/policy/tags", response_model=DashboardPolicyResponse) async def patch_tag_policy(body: list[DashboardTagPolicyPatchItem], _: User = Depends(get_current_user)): await dashboard_service.patch_tag_policy([i.model_dump() for i in body]) object_policies, tag_policies = await dashboard_service.get_policy() return DashboardPolicyResponse(object_policies=object_policies, tag_policies=tag_policies) @router.get("/checks", response_model=DashboardChecksResponse) async def dashboard_checks(_: User = Depends(get_current_user)): checks, overrides = await dashboard_service.list_checks_with_overrides() return DashboardChecksResponse(checks=checks, object_overrides=overrides) @router.patch("/checks", response_model=DashboardChecksResponse) async def patch_checks(body: list[DashboardCheckDefinitionPatchItem], _: User = Depends(get_current_user)): await dashboard_service.patch_checks([item.model_dump(exclude_none=True) for item in body]) checks, overrides = await dashboard_service.list_checks_with_overrides() return DashboardChecksResponse(checks=checks, object_overrides=overrides) @router.patch("/checks/object-overrides", response_model=DashboardChecksResponse) async def patch_object_overrides(body: list[DashboardObjectOverridePatchItem], _: User = Depends(get_current_user)): await dashboard_service.patch_object_overrides([item.model_dump(exclude_none=False) for item in body]) checks, overrides = await dashboard_service.list_checks_with_overrides() return DashboardChecksResponse(checks=checks, object_overrides=overrides) @router.post("/object/{object_id}/baseline", response_model=DashboardBaselineResponse) async def save_baseline(object_id: int, _: User = Depends(get_current_user)): count = await dashboard_service.save_object_baseline(object_id) items = await dashboard_service.get_object_baseline(object_id) return DashboardBaselineResponse(object_id=object_id, count=count, items=items) @router.delete("/object/{object_id}/baseline", response_model=DashboardBaselineResponse) async def clear_baseline(object_id: int, _: User = Depends(get_current_user)): await dashboard_service.clear_object_baseline(object_id) return DashboardBaselineResponse(object_id=object_id, count=0, items=[]) @router.get("/object/{object_id}/baseline", response_model=DashboardBaselineResponse) async def get_baseline(object_id: int, _: User = Depends(get_current_user)): items = await dashboard_service.get_object_baseline(object_id) return DashboardBaselineResponse(object_id=object_id, count=len(items), items=items)