""" Calendar Generator Service AI-powered service for generating comprehensive content calendars based on enterprise best practices. """ import json import time from datetime import datetime, timedelta from typing import Dict, Any, List, Optional from loguru import logger from services.content_gap_analyzer.ai_engine_service import AIEngineService from services.onboarding_data_service import OnboardingDataService from services.content_gap_analyzer.keyword_researcher import KeywordResearcher from services.content_gap_analyzer.competitor_analyzer import CompetitorAnalyzer from services.ai_analysis_db_service import AIAnalysisDBService from services.content_planning_db import ContentPlanningDBService from services.ai_service_manager import AIServiceManager class CalendarGeneratorService: """AI-powered content calendar generator for SMEs.""" def __init__(self): self.ai_engine = AIEngineService() self.onboarding_service = OnboardingDataService() self.keyword_researcher = KeywordResearcher() self.competitor_analyzer = CompetitorAnalyzer() self.ai_analysis_db_service = AIAnalysisDBService() # Initialize content planning db service as None - will be set when needed self.content_planning_db_service = None # Enterprise content calendar templates self.content_pillars = { "technology": ["Educational Content", "Thought Leadership", "Product Updates", "Industry Insights", "Team Culture"], "healthcare": ["Patient Education", "Medical Insights", "Health Tips", "Industry News", "Expert Opinions"], "finance": ["Financial Education", "Market Analysis", "Investment Tips", "Regulatory Updates", "Success Stories"], "education": ["Learning Resources", "Teaching Tips", "Student Success", "Industry Trends", "Innovation"], "retail": ["Product Showcases", "Shopping Tips", "Customer Stories", "Trend Analysis", "Behind the Scenes"], "manufacturing": ["Industry Insights", "Process Improvements", "Technology Updates", "Case Studies", "Team Spotlights"] } self.platform_strategies = { "website": { "content_types": ["blog_posts", "case_studies", "whitepapers", "product_pages"], "frequency": "2-3 per week", "optimal_length": "1500+ words", "tone": "professional, educational" }, "linkedin": { "content_types": ["industry_insights", "professional_tips", "company_updates", "employee_spotlights"], "frequency": "daily", "optimal_length": "100-300 words", "tone": "professional, thought leadership" }, "instagram": { "content_types": ["behind_scenes", "product_demos", "team_culture", "infographics"], "frequency": "daily", "optimal_length": "visual focus", "tone": "casual, engaging" }, "youtube": { "content_types": ["tutorial_videos", "product_demos", "customer_testimonials", "industry_interviews"], "frequency": "weekly", "optimal_length": "5-15 minutes", "tone": "educational, conversational" }, "twitter": { "content_types": ["industry_news", "quick_tips", "event_announcements", "community_engagement"], "frequency": "3-5 per day", "optimal_length": "280 characters", "tone": "informative, conversational" } } self.content_mix = { "educational": 0.40, "thought_leadership": 0.30, "engagement": 0.20, "promotional": 0.10 } async def generate_comprehensive_calendar( self, user_id: int, strategy_id: Optional[int] = None, calendar_type: str = "monthly", industry: Optional[str] = None, business_size: str = "sme" ) -> Dict[str, Any]: """ Generate a comprehensive content calendar using AI with database-driven insights. Args: user_id: User ID strategy_id: Content strategy ID calendar_type: Type of calendar (monthly, weekly, custom) industry: Business industry business_size: Business size (startup, sme, enterprise) Returns: Comprehensive calendar with AI insights and recommendations """ try: logger.info(f"🚀 Starting comprehensive calendar generation for user {user_id}") start_time = time.time() # Get comprehensive user data from database user_data = await self._get_comprehensive_user_data(user_id, strategy_id) industry = industry or user_data.get("industry", "technology") # Generate calendar components using database insights calendar_data = { "user_id": user_id, "strategy_id": strategy_id, "calendar_type": calendar_type, "industry": industry, "business_size": business_size, "generated_at": datetime.utcnow().isoformat(), "content_pillars": self._get_content_pillars(industry), "platform_strategies": self.platform_strategies, "content_mix": self.content_mix, "daily_schedule": await self._generate_daily_schedule_with_db_data(calendar_type, industry, user_data), "weekly_themes": await self._generate_weekly_themes_with_db_data(calendar_type, industry, user_data), "content_recommendations": await self._generate_content_recommendations_with_db_data(user_data, industry), "optimal_timing": await self._generate_optimal_timing_with_db_data(industry, user_data), "performance_predictions": await self._generate_performance_predictions_with_db_data(industry, user_data), "trending_topics": await self._get_trending_topics_from_db(industry, user_data), "repurposing_opportunities": await self._generate_repurposing_opportunities_with_db_data(user_data), "ai_insights": await self._generate_ai_insights_with_db_data(user_data, industry), "competitor_analysis": await self._analyze_competitors_with_db_data(user_data, industry), "gap_analysis_insights": user_data.get("gap_analysis", {}), "strategy_insights": user_data.get("strategy_data", {}), "onboarding_insights": user_data.get("onboarding_data", {}) } processing_time = time.time() - start_time calendar_data["processing_time"] = processing_time calendar_data["ai_confidence"] = 0.90 # Higher confidence with database-driven insights logger.info(f"✅ Calendar generation completed in {processing_time:.2f}s") return calendar_data except Exception as e: logger.error(f"❌ Error generating calendar: {str(e)}") raise async def generate_ai_powered_calendar( self, user_id: int, strategy_id: Optional[int] = None, calendar_type: str = "monthly", industry: Optional[str] = None, business_size: str = "sme" ) -> Dict[str, Any]: """ Generate an AI-powered content calendar using comprehensive database insights. This is the enhanced version with full data transparency and advanced features. """ try: logger.info(f"Generating AI-powered calendar for user {user_id}") start_time = time.time() # Get comprehensive user data user_data = await self._get_comprehensive_user_data(user_id, strategy_id) # Generate calendar using AI insights calendar_data = await self._generate_calendar_with_advanced_ai( user_data, calendar_type, industry, business_size ) # Add performance predictions performance_predictions = await self._predict_calendar_performance( calendar_data, user_data ) # Add trending topics integration trending_topics = await self._get_trending_topics_for_calendar( user_data, industry ) # Add content repurposing opportunities repurposing_opportunities = await self._identify_repurposing_opportunities( calendar_data, user_data ) processing_time = time.time() - start_time return { "user_id": user_id, "strategy_id": strategy_id, "calendar_type": calendar_type, "industry": industry or user_data.get("industry", "technology"), "business_size": business_size, "generated_at": datetime.now().isoformat(), "content_pillars": calendar_data.get("content_pillars", []), "platform_strategies": calendar_data.get("platform_strategies", {}), "content_mix": calendar_data.get("content_mix", {}), "daily_schedule": calendar_data.get("daily_schedule", []), "weekly_themes": calendar_data.get("weekly_themes", []), "content_recommendations": calendar_data.get("content_recommendations", []), "optimal_timing": calendar_data.get("optimal_timing", {}), "performance_predictions": performance_predictions, "trending_topics": trending_topics, "repurposing_opportunities": repurposing_opportunities, "ai_insights": calendar_data.get("ai_insights", []), "competitor_analysis": user_data.get("competitor_analysis", {}), "gap_analysis_insights": user_data.get("gap_analysis", {}), "strategy_insights": user_data.get("strategy_data", {}), "onboarding_insights": user_data.get("onboarding_data", {}), "processing_time": processing_time, "ai_confidence": 0.95 } except Exception as e: logger.error(f"Error generating AI-powered calendar: {str(e)}") raise async def _get_comprehensive_user_data(self, user_id: int, strategy_id: Optional[int]) -> Dict[str, Any]: """Get comprehensive user data from all database sources.""" try: logger.info(f"Getting comprehensive user data for user {user_id}") # Get onboarding data (not async) onboarding_data = self.onboarding_service.get_personalized_ai_inputs(user_id) # Get AI analysis results from the working endpoint try: from services.ai_analytics_service import AIAnalyticsService ai_analytics = AIAnalyticsService() ai_analysis_results = await ai_analytics.generate_strategic_intelligence(strategy_id or 1) except Exception as e: logger.warning(f"Could not get AI analysis results: {str(e)}") ai_analysis_results = {"insights": [], "recommendations": []} # Get gap analysis data from the working endpoint try: from services.content_gap_analyzer.ai_engine_service import AIEngineService ai_engine = AIEngineService() gap_analysis_data = await ai_engine.generate_content_recommendations(onboarding_data) except Exception as e: logger.warning(f"Could not get gap analysis data: {str(e)}") gap_analysis_data = [] # Get content strategy data strategy_data = {} if strategy_id: strategy_data = await self._get_strategy_data(strategy_id) # Get content recommendations recommendations_data = await self._get_recommendations_data(user_id, strategy_id) # Get performance metrics performance_data = await self._get_performance_data(user_id, strategy_id) # Build comprehensive response comprehensive_data = { "user_id": user_id, "onboarding_data": onboarding_data, "ai_analysis_results": ai_analysis_results, "gap_analysis": { "content_gaps": gap_analysis_data if isinstance(gap_analysis_data, list) else [], "keyword_opportunities": onboarding_data.get("keyword_analysis", {}).get("high_value_keywords", []), "competitor_insights": onboarding_data.get("competitor_analysis", {}).get("top_performers", []), "recommendations": gap_analysis_data if isinstance(gap_analysis_data, list) else [], "opportunities": onboarding_data.get("gap_analysis", {}).get("content_opportunities", []) }, "strategy_data": strategy_data, "recommendations_data": recommendations_data, "performance_data": performance_data, "industry": onboarding_data.get("website_analysis", {}).get("industry_focus", "technology"), "target_audience": onboarding_data.get("website_analysis", {}).get("target_audience", []), "business_goals": ["Increase brand awareness", "Generate leads", "Establish thought leadership"], "website_analysis": onboarding_data.get("website_analysis", {}), "competitor_analysis": onboarding_data.get("competitor_analysis", {}), "keyword_analysis": onboarding_data.get("keyword_analysis", {}) } logger.info(f"✅ Successfully retrieved comprehensive user data for user {user_id}") return comprehensive_data except Exception as e: logger.error(f"Error getting comprehensive user data: {str(e)}") return {"user_id": user_id, "industry": "technology"} async def _get_gap_analysis_data(self, user_id: int) -> Dict[str, Any]: """Get gap analysis data from database.""" try: # Check if database service is available if self.content_planning_db_service is None: logger.warning("ContentPlanningDBService not available, returning empty gap analysis data") return {} # Get latest gap analysis results using the correct method name gap_analyses = await self.content_planning_db_service.get_user_content_gap_analyses(user_id) if gap_analyses: latest_analysis = gap_analyses[0] # Get most recent return { "content_gaps": latest_analysis.get("analysis_results", {}).get("content_gaps", []), "keyword_opportunities": latest_analysis.get("analysis_results", {}).get("keyword_opportunities", []), "competitor_insights": latest_analysis.get("analysis_results", {}).get("competitor_insights", []), "recommendations": latest_analysis.get("recommendations", []), "opportunities": latest_analysis.get("opportunities", []) } return {} except Exception as e: logger.error(f"Error getting gap analysis data: {str(e)}") return {} async def _get_strategy_data(self, strategy_id: int) -> Dict[str, Any]: """Get content strategy data from database.""" try: # Check if database service is available if self.content_planning_db_service is None: logger.warning("ContentPlanningDBService not available, returning empty strategy data") return {} strategy = await self.content_planning_db_service.get_content_strategy(strategy_id) if strategy: return { "content_pillars": strategy.get("content_pillars", []), "target_audience": strategy.get("target_audience", {}), "ai_recommendations": strategy.get("ai_recommendations", {}), "industry": strategy.get("industry", ""), "business_goals": strategy.get("business_goals", []) } return {} except Exception as e: logger.error(f"Error getting strategy data: {str(e)}") return {} async def _get_recommendations_data(self, user_id: int, strategy_id: Optional[int]) -> List[Dict[str, Any]]: """Get content recommendations from database.""" try: # Check if database service is available if self.content_planning_db_service is None: logger.warning("ContentPlanningDBService not available, returning empty recommendations data") return [] recommendations = await self.content_planning_db_service.get_user_content_recommendations(user_id) return recommendations or [] except Exception as e: logger.error(f"Error getting recommendations data: {str(e)}") return [] async def _get_performance_data(self, user_id: int, strategy_id: Optional[int]) -> Dict[str, Any]: """Get performance data from database.""" try: # Check if database service is available if self.content_planning_db_service is None: logger.warning("ContentPlanningDBService not available, returning empty performance data") return {} # For now, return empty performance data since the method might not exist # This can be enhanced later when performance tracking is implemented return {} except Exception as e: logger.error(f"Error getting performance data: {str(e)}") return {} def _get_content_pillars(self, industry: str) -> List[str]: """Get content pillars for the industry.""" return self.content_pillars.get(industry, self.content_pillars["technology"]) async def _generate_daily_schedule_with_db_data(self, calendar_type: str, industry: str, user_data: Dict[str, Any]) -> List[Dict[str, Any]]: """Generate daily content schedule using database insights.""" try: # Extract relevant data from user_data gap_analysis = user_data.get("gap_analysis", {}) strategy_data = user_data.get("strategy_data", {}) onboarding_data = user_data.get("onboarding_data", {}) recommendations = user_data.get("recommendations_data", []) prompt = f""" Create a comprehensive daily content schedule for a {industry} business using the following specific data: GAP ANALYSIS INSIGHTS: - Content Gaps: {gap_analysis.get('content_gaps', [])} - Keyword Opportunities: {gap_analysis.get('keyword_opportunities', [])} - Competitor Insights: {gap_analysis.get('competitor_insights', [])} - Recommendations: {gap_analysis.get('recommendations', [])} STRATEGY DATA: - Content Pillars: {strategy_data.get('content_pillars', [])} - Target Audience: {strategy_data.get('target_audience', {})} - AI Recommendations: {strategy_data.get('ai_recommendations', {})} ONBOARDING DATA: - Website Analysis: {onboarding_data.get('website_analysis', {})} - Competitor Analysis: {onboarding_data.get('competitor_analysis', {})} - Keyword Analysis: {onboarding_data.get('keyword_analysis', {})} EXISTING RECOMMENDATIONS: - Content Recommendations: {recommendations} Requirements: - Generate {calendar_type} schedule - Address specific content gaps identified - Incorporate keyword opportunities - Use competitor insights for differentiation - Align with existing content pillars - Consider target audience preferences - Balance educational, thought leadership, engagement, and promotional content Return a structured schedule that specifically addresses the identified gaps and opportunities. """ response = await self.ai_engine.generate_structured_response( prompt=prompt, schema={ "type": "object", "properties": { "daily_schedule": { "type": "array", "items": { "type": "object", "properties": { "day": {"type": "string"}, "theme": {"type": "string"}, "content_types": {"type": "array", "items": {"type": "string"}}, "platforms": {"type": "array", "items": {"type": "string"}}, "optimal_times": {"type": "array", "items": {"type": "string"}}, "content_mix": {"type": "object"}, "gap_addresses": {"type": "array", "items": {"type": "string"}}, "keyword_focus": {"type": "array", "items": {"type": "string"}}, "competitor_differentiation": {"type": "string"} } } } } } ) return response.get("daily_schedule", []) except Exception as e: logger.error(f"Error generating daily schedule with DB data: {str(e)}") return self._get_default_daily_schedule(calendar_type) async def _generate_weekly_themes_with_db_data(self, calendar_type: str, industry: str, user_data: Dict[str, Any]) -> List[Dict[str, Any]]: """Generate weekly content themes using database insights.""" try: gap_analysis = user_data.get("gap_analysis", {}) strategy_data = user_data.get("strategy_data", {}) onboarding_data = user_data.get("onboarding_data", {}) prompt = f""" Create weekly content themes for a {industry} business using specific database insights: CONTENT GAPS TO ADDRESS: - Identified Gaps: {gap_analysis.get('content_gaps', [])} - Opportunities: {gap_analysis.get('opportunities', [])} STRATEGY FOUNDATION: - Content Pillars: {strategy_data.get('content_pillars', [])} - Target Audience: {strategy_data.get('target_audience', {})} COMPETITOR INSIGHTS: - Competitor Analysis: {onboarding_data.get('competitor_analysis', {})} - Industry Position: {onboarding_data.get('website_analysis', {}).get('industry_focus', '')} Requirements: - Generate {calendar_type} themes that address specific gaps - Align with existing content pillars - Incorporate competitor insights for differentiation - Focus on identified opportunities - Consider seasonal and trending topics - Balance different content types based on audience preferences Return structured weekly themes that specifically address the identified gaps and opportunities. """ response = await self.ai_engine.generate_structured_response( prompt=prompt, schema={ "type": "object", "properties": { "weekly_themes": { "type": "array", "items": { "type": "object", "properties": { "week": {"type": "string"}, "theme": {"type": "string"}, "focus_areas": {"type": "array", "items": {"type": "string"}}, "trending_topics": {"type": "array", "items": {"type": "string"}}, "content_types": {"type": "array", "items": {"type": "string"}}, "gap_addresses": {"type": "array", "items": {"type": "string"}}, "competitor_differentiation": {"type": "string"} } } } } } ) return response.get("weekly_themes", []) except Exception as e: logger.error(f"Error generating weekly themes with DB data: {str(e)}") return self._get_default_weekly_themes(calendar_type) async def _generate_content_recommendations_with_db_data(self, user_data: Dict[str, Any], industry: str) -> List[Dict[str, Any]]: """Generate specific content recommendations using database insights.""" try: gap_analysis = user_data.get("gap_analysis", {}) strategy_data = user_data.get("strategy_data", {}) onboarding_data = user_data.get("onboarding_data", {}) existing_recommendations = user_data.get("recommendations_data", []) prompt = f""" Generate specific content recommendations for a {industry} business using comprehensive database insights: CONTENT GAPS TO FILL: - Identified Gaps: {gap_analysis.get('content_gaps', [])} - Keyword Opportunities: {gap_analysis.get('keyword_opportunities', [])} - Competitor Insights: {gap_analysis.get('competitor_insights', [])} STRATEGY CONTEXT: - Content Pillars: {strategy_data.get('content_pillars', [])} - Target Audience: {strategy_data.get('target_audience', {})} - AI Recommendations: {strategy_data.get('ai_recommendations', {})} AUDIENCE INSIGHTS: - Website Analysis: {onboarding_data.get('website_analysis', {})} - Target Demographics: {onboarding_data.get('target_audience', {})} - Content Preferences: {onboarding_data.get('keyword_analysis', {}).get('content_topics', [])} EXISTING RECOMMENDATIONS: - Current Recommendations: {existing_recommendations} Requirements: - Create specific content ideas that address identified gaps - Incorporate keyword opportunities - Use competitor insights for differentiation - Align with content pillars and audience preferences - Predict performance based on existing data - Provide implementation suggestions Return structured recommendations that specifically address the database insights. """ response = await self.ai_engine.generate_structured_response( prompt=prompt, schema={ "type": "object", "properties": { "content_recommendations": { "type": "array", "items": { "type": "object", "properties": { "title": {"type": "string"}, "description": {"type": "string"}, "content_type": {"type": "string"}, "platforms": {"type": "array", "items": {"type": "string"}}, "target_audience": {"type": "string"}, "estimated_performance": {"type": "object"}, "implementation_tips": {"type": "array", "items": {"type": "string"}}, "gap_addresses": {"type": "array", "items": {"type": "string"}}, "keyword_focus": {"type": "array", "items": {"type": "string"}}, "competitor_differentiation": {"type": "string"} } } } } } ) return response.get("content_recommendations", []) except Exception as e: logger.error(f"Error generating content recommendations with DB data: {str(e)}") return self._get_default_content_recommendations(industry) async def _generate_optimal_timing_with_db_data(self, industry: str, user_data: Dict[str, Any]) -> Dict[str, Any]: """Generate optimal posting times using database insights.""" try: performance_data = user_data.get("performance_data", {}) onboarding_data = user_data.get("onboarding_data", {}) prompt = f""" Generate optimal posting times for different social media platforms for a {industry} business using performance data: PERFORMANCE INSIGHTS: - Historical Performance: {performance_data} - Audience Demographics: {onboarding_data.get('target_audience', {})} - Website Analysis: {onboarding_data.get('website_analysis', {})} Requirements: - Consider industry-specific audience behavior - Use historical performance data to optimize timing - Include multiple platforms (LinkedIn, Instagram, Twitter, YouTube) - Provide specific time recommendations based on audience data - Include frequency guidelines - Consider timezone considerations Return structured timing recommendations based on actual performance data. """ response = await self.ai_engine.generate_structured_response( prompt=prompt, schema={ "type": "object", "properties": { "optimal_timing": { "type": "object", "properties": { "linkedin": {"type": "object"}, "instagram": {"type": "object"}, "twitter": {"type": "object"}, "youtube": {"type": "object"}, "website": {"type": "object"} } } } } ) return response.get("optimal_timing", {}) except Exception as e: logger.error(f"Error generating optimal timing with DB data: {str(e)}") return self._get_default_optimal_timing() async def _generate_performance_predictions_with_db_data(self, industry: str, user_data: Dict[str, Any]) -> Dict[str, Any]: """Generate performance predictions using database insights.""" try: performance_data = user_data.get("performance_data", {}) gap_analysis = user_data.get("gap_analysis", {}) onboarding_data = user_data.get("onboarding_data", {}) prompt = f""" Generate performance predictions for different content types in the {industry} industry using database insights: HISTORICAL PERFORMANCE: - Performance Data: {performance_data} - Engagement Patterns: {performance_data.get('engagement_patterns', {})} - Conversion Data: {performance_data.get('conversion_data', {})} CONTENT OPPORTUNITIES: - Content Gaps: {gap_analysis.get('content_gaps', [])} - Keyword Opportunities: {gap_analysis.get('keyword_opportunities', [])} AUDIENCE INSIGHTS: - Target Demographics: {onboarding_data.get('target_audience', {})} - Content Preferences: {onboarding_data.get('keyword_analysis', {}).get('content_topics', [])} Requirements: - Predict engagement rates based on historical data - Estimate reach and impressions using audience insights - Consider industry benchmarks - Include conversion predictions based on gap analysis - Provide ROI estimates using performance data Return structured predictions based on actual database insights. """ response = await self.ai_engine.generate_structured_response( prompt=prompt, schema={ "type": "object", "properties": { "performance_predictions": { "type": "object", "properties": { "content_types": {"type": "object"}, "platforms": {"type": "object"}, "industry_benchmarks": {"type": "object"}, "roi_estimates": {"type": "object"}, "gap_opportunities": {"type": "object"} } } } } ) return response.get("performance_predictions", {}) except Exception as e: logger.error(f"Error generating performance predictions with DB data: {str(e)}") return self._get_default_performance_predictions() async def _get_trending_topics_from_db(self, industry: str, user_data: Dict[str, Any]) -> List[Dict[str, Any]]: """Get trending topics using database insights.""" try: gap_analysis = user_data.get("gap_analysis", {}) onboarding_data = user_data.get("onboarding_data", {}) # Use keyword researcher with database insights keywords = [industry, "trending", "latest"] if gap_analysis.get('keyword_opportunities'): keywords.extend(gap_analysis['keyword_opportunities'][:5]) trending_data = await self.keyword_researcher.analyze_keywords( keywords=keywords, analysis_type="trend_analysis" ) # Enhance with database insights enhanced_trends = trending_data.get("trending_topics", []) for trend in enhanced_trends: trend["gap_relevance"] = self._assess_gap_relevance(trend, gap_analysis) trend["audience_alignment"] = self._assess_audience_alignment(trend, onboarding_data) return enhanced_trends except Exception as e: logger.error(f"Error getting trending topics from DB: {str(e)}") return [] async def _generate_repurposing_opportunities_with_db_data(self, user_data: Dict[str, Any]) -> List[Dict[str, Any]]: """Generate content repurposing opportunities using database insights.""" try: gap_analysis = user_data.get("gap_analysis", {}) strategy_data = user_data.get("strategy_data", {}) recommendations = user_data.get("recommendations_data", []) prompt = f""" Generate content repurposing opportunities using database insights: CONTENT GAPS: - Identified Gaps: {gap_analysis.get('content_gaps', [])} - Opportunities: {gap_analysis.get('opportunities', [])} EXISTING CONTENT: - Content Pillars: {strategy_data.get('content_pillars', [])} - Recommendations: {recommendations} Requirements: - Identify how to adapt existing content to fill gaps - Suggest content transformations based on opportunities - Include platform-specific adaptations - Consider audience preferences per platform - Focus on addressing identified content gaps Return structured repurposing opportunities that address specific database insights. """ response = await self.ai_engine.generate_structured_response( prompt=prompt, schema={ "type": "object", "properties": { "repurposing_opportunities": { "type": "array", "items": { "type": "object", "properties": { "original_content": {"type": "string"}, "platform_adaptations": {"type": "array", "items": {"type": "string"}}, "transformations": {"type": "array", "items": {"type": "string"}}, "implementation_tips": {"type": "array", "items": {"type": "string"}}, "gap_addresses": {"type": "array", "items": {"type": "string"}} } } } } } ) return response.get("repurposing_opportunities", []) except Exception as e: logger.error(f"Error generating repurposing opportunities with DB data: {str(e)}") return [] async def _generate_ai_insights_with_db_data(self, user_data: Dict[str, Any], industry: str) -> List[Dict[str, Any]]: """Generate AI insights using database insights.""" try: gap_analysis = user_data.get("gap_analysis", {}) strategy_data = user_data.get("strategy_data", {}) onboarding_data = user_data.get("onboarding_data", {}) performance_data = user_data.get("performance_data", {}) prompt = f""" Generate AI insights for content planning in the {industry} industry using comprehensive database insights: CONTENT GAPS: - Identified Gaps: {gap_analysis.get('content_gaps', [])} - Opportunities: {gap_analysis.get('opportunities', [])} STRATEGY CONTEXT: - Content Pillars: {strategy_data.get('content_pillars', [])} - Target Audience: {strategy_data.get('target_audience', {})} PERFORMANCE DATA: - Historical Performance: {performance_data} - Engagement Patterns: {performance_data.get('engagement_patterns', {})} AUDIENCE INSIGHTS: - Target Demographics: {onboarding_data.get('target_audience', {})} - Website Analysis: {onboarding_data.get('website_analysis', {})} Requirements: - Provide strategic insights based on gap analysis - Include content optimization tips using performance data - Suggest audience engagement strategies - Consider industry trends and competitor analysis - Include performance optimization insights Return structured insights that specifically address the database insights. """ response = await self.ai_engine.generate_structured_response( prompt=prompt, schema={ "type": "object", "properties": { "ai_insights": { "type": "array", "items": { "type": "object", "properties": { "insight_type": {"type": "string"}, "title": {"type": "string"}, "description": {"type": "string"}, "recommendations": {"type": "array", "items": {"type": "string"}}, "priority": {"type": "string"}, "data_source": {"type": "string"}, "gap_addresses": {"type": "array", "items": {"type": "string"}} } } } } } ) return response.get("ai_insights", []) except Exception as e: logger.error(f"Error generating AI insights with DB data: {str(e)}") return [] async def _analyze_competitors_with_db_data(self, user_data: Dict[str, Any], industry: str) -> Dict[str, Any]: """Analyze competitors using database insights.""" try: gap_analysis = user_data.get("gap_analysis", {}) onboarding_data = user_data.get("onboarding_data", {}) # Use competitor analyzer with database insights competitor_data = await self.competitor_analyzer.analyze_competitors( industry=industry, analysis_type="content_gaps", competitor_urls=onboarding_data.get('competitor_analysis', {}).get('top_performers', []) ) # Enhance with gap analysis insights enhanced_competitor_data = competitor_data or {} enhanced_competitor_data["gap_opportunities"] = gap_analysis.get("opportunities", []) enhanced_competitor_data["content_differentiation"] = gap_analysis.get("competitor_insights", []) return enhanced_competitor_data except Exception as e: logger.error(f"Error analyzing competitors with DB data: {str(e)}") return {} def _assess_gap_relevance(self, trend: Dict[str, Any], gap_analysis: Dict[str, Any]) -> str: """Assess how relevant a trending topic is to identified gaps.""" try: content_gaps = gap_analysis.get("content_gaps", []) trend_title = trend.get("keyword", "").lower() for gap in content_gaps: if any(word in trend_title for word in gap.lower().split()): return "high" return "medium" except Exception: return "low" def _assess_audience_alignment(self, trend: Dict[str, Any], onboarding_data: Dict[str, Any]) -> str: """Assess how well a trending topic aligns with target audience.""" try: target_audience = onboarding_data.get("target_audience", {}) trend_title = trend.get("keyword", "").lower() # Simple keyword matching - could be enhanced with more sophisticated analysis audience_keywords = ["professional", "business", "industry", "technology", "marketing"] if any(keyword in trend_title for keyword in audience_keywords): return "high" return "medium" except Exception: return "low" def _get_default_daily_schedule(self, calendar_type: str) -> List[Dict[str, Any]]: """Get default daily schedule if AI generation fails.""" return [ { "day": "Monday", "theme": "Educational Content", "content_types": ["blog_post", "how_to_guide"], "platforms": ["website", "linkedin"], "optimal_times": ["9:00 AM", "2:00 PM"], "content_mix": {"educational": 0.6, "thought_leadership": 0.4} }, { "day": "Tuesday", "theme": "Industry Insights", "content_types": ["industry_analysis", "trend_report"], "platforms": ["linkedin", "twitter"], "optimal_times": ["10:00 AM", "3:00 PM"], "content_mix": {"thought_leadership": 0.7, "educational": 0.3} } ] def _get_default_weekly_themes(self, calendar_type: str) -> List[Dict[str, Any]]: """Get default weekly themes if AI generation fails.""" return [ { "week": "Week 1", "theme": "Industry Fundamentals", "focus_areas": ["Educational content", "Basic concepts"], "trending_topics": ["Industry trends", "Best practices"], "content_types": ["blog_posts", "infographics"] } ] def _get_default_content_recommendations(self, industry: str) -> List[Dict[str, Any]]: """Get default content recommendations if AI generation fails.""" return [ { "title": f"Complete Guide to {industry.title()} Best Practices", "description": f"A comprehensive guide covering essential {industry} practices and strategies.", "content_type": "blog_post", "platforms": ["website", "linkedin"], "target_audience": "Industry professionals", "estimated_performance": {"engagement_rate": 0.08, "reach": 5000}, "implementation_tips": ["Use industry keywords", "Include expert quotes", "Add visual elements"] } ] def _get_default_optimal_timing(self) -> Dict[str, Any]: """Get default optimal timing if AI generation fails.""" return { "linkedin": {"optimal_times": ["9:00 AM", "2:00 PM"], "frequency": "daily"}, "instagram": {"optimal_times": ["12:00 PM", "7:00 PM"], "frequency": "daily"}, "twitter": {"optimal_times": ["8:00 AM", "12:00 PM", "5:00 PM"], "frequency": "3-5 per day"}, "youtube": {"optimal_times": ["2:00 PM", "7:00 PM"], "frequency": "weekly"}, "website": {"optimal_times": ["10:00 AM"], "frequency": "2-3 per week"} } def _get_default_performance_predictions(self) -> Dict[str, Any]: """Get default performance predictions if AI generation fails.""" return { "content_types": { "blog_posts": {"engagement_rate": 0.06, "reach": 3000}, "videos": {"engagement_rate": 0.12, "reach": 5000}, "infographics": {"engagement_rate": 0.15, "reach": 8000} }, "platforms": { "linkedin": {"engagement_rate": 0.08, "reach": 4000}, "instagram": {"engagement_rate": 0.10, "reach": 6000}, "twitter": {"engagement_rate": 0.05, "reach": 2000} } } async def _generate_calendar_with_advanced_ai( self, user_data: Dict[str, Any], calendar_type: str, industry: str, business_size: str ) -> Dict[str, Any]: """ Generate calendar using advanced AI with comprehensive database insights. """ try: # Extract key data points gap_analysis = user_data.get("gap_analysis", {}) ai_analysis = user_data.get("ai_analysis_results", {}) strategy_data = user_data.get("strategy_data", {}) # Generate content pillars based on gap analysis content_pillars = self._generate_content_pillars_from_gaps( gap_analysis, industry, business_size ) # Generate daily schedule addressing specific gaps daily_schedule = await self._generate_daily_schedule_addressing_gaps( calendar_type, gap_analysis, content_pillars, user_data ) # Generate weekly themes based on AI insights weekly_themes = await self._generate_weekly_themes_from_ai_insights( ai_analysis, content_pillars, calendar_type ) # Generate platform-specific strategies platform_strategies = self._generate_platform_strategies( industry, business_size, content_pillars ) # Generate optimal content mix content_mix = self._generate_optimal_content_mix( gap_analysis, ai_analysis, industry ) # Generate content recommendations content_recommendations = await self._generate_content_recommendations( gap_analysis, ai_analysis, content_pillars ) # Generate optimal timing optimal_timing = await self._generate_optimal_timing( user_data, industry, business_size ) # Generate AI insights ai_insights = await self._generate_calendar_ai_insights( gap_analysis, ai_analysis, content_pillars ) return { "content_pillars": content_pillars, "daily_schedule": daily_schedule, "weekly_themes": weekly_themes, "platform_strategies": platform_strategies, "content_mix": content_mix, "content_recommendations": content_recommendations, "optimal_timing": optimal_timing, "ai_insights": ai_insights } except Exception as e: logger.error(f"Error in advanced AI calendar generation: {str(e)}") raise def _generate_content_pillars_from_gaps( self, gap_analysis: Dict[str, Any], industry: str, business_size: str ) -> List[str]: """ Generate content pillars based on identified gaps and industry best practices. """ # Get industry-specific content pillars industry_pillars = self.content_pillars.get(industry, [ "Educational Content", "Thought Leadership", "Product Updates", "Industry Insights", "Team Culture" ]) # Add gap-specific pillars gap_pillars = [] if gap_analysis.get("content_gaps"): for gap in gap_analysis["content_gaps"][:3]: # Top 3 gaps gap_type = gap.get("type", "Content Creation") if gap_type not in gap_pillars: gap_pillars.append(gap_type) # Combine and prioritize all_pillars = industry_pillars + gap_pillars return list(dict.fromkeys(all_pillars))[:5] # Top 5 unique pillars async def _generate_daily_schedule_addressing_gaps( self, calendar_type: str, gap_analysis: Dict[str, Any], content_pillars: List[str], user_data: Dict[str, Any] ) -> List[Dict[str, Any]]: """ Generate daily schedule that specifically addresses identified content gaps. """ try: # Get AI service for advanced scheduling ai_manager = AIServiceManager() # Prepare prompt with gap analysis data gap_data = { "content_gaps": gap_analysis.get("content_gaps", []), "keyword_opportunities": gap_analysis.get("keyword_opportunities", []), "recommendations": gap_analysis.get("recommendations", []), "content_pillars": content_pillars, "calendar_type": calendar_type, "industry": user_data.get("industry", "technology"), "business_size": user_data.get("business_size", "sme") } # Generate schedule using AI schedule_prompt = f""" Create a comprehensive {calendar_type} content schedule that addresses specific content gaps: CONTENT GAPS TO ADDRESS: {gap_analysis.get('content_gaps', [])} KEYWORD OPPORTUNITIES: {gap_analysis.get('keyword_opportunities', [])} CONTENT PILLARS: {content_pillars} Requirements: 1. Address each identified content gap with specific content pieces 2. Incorporate keyword opportunities naturally 3. Balance content pillars throughout the schedule 4. Include specific titles, descriptions, and content types 5. Optimize for engagement and SEO 6. Consider industry best practices for {user_data.get('industry', 'technology')} Return a structured schedule with daily content pieces. """ ai_response = await ai_manager.generate_content_schedule(schedule_prompt) # Parse and structure the response if isinstance(ai_response, dict) and "schedule" in ai_response: return ai_response["schedule"] else: # Fallback to template-based generation return self._generate_fallback_schedule(calendar_type, content_pillars) except Exception as e: logger.error(f"Error generating daily schedule: {str(e)}") return self._generate_fallback_schedule(calendar_type, content_pillars) async def _generate_weekly_themes_from_ai_insights( self, ai_analysis: Dict[str, Any], content_pillars: List[str], calendar_type: str ) -> List[Dict[str, Any]]: """ Generate weekly themes based on AI analysis insights. """ try: themes = [] # Extract themes from AI analysis if ai_analysis.get("market_positioning"): positioning = ai_analysis["market_positioning"] themes.append({ "week": 1, "theme": f"Establishing {positioning.get('competitive_advantage', 'Content Quality')}", "focus": "Building competitive advantage through content", "content_types": ["thought_leadership", "case_studies", "expert_insights"] }) # Add gap-based themes if ai_analysis.get("gap_analysis"): gap_themes = self._extract_themes_from_gaps(ai_analysis["gap_analysis"]) themes.extend(gap_themes) # Add industry-specific themes industry_themes = self._get_industry_themes(ai_analysis.get("industry", "technology")) themes.extend(industry_themes) return themes[:4] # Return top 4 themes except Exception as e: logger.error(f"Error generating weekly themes: {str(e)}") return [] def _generate_platform_strategies( self, industry: str, business_size: str, content_pillars: List[str] ) -> Dict[str, Any]: """ Generate platform-specific content strategies. """ return { "website": { "content_types": ["blog_posts", "case_studies", "whitepapers", "product_pages"], "frequency": "2-3 per week", "optimal_length": "1500+ words", "tone": "professional, educational", "content_pillars": content_pillars }, "linkedin": { "content_types": ["industry_insights", "professional_tips", "company_updates", "employee_spotlights"], "frequency": "daily", "optimal_length": "100-300 words", "tone": "professional, thought leadership", "content_pillars": content_pillars }, "instagram": { "content_types": ["behind_scenes", "product_demos", "team_culture", "infographics"], "frequency": "daily", "optimal_length": "visual focus", "tone": "casual, engaging", "content_pillars": content_pillars }, "youtube": { "content_types": ["tutorial_videos", "product_demos", "customer_testimonials", "industry_interviews"], "frequency": "weekly", "optimal_length": "5-15 minutes", "tone": "educational, engaging", "content_pillars": content_pillars }, "twitter": { "content_types": ["industry_news", "quick_tips", "event_announcements", "community_engagement"], "frequency": "3-5 per day", "optimal_length": "280 characters", "tone": "informative, engaging", "content_pillars": content_pillars } } def _generate_optimal_content_mix( self, gap_analysis: Dict[str, Any], ai_analysis: Dict[str, Any], industry: str ) -> Dict[str, float]: """ Generate optimal content mix based on gap analysis and AI insights. """ # Base mix for industry base_mix = { "educational": 40, "thought_leadership": 30, "engagement": 20, "promotional": 10 } # Adjust based on gap analysis if gap_analysis.get("content_gaps"): educational_gaps = len([g for g in gap_analysis["content_gaps"] if "educational" in g.get("type", "").lower()]) thought_leadership_gaps = len([g for g in gap_analysis["content_gaps"] if "leadership" in g.get("type", "").lower()]) if educational_gaps > thought_leadership_gaps: base_mix["educational"] += 10 base_mix["thought_leadership"] -= 5 base_mix["engagement"] -= 5 elif thought_leadership_gaps > educational_gaps: base_mix["thought_leadership"] += 10 base_mix["educational"] -= 5 base_mix["engagement"] -= 5 return base_mix async def _predict_calendar_performance( self, calendar_data: Dict[str, Any], user_data: Dict[str, Any] ) -> Dict[str, Any]: """ Predict calendar performance based on AI analysis and historical data. """ try: # Extract performance indicators ai_analysis = user_data.get("ai_analysis_results", {}) strategic_scores = ai_analysis.get("strategic_scores", {}) # Calculate performance predictions base_traffic_growth = 25 base_engagement_rate = 15 base_conversion_rate = 10 # Adjust based on strategic scores if strategic_scores: market_positioning_score = strategic_scores.get("market_positioning_score", 0.7) content_strategy_score = strategic_scores.get("content_strategy_score", 0.7) # Adjust predictions based on scores traffic_growth = base_traffic_growth * (0.8 + market_positioning_score * 0.4) engagement_rate = base_engagement_rate * (0.8 + content_strategy_score * 0.4) conversion_rate = base_conversion_rate * (0.8 + (market_positioning_score + content_strategy_score) / 2 * 0.4) else: traffic_growth = base_traffic_growth engagement_rate = base_engagement_rate conversion_rate = base_conversion_rate return { "traffic_growth": round(traffic_growth, 1), "engagement_rate": round(engagement_rate, 1), "conversion_rate": round(conversion_rate, 1), "roi_prediction": round(traffic_growth * 0.3 + engagement_rate * 0.4 + conversion_rate * 0.3, 1), "confidence_score": 0.85 } except Exception as e: logger.error(f"Error predicting calendar performance: {str(e)}") return { "traffic_growth": 25, "engagement_rate": 15, "conversion_rate": 10, "roi_prediction": 15, "confidence_score": 0.7 } async def _get_trending_topics_for_calendar( self, user_data: Dict[str, Any], industry: str ) -> List[Dict[str, Any]]: """ Get trending topics relevant to the calendar and industry. """ try: # Extract keywords from gap analysis keywords = user_data.get("gap_analysis", {}).get("keyword_opportunities", []) # Generate trending topics based on keywords and industry trending_topics = [] for keyword in keywords[:5]: # Top 5 keywords trending_topics.append({ "topic": keyword, "relevance_score": 0.9, "trend_direction": "rising", "content_opportunities": [ f"Create content around {keyword}", f"Develop case studies featuring {keyword}", f"Create how-to guides for {keyword}" ] }) return trending_topics except Exception as e: logger.error(f"Error getting trending topics: {str(e)}") return [] async def _identify_repurposing_opportunities( self, calendar_data: Dict[str, Any], user_data: Dict[str, Any] ) -> List[Dict[str, Any]]: """ Identify content repurposing opportunities for the calendar. """ try: opportunities = [] # Identify opportunities from content pillars content_pillars = calendar_data.get("content_pillars", []) for pillar in content_pillars: opportunities.append({ "original_content": f"{pillar} content piece", "repurposing_options": [ f"Convert to {pillar} blog post", f"Create {pillar} social media series", f"Develop {pillar} video content", f"Design {pillar} infographic" ], "platforms": ["website", "linkedin", "instagram", "youtube"], "estimated_reach_increase": "40%" }) return opportunities except Exception as e: logger.error(f"Error identifying repurposing opportunities: {str(e)}") return [] def _generate_fallback_schedule( self, calendar_type: str, content_pillars: List[str] ) -> List[Dict[str, Any]]: """ Generate fallback schedule when AI generation fails. """ schedule = [] days = 30 if calendar_type == "monthly" else 7 if calendar_type == "weekly" else 90 for day in range(1, days + 1): pillar = content_pillars[day % len(content_pillars)] schedule.append({ "day": day, "title": f"{pillar} Content Day {day}", "description": f"Create engaging {pillar.lower()} content", "content_type": "blog_post", "platform": "website", "pillar": pillar, "priority": "medium" }) return schedule def _extract_themes_from_gaps(self, gap_analysis: Dict[str, Any]) -> List[Dict[str, Any]]: """ Extract weekly themes from gap analysis. """ themes = [] if gap_analysis.get("content_gaps"): for i, gap in enumerate(gap_analysis["content_gaps"][:3]): themes.append({ "week": i + 1, "theme": f"Addressing {gap.get('type', 'Content Gap')}", "focus": gap.get("title", "Content gap"), "content_types": ["blog_posts", "case_studies", "how_to_guides"] }) return themes def _get_industry_themes(self, industry: str) -> List[Dict[str, Any]]: """ Get industry-specific themes. """ industry_themes = { "technology": [ { "week": 4, "theme": "Technology Innovation", "focus": "Latest tech trends and innovations", "content_types": ["industry_insights", "product_updates", "expert_interviews"] } ], "healthcare": [ { "week": 4, "theme": "Healthcare Insights", "focus": "Patient care and medical innovations", "content_types": ["patient_education", "medical_insights", "health_tips"] } ], "finance": [ { "week": 4, "theme": "Financial Education", "focus": "Investment strategies and market analysis", "content_types": ["financial_education", "market_analysis", "investment_tips"] } ] } return industry_themes.get(industry, []) async def _generate_content_recommendations( self, gap_analysis: Dict[str, Any], ai_analysis: Dict[str, Any], content_pillars: List[str] ) -> List[Dict[str, Any]]: """ Generate content recommendations based on gap analysis and AI insights. """ recommendations = [] # Add recommendations from gap analysis if gap_analysis.get("recommendations"): for rec in gap_analysis["recommendations"][:5]: recommendations.append({ "title": rec.get("title", "Content recommendation"), "description": rec.get("description", "Based on gap analysis"), "priority": rec.get("priority", "medium"), "content_type": rec.get("type", "blog_post"), "estimated_impact": rec.get("estimated_impact", "Medium"), "implementation_time": rec.get("implementation_time", "2-4 weeks") }) # Add AI-generated recommendations if ai_analysis.get("recommendations"): for rec in ai_analysis["recommendations"][:3]: recommendations.append({ "title": rec.get("title", "AI recommendation"), "description": rec.get("description", "AI-generated insight"), "priority": "high", "content_type": "blog_post", "estimated_impact": "High", "implementation_time": "1-2 weeks" }) return recommendations async def _generate_optimal_timing( self, user_data: Dict[str, Any], industry: str, business_size: str ) -> Dict[str, Any]: """ Generate optimal timing recommendations based on industry and business size. """ # Industry-specific timing industry_timing = { "technology": { "best_days": ["Tuesday", "Wednesday", "Thursday"], "best_times": ["9:00 AM", "2:00 PM", "7:00 PM"], "optimal_frequency": "2-3 per week" }, "healthcare": { "best_days": ["Monday", "Wednesday", "Friday"], "best_times": ["8:00 AM", "12:00 PM", "6:00 PM"], "optimal_frequency": "1-2 per week" }, "finance": { "best_days": ["Tuesday", "Thursday", "Friday"], "best_times": ["9:00 AM", "1:00 PM", "5:00 PM"], "optimal_frequency": "2-3 per week" } } timing = industry_timing.get(industry, { "best_days": ["Monday", "Wednesday", "Friday"], "best_times": ["9:00 AM", "2:00 PM", "7:00 PM"], "optimal_frequency": "2-3 per week" }) # Adjust for business size if business_size == "startup": timing["optimal_frequency"] = "1-2 per week" elif business_size == "enterprise": timing["optimal_frequency"] = "3-4 per week" return timing async def _generate_calendar_ai_insights( self, gap_analysis: Dict[str, Any], ai_analysis: Dict[str, Any], content_pillars: List[str] ) -> List[Dict[str, Any]]: """ Generate AI insights specifically for the calendar. """ insights = [] # Add insights from gap analysis if gap_analysis.get("content_gaps"): insights.append({ "type": "opportunity", "title": "Content Gap Opportunity", "description": f"Address {len(gap_analysis['content_gaps'])} identified content gaps", "priority": "high", "impact": "High - Increased lead generation and brand authority" }) # Add insights from AI analysis if ai_analysis.get("market_positioning"): positioning = ai_analysis["market_positioning"] insights.append({ "type": "strategy", "title": "Market Positioning", "description": f"Focus on {positioning.get('competitive_advantage', 'content quality')}", "priority": "high", "impact": "High - Competitive differentiation" }) # Add content pillar insights insights.append({ "type": "strategy", "title": "Content Pillars", "description": f"Focus on {len(content_pillars)} core content pillars", "priority": "medium", "impact": "Medium - Consistent content strategy" }) return insights