"""
Keyword Extractor

Extracts HVAC-specific keywords, identifies SEO opportunities,
and analyzes keyword trends across content.
"""

import re
import logging
from typing import Dict, List, Any, Set, Tuple
from collections import Counter, defaultdict
from dataclasses import dataclass


@dataclass
class KeywordAnalysis:
    """Keyword analysis results"""
    content_id: str
    primary_keywords: List[str]
    technical_terms: List[str]
    product_keywords: List[str]
    seo_keywords: List[str]
    keyword_density: Dict[str, float]


@dataclass
class SEOOpportunity:
    """SEO opportunity identification"""
    keyword: str
    frequency: int
    sources_mentioning: List[str]
    competition_level: str  # 'low', 'medium', 'high'
    opportunity_score: float


class KeywordExtractor:
    """Extracts and analyzes HVAC-specific keywords"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        
        # HVAC-specific keyword categories
        self.hvac_systems = {
            'heat pump', 'heat pumps', 'air conditioning', 'ac unit', 'ac units',
            'hvac system', 'hvac systems', 'refrigeration', 'commercial hvac',
            'residential hvac', 'mini split', 'mini splits', 'ductless system',
            'central air', 'furnace', 'boiler', 'chiller', 'cooling tower',
            'air handler', 'ahu', 'rtu', 'rooftop unit', 'package unit'
        }
        
        self.refrigerants = {
            'r410a', 'r-410a', 'r22', 'r-22', 'r32', 'r-32', 'r454b', 'r-454b',
            'r290', 'r-290', 'refrigerant', 'refrigerants', 'freon', 'puron',
            'hfc', 'hfo', 'a2l refrigerant', 'refrigerant leak', 'refrigerant recovery'
        }
        
        self.hvac_components = {
            'compressor', 'condenser', 'evaporator', 'expansion valve', 'txv',
            'metering device', 'suction line', 'liquid line', 'reversing valve',
            'defrost board', 'control board', 'contactors', 'capacitor',
            'thermostat', 'pressure switch', 'float switch', 'crankcase heater',
            'accumulator', 'receiver', 'drier', 'filter drier'
        }
        
        self.hvac_tools = {
            'manifold gauges', 'digital manifold', 'micron gauge', 'vacuum pump',
            'recovery machine', 'leak detector', 'multimeter', 'clamp meter',
            'manometer', 'psychrometer', 'refrigerant identifier', 'brazing torch',
            'tubing cutter', 'flaring tool', 'swaging tool', 'core remover',
            'charging hoses', 'service valves'
        }
        
        self.hvac_processes = {
            'evacuation', 'charging', 'recovery', 'brazing', 'leak detection',
            'pressure testing', 'superheat', 'subcooling', 'static pressure',
            'airflow measurement', 'commissioning', 'startup', 'troubleshooting',
            'diagnosis', 'maintenance', 'service', 'installation', 'repair'
        }
        
        self.hvac_problems = {
            'low refrigerant', 'refrigerant leak', 'dirty coil', 'frozen coil',
            'short cycling', 'low airflow', 'high head pressure', 'low suction',
            'compressor failure', 'txv failure', 'electrical problem', 'no cooling',
            'no heating', 'poor performance', 'high utility bills', 'noise issues'
        }
        
        # Combine all HVAC keywords
        self.all_hvac_keywords = (
            self.hvac_systems | self.refrigerants | self.hvac_components |
            self.hvac_tools | self.hvac_processes | self.hvac_problems
        )
        
        # Common stop words to filter out
        self.stop_words = {
            'the', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with',
            'by', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
            'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
            'should', 'may', 'might', 'can', 'this', 'that', 'these', 'those',
            'what', 'when', 'where', 'why', 'how', 'who', 'which'
        }

    def extract_keywords(self, content_item: Dict[str, Any]) -> KeywordAnalysis:
        """Extract keywords from a content item"""
        
        content_text = self._get_content_text(content_item)
        content_id = content_item.get('id', 'unknown')
        
        if not content_text:
            return KeywordAnalysis(
                content_id=content_id,
                primary_keywords=[],
                technical_terms=[],
                product_keywords=[],
                seo_keywords=[],
                keyword_density={}
            )
        
        # Clean and normalize text
        clean_text = self._clean_text(content_text)
        
        # Extract different types of keywords
        primary_keywords = self._extract_primary_keywords(clean_text)
        technical_terms = self._extract_technical_terms(clean_text)
        product_keywords = self._extract_product_keywords(clean_text)
        seo_keywords = self._extract_seo_keywords(clean_text)
        
        # Calculate keyword density
        keyword_density = self._calculate_keyword_density(clean_text, primary_keywords)
        
        return KeywordAnalysis(
            content_id=content_id,
            primary_keywords=primary_keywords,
            technical_terms=technical_terms,
            product_keywords=product_keywords,
            seo_keywords=seo_keywords,
            keyword_density=keyword_density
        )

    def identify_trending_keywords(self, content_items: List[Dict[str, Any]], 
                                 min_frequency: int = 3) -> List[Tuple[str, int]]:
        """Identify trending keywords across content items"""
        
        keyword_counts = Counter()
        
        for item in content_items:
            try:
                analysis = self.extract_keywords(item)
                
                # Count all types of keywords
                for keyword in (analysis.primary_keywords + analysis.technical_terms + 
                               analysis.product_keywords + analysis.seo_keywords):
                    keyword_counts[keyword.lower()] += 1
                    
            except Exception as e:
                self.logger.error(f"Error extracting keywords from {item.get('id')}: {e}")
        
        # Filter by minimum frequency and return top keywords
        trending = [(keyword, count) for keyword, count in keyword_counts.items() 
                   if count >= min_frequency]
        
        return sorted(trending, key=lambda x: x[1], reverse=True)

    def identify_seo_opportunities(self, hkia_content: List[Dict[str, Any]], 
                                 competitor_content: Dict[str, List[Dict[str, Any]]]) -> List[SEOOpportunity]:
        """Identify SEO keyword opportunities by comparing HKIA vs competitor content"""
        
        # Get HKIA keywords
        hkia_keywords = Counter()
        for item in hkia_content:
            analysis = self.extract_keywords(item)
            for keyword in analysis.seo_keywords:
                hkia_keywords[keyword.lower()] += 1
        
        # Get competitor keywords  
        competitor_keywords = defaultdict(lambda: Counter())
        for source, items in competitor_content.items():
            for item in items:
                analysis = self.extract_keywords(item)
                for keyword in analysis.seo_keywords:
                    competitor_keywords[source][keyword.lower()] += 1
        
        # Find opportunities (keywords competitors use but HKIA doesn't)
        opportunities = []
        
        for source, keywords in competitor_keywords.items():
            for keyword, frequency in keywords.items():
                if frequency >= 2 and hkia_keywords.get(keyword, 0) < 2:  # HKIA has low usage
                    
                    # Calculate opportunity score
                    competitor_usage = sum(1 for comp_kws in competitor_keywords.values() 
                                         if keyword in comp_kws)
                    
                    opportunity_score = (frequency * 0.6) + (competitor_usage * 0.4)
                    
                    competition_level = self._assess_competition_level(keyword, competitor_keywords)
                    
                    opportunities.append(SEOOpportunity(
                        keyword=keyword,
                        frequency=frequency,
                        sources_mentioning=[s for s, kws in competitor_keywords.items() if keyword in kws],
                        competition_level=competition_level,
                        opportunity_score=opportunity_score
                    ))
        
        # Sort by opportunity score
        return sorted(opportunities, key=lambda x: x.opportunity_score, reverse=True)

    def _get_content_text(self, content_item: Dict[str, Any]) -> str:
        """Extract all text content from item"""
        
        text_parts = []
        
        # Add title with higher weight (repeat 2x)
        if title := content_item.get('title'):
            text_parts.extend([title] * 2)
        
        # Add description
        if description := content_item.get('description'):
            text_parts.append(description)
        
        # Add transcript (YouTube)
        if transcript := content_item.get('transcript'):
            text_parts.append(transcript)
        
        # Add content (blog posts)
        if content := content_item.get('content'):
            text_parts.append(content)
        
        # Add hashtags (Instagram)
        if hashtags := content_item.get('hashtags'):
            if isinstance(hashtags, str):
                text_parts.append(hashtags)
            elif isinstance(hashtags, list):
                text_parts.extend(hashtags)
        
        return ' '.join(text_parts)

    def _clean_text(self, text: str) -> str:
        """Clean and normalize text for keyword extraction"""
        
        # Convert to lowercase
        text = text.lower()
        
        # Remove special characters but keep hyphens and spaces
        text = re.sub(r'[^\w\s\-]', ' ', text)
        
        # Normalize whitespace
        text = re.sub(r'\s+', ' ', text)
        
        return text.strip()

    def _extract_primary_keywords(self, text: str) -> List[str]:
        """Extract primary HVAC keywords from text"""
        
        found_keywords = []
        
        for keyword in self.all_hvac_keywords:
            if keyword.lower() in text:
                found_keywords.append(keyword)
        
        # Also look for multi-word technical phrases
        technical_phrases = [
            'heat pump defrost', 'refrigerant leak detection', 'txv bulb placement',
            'superheat subcooling', 'static pressure measurement', 'vacuum pump down',
            'brazing copper lines', 'electrical troubleshooting', 'compressor diagnosis'
        ]
        
        for phrase in technical_phrases:
            if phrase in text:
                found_keywords.append(phrase)
        
        return list(set(found_keywords))  # Remove duplicates

    def _extract_technical_terms(self, text: str) -> List[str]:
        """Extract HVAC technical terminology"""
        
        # Look for measurement units and technical specs
        tech_patterns = [
            r'\d+\s*btu', r'\d+\s*tons?', r'\d+\s*cfm', r'\d+\s*psi',
            r'\d+\s*degrees?', r'\d+\s*f\b', r'\d+\s*microns?',
            r'r-?\d{2,3}[a-z]?', r'\d+\s*seer', r'\d+\s*hspf'
        ]
        
        technical_terms = []
        
        for pattern in tech_patterns:
            matches = re.findall(pattern, text)
            technical_terms.extend(matches)
        
        # Add component-specific terms
        component_terms = [
            'low pressure switch', 'high pressure switch', 'crankcase heater',
            'reversing valve solenoid', 'defrost control board', 'txv sensing bulb'
        ]
        
        for term in component_terms:
            if term in text:
                technical_terms.append(term)
        
        return technical_terms

    def _extract_product_keywords(self, text: str) -> List[str]:
        """Extract product and brand keywords"""
        
        # Common HVAC brands and products
        brands = [
            'carrier', 'trane', 'york', 'lennox', 'rheem', 'goodman', 'amana',
            'bryant', 'payne', 'heil', 'tempstar', 'comfortmaker', 'ducane'
        ]
        
        products = [
            'infinity series', 'variable speed', 'two stage', 'single stage',
            'inverter technology', 'communicating system', 'zoning system'
        ]
        
        found_products = []
        
        for brand in brands:
            if brand in text:
                found_products.append(brand)
        
        for product in products:
            if product in text:
                found_products.append(product)
        
        return found_products

    def _extract_seo_keywords(self, text: str) -> List[str]:
        """Extract SEO-relevant keyword phrases"""
        
        # Common HVAC SEO phrases
        seo_phrases = [
            'hvac repair', 'hvac installation', 'hvac maintenance', 'ac repair',
            'heat pump repair', 'furnace repair', 'hvac service', 'hvac contractor',
            'hvac technician', 'hvac troubleshooting', 'hvac training',
            'refrigerant leak repair', 'duct cleaning', 'hvac replacement',
            'energy efficient hvac', 'smart thermostat installation'
        ]
        
        found_seo = []
        
        for phrase in seo_phrases:
            if phrase in text:
                found_seo.append(phrase)
        
        # Look for location-based keywords (simplified)
        location_patterns = [
            r'hvac\s+\w+\s+area', r'hvac\s+near\s+me', r'local\s+hvac',
            r'residential\s+hvac', r'commercial\s+hvac'
        ]
        
        for pattern in location_patterns:
            matches = re.findall(pattern, text)
            found_seo.extend(matches)
        
        return found_seo

    def _calculate_keyword_density(self, text: str, keywords: List[str]) -> Dict[str, float]:
        """Calculate keyword density for primary keywords"""
        
        words = text.split()
        total_words = len(words)
        
        if total_words == 0:
            return {}
        
        density = {}
        
        for keyword in keywords[:10]:  # Limit to top 10 keywords
            count = text.count(keyword.lower())
            density[keyword] = (count / total_words) * 100  # Percentage
        
        return density

    def _assess_competition_level(self, keyword: str, 
                                competitor_keywords: Dict[str, Counter]) -> str:
        """Assess competition level for a keyword"""
        
        competitor_count = sum(1 for comp_kws in competitor_keywords.values() 
                             if keyword in comp_kws)
        
        total_frequency = sum(comp_kws.get(keyword, 0) 
                            for comp_kws in competitor_keywords.values())
        
        if competitor_count >= 3 and total_frequency >= 10:
            return 'high'
        elif competitor_count >= 2 or total_frequency >= 5:
            return 'medium'
        else:
            return 'low'