from datetime import datetime, timedelta from typing import Optional from db.db import get_db from db.models import InvestorInsightCache, InvestorTable, ProjectTable from fastapi import APIRouter, Depends, HTTPException from schemas.insight_schema import InsightResponse from services.compatibility_score import ( calculate_project_investor_compatibility, generate_compatibility_explanation, ) from services.insight import QueryProcessor from sqlalchemy.orm import Session router = APIRouter() @router.get( "/insights/{investor_id}", response_model=InsightResponse, tags=["Insights"] ) async def get_insights( investor_id: int, project_id: Optional[int] = None, db: Session = Depends(get_db) ): """ Get investor insights including investment pattern analysis, market position, and optionally compatibility score with a project. Args: investor_id: The ID of the investor to analyze project_id: Optional project ID to calculate compatibility score Returns: InsightResponse with investment_pattern_analysis, market_position, and compatibility_score (if project_id provided) """ # Get investor from database investor = db.query(InvestorTable).filter(InvestorTable.id == investor_id).first() if not investor: raise HTTPException( status_code=404, detail=f"Investor with id {investor_id} not found" ) # Check if we have cached insights cached_insights = ( db.query(InvestorInsightCache) .filter(InvestorInsightCache.investor_id == investor_id) .first() ) # Determine if cache needs refresh (older than 1 month) needs_refresh = True if cached_insights: # Calculate if cache is older than 1 month cache_age = ( datetime.now(cached_insights.last_refreshed.tzinfo) - cached_insights.last_refreshed ) needs_refresh = cache_age > timedelta(days=30) # Fetch new insights if needed if needs_refresh: # Initialize the query processor for insights query_processor = QueryProcessor() # Get investment pattern analysis and market position using web search insights = await query_processor.get_investor_insights( investor_name=investor.name, investor_website=investor.website, investor_description=investor.description, investor_headquarters=investor.headquarters, investment_thesis=investor.investment_thesis, portfolio_highlights=investor.portfolio_highlights, ) # Update or create cache entry if cached_insights: # Update existing cache cached_insights.investment_pattern_analysis = insights[ "investment_pattern_analysis" ] cached_insights.market_position = insights["market_position"] cached_insights.last_refreshed = datetime.now( cached_insights.last_refreshed.tzinfo ) else: # Create new cache entry cached_insights = InvestorInsightCache( investor_id=investor_id, investment_pattern_analysis=insights["investment_pattern_analysis"], market_position=insights["market_position"], ) db.add(cached_insights) db.commit() db.refresh(cached_insights) # Calculate compatibility score if project_id is provided compatibility_score = None if project_id: project = db.query(ProjectTable).filter(ProjectTable.id == project_id).first() if not project: raise HTTPException( status_code=404, detail=f"Project with id {project_id} not found" ) # Calculate the compatibility score score = calculate_project_investor_compatibility( project, investor, use_funds=True ) # Generate detailed explanation compatibility_score = generate_compatibility_explanation( project, investor, score, use_funds=True ) else: compatibility_score = "Select a project to see compatibility analysis" return InsightResponse( investment_pattern_analysis=cached_insights.investment_pattern_analysis, market_position=cached_insights.market_position, compatibility_score=compatibility_score, )