from fastapi import APIRouter, Request, HTTPException, Depends from fastapi.responses import JSONResponse from typing import Dict, Any import config from llm.models import LLMResponse, JiraWebhookPayload, JiraAnalysisResponse from database.database import get_db_session # Removed Session import here from sqlalchemy.orm import Session # Added correct SQLAlchemy import from database.crud import get_all_analysis_records, delete_all_analysis_records, get_analysis_by_id, create_analysis_record, get_pending_analysis_records, update_record_status router = APIRouter( prefix="/api", tags=["API"] ) @router.get("/request") async def get_analysis_records_endpoint(db: Session = Depends(get_db_session)): """Get analysis records""" try: records = get_all_analysis_records(db) return JSONResponse( status_code=200, content={"data": records} ) except Exception as e: return JSONResponse( status_code=500, content={"error": str(e)} ) @router.post("/request", status_code=201) async def create_analysis_record_endpoint( payload: JiraWebhookPayload, db: Session = Depends(get_db_session) ): """Create a new Jira analysis record""" try: db_record = create_analysis_record(db, payload) return JSONResponse( status_code=201, content={"message": "Record created successfully", "record_id": db_record.id} ) except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to create record: {str(e)}") @router.post("/test-llm") async def test_llm_endpoint(db: Session = Depends(get_db_session)): """Test endpoint for LLM integration""" try: from llm.chains import llm test_prompt = "What is 1 + 1? Respond only with the number." response = llm.invoke(test_prompt) return { "status": "success", "message": "LLM integration test successful", "response": str(response) } except Exception as e: return JSONResponse( status_code=500, content={ "status": "error", "message": f"LLM test failed: {str(e)}" } ) @router.delete("/request") async def delete_analysis_records_endpoint(db: Session = Depends(get_db_session)): """Delete analysis records""" try: deleted_count = delete_all_analysis_records(db) return JSONResponse( status_code=200, content={"message": f"Successfully deleted {deleted_count} records", "deleted_count": deleted_count} ) except Exception as e: return JSONResponse( status_code=500, content={"error": str(e)}) @router.get("/request/{record_id}") async def get_analysis_record_endpoint(record_id: int, db: Session = Depends(get_db_session)): """Get specific analysis record by ID""" record = get_analysis_by_id(db, record_id) if not record: raise HTTPException(status_code=404, detail="Analysis record not found") return JiraAnalysisResponse.model_validate(record) @router.get("/queue/pending") async def get_pending_queue_records_endpoint(db: Session = Depends(get_db_session)): """Get all pending or retrying analysis records.""" try: records = get_pending_analysis_records(db) # Convert records to serializable format serialized_records = [] for record in records: record_dict = JiraAnalysisResponse.model_validate(record).model_dump() # Convert datetime fields to ISO format record_dict["created_at"] = record_dict["created_at"].isoformat() if record_dict["created_at"] else None record_dict["updated_at"] = record_dict["updated_at"].isoformat() if record_dict["updated_at"] else None serialized_records.append(record_dict) return JSONResponse( status_code=200, content={"data": serialized_records} ) except Exception as e: raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") @router.post("/queue/{record_id}/retry", status_code=200) async def retry_analysis_record_endpoint(record_id: int, db: Session = Depends(get_db_session)): """Manually trigger a retry for a failed, processing or validation_failed analysis record.""" db_record = get_analysis_by_id(db, record_id) if not db_record: raise HTTPException(status_code=404, detail="Analysis record not found") if db_record.status not in ["processing", "failed", "validation_failed"]: raise HTTPException(status_code=400, detail=f"Record status is '{db_record.status}'. Only 'failed', 'processing' or 'validation_failed' records can be retried.") # Reset status to pending and clear error message for retry updated_record = update_record_status( db=db, record_id=record_id, status="pending", error_message=None, analysis_result=None, raw_response=None, next_retry_at=None # Reset retry time ) if not updated_record: raise HTTPException(status_code=500, detail="Failed to update record for retry.") return JSONResponse( status_code=200, content={"message": f"Record {record_id} marked for retry.", "record_id": updated_record.id} )