"""
Competitive Intelligence Aggregator

Extends the base IntelligenceAggregator to process competitive content through
the existing analysis pipeline while adding competitive intelligence metadata.

Phase 3A: Core Extension Implementation
"""

import asyncio
import logging
from pathlib import Path
from datetime import datetime, timezone
from typing import Dict, List, Optional, Any, Set
from dataclasses import replace

from ..intelligence_aggregator import IntelligenceAggregator, AnalysisResult
from ..claude_analyzer import ClaudeHaikuAnalyzer
from ..engagement_analyzer import EngagementAnalyzer
from ..keyword_extractor import KeywordExtractor

from .models.competitive_result import (
    CompetitiveAnalysisResult, 
    MarketContext, 
    CompetitorCategory,
    CompetitorPriority,
    CompetitorMetrics,
    MarketPosition
)


class CompetitiveIntelligenceAggregator(IntelligenceAggregator):
    """
    Extends base aggregator to process competitive content with intelligence metadata.
    
    Reuses existing analysis pipeline (Claude, engagement, keywords) while adding
    competitive context, market positioning, and strategic analysis.
    """
    
    def __init__(
        self, 
        data_dir: Path,
        logs_dir: Optional[Path] = None,
        competitor_config: Optional[Dict[str, Dict[str, Any]]] = None
    ):
        """
        Initialize competitive intelligence aggregator.
        
        Args:
            data_dir: Base data directory
            logs_dir: Logging directory (optional)  
            competitor_config: Competitor configuration mapping
        """
        super().__init__(data_dir)
        
        self.logs_dir = logs_dir or data_dir / 'logs'
        self.logs_dir.mkdir(parents=True, exist_ok=True)
        
        self.logger = logging.getLogger(f"{__name__}.CompetitiveIntelligenceAggregator")
        
        # Competitive intelligence directories
        self.competitive_data_dir = data_dir / "competitive_intelligence"
        self.competitive_analysis_dir = data_dir / "competitive_analysis"
        self.competitive_data_dir.mkdir(parents=True, exist_ok=True)
        self.competitive_analysis_dir.mkdir(parents=True, exist_ok=True)
        
        # Competitor configuration
        self.competitor_config = competitor_config or self._get_default_competitor_config()
        
        # Analysis state tracking
        self.processed_competitive_content: Set[str] = set()
        
        self.logger.info(f"Initialized competitive intelligence aggregator for {len(self.competitor_config)} competitors")
    
    def _get_default_competitor_config(self) -> Dict[str, Dict[str, Any]]:
        """Get default competitor configuration"""
        return {
            'ac_service_tech': {
                'name': 'AC Service Tech',
                'platforms': ['youtube'],
                'category': CompetitorCategory.EDUCATIONAL_TECHNICAL,
                'priority': CompetitorPriority.HIGH,
                'target_audience': 'hvac_technicians',
                'content_focus': ['troubleshooting', 'repair_techniques', 'field_service'],
                'analysis_focus': ['content_gaps', 'technical_depth', 'engagement_patterns']
            },
            'refrigeration_mentor': {
                'name': 'Refrigeration Mentor',
                'platforms': ['youtube'],
                'category': CompetitorCategory.EDUCATIONAL_SPECIALIZED,
                'priority': CompetitorPriority.HIGH,
                'target_audience': 'refrigeration_specialists',
                'content_focus': ['refrigeration_systems', 'commercial_hvac', 'troubleshooting'],
                'analysis_focus': ['niche_content', 'commercial_focus', 'technical_authority']
            },
            'love2hvac': {
                'name': 'Love2HVAC',
                'platforms': ['youtube', 'instagram'],
                'category': CompetitorCategory.EDUCATIONAL_GENERAL,
                'priority': CompetitorPriority.MEDIUM,
                'target_audience': 'homeowners_beginners',
                'content_focus': ['basic_concepts', 'diy_guidance', 'system_explanations'],
                'analysis_focus': ['accessibility', 'explanation_style', 'beginner_content']
            },
            'hvac_tv': {
                'name': 'HVAC TV',
                'platforms': ['youtube'],
                'category': CompetitorCategory.INDUSTRY_NEWS,
                'priority': CompetitorPriority.MEDIUM,
                'target_audience': 'hvac_professionals',
                'content_focus': ['industry_trends', 'product_reviews', 'business_insights'],
                'analysis_focus': ['industry_coverage', 'product_insights', 'business_content']
            },
            'hvacrschool': {
                'name': 'HVACR School',
                'platforms': ['blog'],
                'category': CompetitorCategory.EDUCATIONAL_TECHNICAL,
                'priority': CompetitorPriority.HIGH,
                'target_audience': 'hvac_technicians',
                'content_focus': ['technical_education', 'system_design', 'troubleshooting'],
                'analysis_focus': ['technical_depth', 'educational_quality', 'comprehensive_coverage']
            },
            'hkia': {
                'name': 'HVAC Know It All',
                'platforms': ['youtube', 'blog', 'instagram'],
                'category': CompetitorCategory.EDUCATIONAL_TECHNICAL,
                'priority': CompetitorPriority.MEDIUM,
                'target_audience': 'hvac_professionals_homeowners',
                'content_focus': ['comprehensive_hvac', 'practical_guides', 'system_education'],
                'analysis_focus': ['content_breadth', 'multi_platform', 'audience_reach']
            }
        }
    
    async def process_competitive_content(
        self, 
        competitor_key: str,
        content_source: str = "all",  # backlog, incremental, or all
        limit: Optional[int] = None
    ) -> List[CompetitiveAnalysisResult]:
        """
        Process competitive content through analysis pipeline with competitive metadata.
        
        Args:
            competitor_key: Competitor identifier (e.g., 'ac_service_tech')
            content_source: Which content to process (backlog, incremental, all)
            limit: Maximum number of items to process
            
        Returns:
            List of competitive analysis results
        """
        # Handle 'all' case - process all competitors
        if competitor_key == "all":
            all_results = []
            for comp_key in self.competitor_config.keys():
                comp_results = await self.process_competitive_content(comp_key, content_source, limit)
                all_results.extend(comp_results)
            return all_results
            
        if competitor_key not in self.competitor_config:
            raise ValueError(f"Unknown competitor: {competitor_key}")
        
        competitor_info = self.competitor_config[competitor_key]
        self.logger.info(f"Processing competitive content for {competitor_info['name']} ({content_source})")
        
        # Find competitive content files
        competitive_files = self._find_competitive_content_files(competitor_key, content_source)
        if not competitive_files:
            self.logger.warning(f"No competitive content files found for {competitor_key}")
            return []
        
        # Process content through existing pipeline with limited concurrency
        results = []
        semaphore = asyncio.Semaphore(8)  # Limit concurrent processing to 8 items
        
        async def process_single_item(item, competitor_key, competitor_info):
            """Process a single content item with semaphore control"""
            async with semaphore:
                if item.get('id') in self.processed_competitive_content:
                    return None  # Skip already processed
                
                try:
                    # Run through existing analysis pipeline
                    analysis_result = await self._analyze_content_item(item)
                    
                    # Enrich with competitive intelligence metadata
                    competitive_result = self._enrich_with_competitive_metadata(
                        analysis_result, competitor_key, competitor_info
                    )
                    
                    self.processed_competitive_content.add(item.get('id', ''))
                    return competitive_result
                    
                except Exception as e:
                    self.logger.error(f"Error analyzing competitive content item {item.get('id', 'unknown')}: {e}")
                    return None
        
        # Collect all items from all files first
        all_items = []
        for file_path in competitive_files[:limit] if limit else competitive_files:
            try:
                # Parse competitive markdown content (now async)
                content_items = await self._parse_content_file(file_path)
                all_items.extend([(item, competitor_key, competitor_info) for item in content_items])
                
            except Exception as e:
                self.logger.error(f"Error processing competitive file {file_path}: {e}")
                continue
        
        # Process all items concurrently with semaphore control
        if all_items:
            tasks = [process_single_item(item, ck, ci) for item, ck, ci in all_items]
            concurrent_results = await asyncio.gather(*tasks, return_exceptions=True)
            
            # Filter out None results and exceptions
            results = [
                result for result in concurrent_results 
                if result is not None and not isinstance(result, Exception)
            ]
        
        self.logger.info(f"Processed {len(results)} competitive content items for {competitor_info['name']}")
        return results
    
    def _find_competitive_content_files(self, competitor_key: str, content_source: str) -> List[Path]:
        """Find competitive content markdown files"""
        competitor_dir = self.competitive_data_dir / competitor_key
        
        files = []
        if content_source in ["backlog", "all"]:
            backlog_dir = competitor_dir / "backlog"
            if backlog_dir.exists():
                files.extend(list(backlog_dir.glob("*.md")))
        
        if content_source in ["incremental", "all"]:
            incremental_dir = competitor_dir / "incremental" 
            if incremental_dir.exists():
                files.extend(list(incremental_dir.glob("*.md")))
        
        # Sort by modification time (newest first)
        return sorted(files, key=lambda f: f.stat().st_mtime, reverse=True)
    
    async def _parse_content_file(self, file_path: Path) -> List[Dict[str, Any]]:
        """
        Parse competitive content markdown file into content items.
        
        Args:
            file_path: Path to markdown file
            
        Returns:
            List of content items with metadata
        """
        try:
            content = await asyncio.to_thread(file_path.read_text, encoding='utf-8')
            
            # Simple markdown parser - split by headers
            items = []
            lines = content.split('\n')
            current_item = None
            current_content = []
            
            for line in lines:
                line = line.strip()
                
                # New content item starts with # header
                if line.startswith('# '):
                    # Save previous item if exists
                    if current_item:
                        current_item['content'] = '\n'.join(current_content).strip()
                        items.append(current_item)
                    
                    # Start new item
                    current_item = {
                        'id': f"{file_path.stem}_{len(items)+1}",
                        'title': line[2:].strip(),
                        'source': file_path.parent.parent.name,  # competitor_key
                        'publish_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC'),
                        'permalink': f"file://{file_path}"
                    }
                    current_content = []
                    
                elif current_item:
                    current_content.append(line)
            
            # Save final item
            if current_item:
                current_item['content'] = '\n'.join(current_content).strip()
                items.append(current_item)
            
            # If no headers found, treat entire file as one item
            if not items and content.strip():
                items = [{
                    'id': f"{file_path.stem}_1",
                    'title': file_path.stem.replace('_', ' ').title(),
                    'content': content.strip(),
                    'source': file_path.parent.parent.name,
                    'publish_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC'),
                    'permalink': f"file://{file_path}"
                }]
            
            self.logger.debug(f"Parsed {len(items)} content items from {file_path}")
            return items
            
        except Exception as e:
            self.logger.error(f"Error parsing content file {file_path}: {e}")
            return []
    
    async def _analyze_content_item(self, content_item: Dict[str, Any]) -> AnalysisResult:
        """
        Run content item through existing analysis pipeline.
        
        Reuses Claude analyzer, engagement analyzer, and keyword extractor.
        """
        # Extract content text
        content_text = content_item.get('content', '')
        title = content_item.get('title', '')
        
        # Run through existing analyzers
        try:
            # Claude analysis (if available)
            claude_result = None
            if self.claude_analyzer:
                claude_result = await self.claude_analyzer.analyze_content(
                    content_text, title, source_type="competitive"
                )
            
            # Engagement analysis
            engagement_metrics = {}
            if self.engagement_analyzer:
                # Calculate engagement rate using existing API
                engagement_rate = self.engagement_analyzer._calculate_engagement_rate(
                    content_item, content_item.get('source', 'competitive')
                )
                engagement_metrics = {
                    'engagement_rate': engagement_rate,
                    'quality_score': min(engagement_rate * 10, 1.0)  # Scale to 0-1
                }
            
            # Keyword extraction
            keywords = []
            if self.keyword_extractor:
                keywords = self.keyword_extractor.extract_keywords(content_text + " " + title)
            
            # Create analysis result
            analysis_result = AnalysisResult(
                content_id=content_item.get('id', ''),
                title=title,
                content=content_text,
                source=content_item.get('source', 'competitive'),
                analyzed_at=datetime.now(timezone.utc),
                claude_analysis=claude_result,
                engagement_metrics=engagement_metrics,
                keywords=keywords,
                metadata={
                    'original_item': content_item,
                    'analysis_type': 'competitive_intelligence'
                }
            )
            
            return analysis_result
            
        except Exception as e:
            content_id = content_item.get('id', 'unknown') if isinstance(content_item, dict) else 'invalid_item'
            self.logger.error(f"Error analyzing competitive content item {content_id}: {e}")
            # Return minimal result on error
            safe_content_id = content_item.get('id', '') if isinstance(content_item, dict) else ''
            safe_title = title if 'title' in locals() else content_item.get('title', '') if isinstance(content_item, dict) else ''
            safe_content = content_text if 'content_text' in locals() else content_item.get('content', '') if isinstance(content_item, dict) else ''
            
            return AnalysisResult(
                content_id=safe_content_id,
                title=safe_title,
                content=safe_content,
                source='competitive_error',
                analyzed_at=datetime.now(timezone.utc),
                metadata={'error': str(e), 'original_item': content_item}
            )
    
    def _enrich_with_competitive_metadata(
        self, 
        analysis_result: AnalysisResult, 
        competitor_key: str,
        competitor_info: Dict[str, Any]
    ) -> CompetitiveAnalysisResult:
        """
        Enrich base analysis result with competitive intelligence metadata.
        
        Args:
            analysis_result: Base analysis result from pipeline
            competitor_key: Competitor identifier  
            competitor_info: Competitor configuration
            
        Returns:
            Enhanced result with competitive metadata
        """
        # Build market context
        market_context = MarketContext(
            category=competitor_info['category'],
            priority=competitor_info['priority'],
            target_audience=competitor_info['target_audience'],
            content_focus_areas=competitor_info['content_focus'],
            analysis_focus=competitor_info['analysis_focus']
        )
        
        # Extract competitive metrics from original item
        original_item = analysis_result.metadata.get('original_item', {})
        social_metrics = original_item.get('social_metrics', {})
        
        # Calculate content quality score (simple implementation)
        quality_score = self._calculate_content_quality_score(analysis_result, social_metrics)
        
        # Determine content focus tags
        content_focus_tags = self._determine_content_focus_tags(
            analysis_result.keywords, competitor_info['content_focus']
        )
        
        # Calculate days since publish
        days_since_publish = self._calculate_days_since_publish(original_item)
        
        # Create competitive analysis result
        competitive_result = CompetitiveAnalysisResult(
            # Base analysis result fields
            content_id=analysis_result.content_id,
            title=analysis_result.title,
            content=analysis_result.content,
            source=analysis_result.source,
            analyzed_at=analysis_result.analyzed_at,
            claude_analysis=analysis_result.claude_analysis,
            engagement_metrics=analysis_result.engagement_metrics,
            keywords=analysis_result.keywords,
            metadata=analysis_result.metadata,
            
            # Competitive intelligence fields
            competitor_name=competitor_info['name'],
            competitor_platform=self._determine_platform(original_item),
            competitor_key=competitor_key,
            market_context=market_context,
            content_quality_score=quality_score,
            content_focus_tags=content_focus_tags,
            days_since_publish=days_since_publish,
            strategic_importance=self._assess_strategic_importance(quality_score, analysis_result.engagement_metrics)
        )
        
        return competitive_result
    
    def _calculate_content_quality_score(
        self, 
        analysis_result: AnalysisResult, 
        social_metrics: Dict[str, Any]
    ) -> float:
        """Calculate content quality score (0-1)"""
        score = 0.0
        
        # Title quality (0.25 weight)
        title_length = len(analysis_result.title)
        if 10 <= title_length <= 100:
            score += 0.25
        elif title_length > 5:
            score += 0.15
        
        # Content length (0.25 weight)
        content_length = len(analysis_result.content)
        if content_length > 500:
            score += 0.25
        elif content_length > 100:
            score += 0.15
        
        # Keyword relevance (0.25 weight)
        if len(analysis_result.keywords) > 3:
            score += 0.25
        elif len(analysis_result.keywords) > 0:
            score += 0.15
        
        # Social engagement (0.25 weight)
        engagement_rate = social_metrics.get('engagement_rate', 0)
        if engagement_rate > 0.05:  # 5% engagement
            score += 0.25
        elif engagement_rate > 0.01:  # 1% engagement
            score += 0.15
        
        return min(score, 1.0)  # Cap at 1.0
    
    def _determine_content_focus_tags(
        self, 
        keywords: List[str], 
        focus_areas: List[str]
    ) -> List[str]:
        """Determine content focus tags based on keywords and competitor focus"""
        tags = []
        
        # Map keywords to focus areas
        keyword_text = " ".join(keywords).lower()
        for focus_area in focus_areas:
            if focus_area.lower().replace('_', ' ') in keyword_text:
                tags.append(focus_area)
        
        # Add general HVAC tags based on keywords
        hvac_tag_mapping = {
            'troubleshooting': ['troubleshoot', 'problem', 'fix', 'repair', 'error'],
            'maintenance': ['maintenance', 'service', 'clean', 'replace', 'check'],
            'installation': ['install', 'setup', 'connect', 'mount', 'wire'],
            'refrigeration': ['refriger', 'cool', 'freeze', 'compressor'],
            'heating': ['heat', 'furnace', 'boiler', 'warm']
        }
        
        for tag, tag_keywords in hvac_tag_mapping.items():
            if any(tk in keyword_text for tk in tag_keywords) and tag not in tags:
                tags.append(tag)
        
        return tags[:5]  # Limit to top 5 tags
    
    def _determine_platform(self, original_item: Dict[str, Any]) -> str:
        """Determine content platform from original item"""
        permalink = original_item.get('permalink', '')
        if 'youtube.com' in permalink:
            return 'youtube'
        elif 'instagram.com' in permalink:
            return 'instagram' 
        elif any(domain in permalink for domain in ['hvacrschool.com', '.com', '.org']):
            return 'blog'
        else:
            return 'unknown'
    
    def _calculate_days_since_publish(self, original_item: Dict[str, Any]) -> Optional[int]:
        """Calculate days since content was published"""
        try:
            publish_date_str = original_item.get('publish_date')
            if not publish_date_str:
                return None
            
            # Parse various date formats
            publish_date = None
            date_formats = [
                ('%Y-%m-%d %H:%M:%S %Z', publish_date_str),  # Try original format first
                ('%Y-%m-%dT%H:%M:%S%z', publish_date_str.replace(' UTC', '+00:00')),  # Convert UTC to offset  
                ('%Y-%m-%d', publish_date_str),  # Date only format
            ]
            
            for fmt, date_str in date_formats:
                try:
                    publish_date = datetime.strptime(date_str, fmt)
                    break
                except ValueError:
                    continue
            
            if publish_date:
                now = datetime.now(timezone.utc)
                if publish_date.tzinfo is None:
                    publish_date = publish_date.replace(tzinfo=timezone.utc)
                elif publish_date.tzinfo != timezone.utc:
                    publish_date = publish_date.astimezone(timezone.utc)
                
                delta = now - publish_date
                return delta.days
            
        except Exception as e:
            self.logger.debug(f"Error calculating days since publish: {e}")
        
        return None
    
    def _assess_strategic_importance(
        self, 
        quality_score: float, 
        engagement_metrics: Dict[str, Any]
    ) -> str:
        """Assess strategic importance of content"""
        engagement_rate = engagement_metrics.get('engagement_rate', 0)
        
        if quality_score > 0.7 and engagement_rate > 0.05:
            return "high"
        elif quality_score > 0.5 or engagement_rate > 0.02:
            return "medium"
        else:
            return "low"
    
    async def save_competitive_analysis_results(
        self, 
        results: List[CompetitiveAnalysisResult],
        competitor_key: str,
        analysis_type: str = "daily"
    ) -> Path:
        """
        Save competitive analysis results to file.
        
        Args:
            results: Analysis results to save
            competitor_key: Competitor identifier
            analysis_type: Type of analysis (daily, weekly, etc.)
            
        Returns:
            Path to saved file
        """
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"competitive_analysis_{competitor_key}_{analysis_type}_{timestamp}.json"
        filepath = self.competitive_analysis_dir / filename
        
        # Convert results to dictionaries
        results_data = {
            'analysis_date': datetime.now(timezone.utc).isoformat(),
            'competitor_key': competitor_key,
            'analysis_type': analysis_type,
            'total_items': len(results),
            'results': [result.to_competitive_dict() for result in results]
        }
        
        # Save to JSON
        import json
        
        def _write_json_file(filepath, data):
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=2, ensure_ascii=False)
        
        await asyncio.to_thread(_write_json_file, filepath, results_data)
        
        self.logger.info(f"Saved competitive analysis results to {filepath}")
        return filepath
    
    def _calculate_competitor_metrics(
        self, 
        results: List[CompetitiveAnalysisResult], 
        competitor_name: str
    ) -> CompetitorMetrics:
        """
        Calculate aggregated metrics for a competitor based on analysis results.
        
        Args:
            results: List of competitive analysis results
            competitor_name: Name of competitor to calculate metrics for
            
        Returns:
            Aggregated competitor metrics
        """
        
        if not results:
            return CompetitorMetrics(
                competitor_name=competitor_name,
                total_content_pieces=0,
                avg_engagement_rate=0.0,
                total_views=0,
                content_frequency=0.0,
                top_topics=[],
                content_consistency_score=0.0,
                market_position=MarketPosition.FOLLOWER
            )
        
        # Calculate metrics
        total_engagement = sum(
            result.engagement_metrics.get('engagement_rate', 0) 
            for result in results
        )
        avg_engagement = total_engagement / len(results)
        
        total_views = sum(
            result.engagement_metrics.get('views', 0)
            for result in results
        )
        
        # Extract top topics from claude_analysis
        topics = []
        for result in results:
            if result.claude_analysis and isinstance(result.claude_analysis, dict):
                topic = result.claude_analysis.get('primary_topic')
                if topic:
                    topics.append(topic)
        
        # Count topic frequency
        from collections import Counter
        topic_counts = Counter(topics)
        top_topics = [topic for topic, count in topic_counts.most_common(5)]
        
        # Simple content frequency (posts per week estimate)
        content_frequency = len(results) / 4.0  # Assume 4 weeks of data
        
        # Simple consistency score based on topic diversity
        topic_diversity = len(set(topics)) / max(len(topics), 1)
        content_consistency_score = min(topic_diversity, 1.0)
        
        # Determine market position
        market_position = self._determine_market_position_from_metrics(
            len(results), avg_engagement, total_views, content_frequency
        )
        
        return CompetitorMetrics(
            competitor_name=competitor_name,
            total_content_pieces=len(results),
            avg_engagement_rate=avg_engagement,
            total_views=total_views,
            content_frequency=content_frequency,
            top_topics=top_topics,
            content_consistency_score=content_consistency_score,
            market_position=market_position
        )
    
    def _determine_market_position(self, metrics: CompetitorMetrics) -> MarketPosition:
        """
        Determine market position based on competitor metrics.
        
        Args:
            metrics: Competitor metrics
            
        Returns:
            Market position classification
        """
        return self._determine_market_position_from_metrics(
            metrics.total_content_pieces,
            metrics.avg_engagement_rate,
            metrics.total_views,
            metrics.content_frequency
        )
    
    def _determine_market_position_from_metrics(
        self,
        content_pieces: int,
        avg_engagement: float,
        total_views: int,
        content_frequency: float
    ) -> MarketPosition:
        """Determine market position from raw metrics"""
        
        # Leader criteria: High content volume, high engagement, high views
        if (content_pieces >= 50 and 
            avg_engagement >= 0.04 and 
            total_views >= 100000 and 
            content_frequency >= 10.0):
            return MarketPosition.LEADER
        
        # Challenger criteria: Good content volume, decent engagement
        elif (content_pieces >= 25 and 
              avg_engagement >= 0.025 and 
              total_views >= 50000 and 
              content_frequency >= 5.0):
            return MarketPosition.CHALLENGER
        
        # Follower: Everything else with some activity
        elif content_pieces > 5:
            return MarketPosition.FOLLOWER
        
        # Niche: Low content volume
        else:
            return MarketPosition.NICHE