Files
ALwrity/backend/api/content_planning/api/routes/gap_analysis.py

177 lines
6.5 KiB
Python

"""
Gap Analysis Routes for Content Planning API
Extracted from the main content_planning.py file for better organization.
"""
from fastapi import APIRouter, HTTPException, Depends, status, Query
from sqlalchemy.orm import Session
from typing import Dict, Any, List, Optional
from datetime import datetime
from loguru import logger
import json
# Import auth middleware
from middleware.auth_middleware import get_current_user
# Import database service
from services.database import get_db_session, get_db
from services.content_planning_db import ContentPlanningDBService
# Import models
from ..models.requests import ContentGapAnalysisCreate, ContentGapAnalysisRequest
from ..models.responses import ContentGapAnalysisResponse, ContentGapAnalysisFullResponse
# Import utilities
from ...utils.error_handlers import ContentPlanningErrorHandler
from ...utils.response_builders import ResponseBuilder
from ...utils.constants import ERROR_MESSAGES, SUCCESS_MESSAGES
# Import services
from ...services.gap_analysis_service import GapAnalysisService
# Initialize services
gap_analysis_service = GapAnalysisService()
# Create router
router = APIRouter(prefix="/gap-analysis", tags=["gap-analysis"])
@router.post("/", response_model=ContentGapAnalysisResponse)
async def create_content_gap_analysis(
analysis: ContentGapAnalysisCreate,
db: Session = Depends(get_db)
):
"""Create a new content gap analysis."""
try:
logger.info(f"Creating content gap analysis for: {analysis.website_url}")
analysis_data = analysis.dict()
created_analysis = await gap_analysis_service.create_gap_analysis(analysis_data, db)
return ContentGapAnalysisResponse(**created_analysis)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error creating content gap analysis: {str(e)}")
raise ContentPlanningErrorHandler.handle_general_error(e, "create_content_gap_analysis")
@router.get("/", response_model=Dict[str, Any])
async def get_content_gap_analyses(
strategy_id: Optional[int] = Query(None, description="Strategy ID"),
force_refresh: bool = Query(False, description="Force refresh gap analysis"),
current_user: Dict[str, Any] = Depends(get_current_user)
):
"""Get content gap analysis with real AI insights - Database first approach."""
try:
user_id = str(current_user.get('id'))
logger.info(f"🚀 Starting content gap analysis for user: {user_id}, strategy: {strategy_id}, force_refresh: {force_refresh}")
result = await gap_analysis_service.get_gap_analyses(user_id, strategy_id, force_refresh)
return result
except Exception as e:
logger.error(f"❌ Error generating content gap analysis: {str(e)}")
raise HTTPException(status_code=500, detail=f"Error generating content gap analysis: {str(e)}")
@router.get("/{analysis_id}", response_model=ContentGapAnalysisResponse)
async def get_content_gap_analysis(
analysis_id: int,
db: Session = Depends(get_db)
):
"""Get a specific content gap analysis by ID."""
try:
logger.info(f"Fetching content gap analysis: {analysis_id}")
analysis = await gap_analysis_service.get_gap_analysis_by_id(analysis_id, db)
return ContentGapAnalysisResponse(**analysis)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error getting content gap analysis: {str(e)}")
raise ContentPlanningErrorHandler.handle_general_error(e, "get_content_gap_analysis")
@router.post("/analyze", response_model=ContentGapAnalysisFullResponse)
async def analyze_content_gaps(
request: ContentGapAnalysisRequest,
current_user: Dict[str, Any] = Depends(get_current_user)
):
"""
Analyze content gaps between your website and competitors.
"""
try:
logger.info(f"Starting content gap analysis for: {request.website_url}")
user_id = str(current_user.get('id'))
request_data = request.dict()
result = await gap_analysis_service.analyze_content_gaps(request_data, user_id)
return ContentGapAnalysisFullResponse(**result)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error analyzing content gaps: {str(e)}")
raise ContentPlanningErrorHandler.handle_general_error(e, "analyze_content_gaps")
@router.get("/user/{user_id}/analyses")
async def get_user_gap_analyses(
user_id: int,
db: Session = Depends(get_db)
):
"""Get all gap analyses for a specific user."""
try:
logger.info(f"Fetching gap analyses for user: {user_id}")
analyses = await gap_analysis_service.get_user_gap_analyses(user_id, db)
return {
"user_id": user_id,
"analyses": analyses,
"total_count": len(analyses)
}
except Exception as e:
logger.error(f"Error getting user gap analyses: {str(e)}")
raise ContentPlanningErrorHandler.handle_general_error(e, "get_user_gap_analyses")
@router.put("/{analysis_id}", response_model=ContentGapAnalysisResponse)
async def update_content_gap_analysis(
analysis_id: int,
update_data: Dict[str, Any],
db: Session = Depends(get_db)
):
"""Update a content gap analysis."""
try:
logger.info(f"Updating content gap analysis: {analysis_id}")
updated_analysis = await gap_analysis_service.update_gap_analysis(analysis_id, update_data, db)
return ContentGapAnalysisResponse(**updated_analysis)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error updating content gap analysis: {str(e)}")
raise ContentPlanningErrorHandler.handle_general_error(e, "update_content_gap_analysis")
@router.delete("/{analysis_id}")
async def delete_content_gap_analysis(
analysis_id: int,
db: Session = Depends(get_db)
):
"""Delete a content gap analysis."""
try:
logger.info(f"Deleting content gap analysis: {analysis_id}")
deleted = await gap_analysis_service.delete_gap_analysis(analysis_id, db)
if deleted:
return {"message": f"Content gap analysis {analysis_id} deleted successfully"}
else:
raise ContentPlanningErrorHandler.handle_not_found_error("Content gap analysis", analysis_id)
except HTTPException:
raise
except Exception as e:
logger.error(f"Error deleting content gap analysis: {str(e)}")
raise ContentPlanningErrorHandler.handle_general_error(e, "delete_content_gap_analysis")