from fastapi import FastAPI, UploadFile, File, HTTPException, Form, Body, Request from fastapi.responses import JSONResponse, FileResponse from fastapi.middleware.cors import CORSMiddleware from typing import Union, Optional from app import schemas, services import os app = FastAPI(title="AI-Powered Health Risk Profiler") # --- CORS Middleware --- app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # --- Health Check --- @app.get("/health", summary="Health Check", include_in_schema=False) async def health_check(): return {"status": "healthy"} # --- Serve the Simulator --- @app.get("/", response_class=FileResponse, include_in_schema=False) async def read_simulator(): simulator_path = os.path.join(os.path.dirname(__file__), 'simulator.html') if not os.path.exists(simulator_path): raise HTTPException(status_code=404, detail="simulator.html not found") return FileResponse(simulator_path) # --- Analyze Endpoint --- @app.post("/analyze", response_model=Union[schemas.Recommendations, schemas.IncompleteProfileError], summary="Analyze Health Survey from JSON or Image") async def analyze_survey( request: Request, file: Optional[UploadFile] = File(None) ): answers = {} confidence = 0.0 if file: if not file.content_type.startswith("image/"): raise HTTPException(status_code=400, detail="Invalid file type. Please upload an image.") image_bytes = await file.read() parsed = services.parse_survey_from_image(image_bytes) answers = parsed["answers"] confidence = parsed["confidence"] else: try: survey_json = await request.json() survey_data = schemas.SurveyInput(**survey_json) answers = survey_data.dict() confidence = 1.0 except Exception: raise HTTPException(status_code=422, detail="Invalid JSON format in request body.") required_fields = ["age", "smoker", "exercise", "diet"] missing_fields = [field for field in required_fields if field not in answers] if len(missing_fields) > len(required_fields) / 2: return schemas.IncompleteProfileError(status="incomplete_profile", reason=f">50% fields missing. Missing: {', '.join(missing_fields)}") factors = services.extract_factors(answers) risk_profile = services.classify_risk(factors) final_recommendations = services.generate_recommendations(risk_level=risk_profile["risk_level"], factors=factors) final_recommendations["confidence"] = confidence return schemas.Recommendations(**final_recommendations)