"""Domain-Specific Enhancement Pipeline.

This module provides specialized enhancement workflows for different domains,
including technical terminology enhancement, medical vocabulary optimization,
academic citation handling, and domain-specific quality metrics.
"""

import logging
import re
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, List, Optional, Any, Tuple
from enum import Enum

from src.services.enhancement.service import DeepSeekEnhancementService
from src.services.domain_adaptation import DomainDetector

logger = logging.getLogger(__name__)


class DomainType(Enum):
    """Supported domain types for enhancement."""
    GENERAL = "general"
    TECHNICAL = "technical"
    MEDICAL = "medical"
    ACADEMIC = "academic"
    LEGAL = "legal"


@dataclass
class DomainEnhancementConfig:
    """Configuration for domain-specific enhancement."""
    domain: DomainType
    enable_terminology_enhancement: bool = True
    enable_citation_handling: bool = True
    enable_formatting_optimization: bool = True
    quality_threshold: float = 0.8
    max_enhancement_iterations: int = 2
    
    # Domain-specific settings
    technical_jargon_threshold: float = 0.7
    medical_terminology_threshold: float = 0.8
    academic_citation_threshold: float = 0.75
    legal_precision_threshold: float = 0.85


@dataclass
class EnhancementResult:
    """Result of domain-specific enhancement."""
    original_text: str
    enhanced_text: str
    domain: DomainType
    confidence_score: float
    improvements: List[str]
    terminology_corrections: List[str]
    quality_metrics: Dict[str, float]
    processing_time: float


class DomainEnhancementPipeline:
    """Domain-specific enhancement pipeline with specialized workflows."""
    
    def __init__(self, enhancement_service: Optional[DeepSeekEnhancementService] = None):
        self.enhancement_service = enhancement_service
        self.domain_detector = DomainDetector()
        
        # Domain-specific enhancement strategies
        self.strategies = {
            DomainType.TECHNICAL: self._enhance_technical_content,
            DomainType.MEDICAL: self._enhance_medical_content,
            DomainType.ACADEMIC: self._enhance_academic_content,
            DomainType.LEGAL: self._enhance_legal_content,
            DomainType.GENERAL: self._enhance_general_content
        }
        
        # Domain-specific quality metrics
        self.quality_metrics = {
            DomainType.TECHNICAL: self._calculate_technical_quality,
            DomainType.MEDICAL: self._calculate_medical_quality,
            DomainType.ACADEMIC: self._calculate_academic_quality,
            DomainType.LEGAL: self._calculate_legal_quality,
            DomainType.GENERAL: self._calculate_general_quality
        }
    
    async def enhance_content(
        self, 
        text: str, 
        domain: Optional[DomainType] = None,
        config: Optional[DomainEnhancementConfig] = None
    ) -> EnhancementResult:
        """Enhance content using domain-specific strategies."""
        import time
        start_time = time.time()
        
        # Auto-detect domain if not specified
        if domain is None:
            detected_domain = self.domain_detector.detect_domain_from_text(text)
            domain = DomainType(detected_domain) if detected_domain else DomainType.GENERAL
        
        # Use default config if not provided
        if config is None:
            config = DomainEnhancementConfig(domain=domain)
        
        logger.info(f"Enhancing {domain.value} content with specialized pipeline")
        
        # Apply domain-specific enhancement strategy
        if domain in self.strategies:
            enhanced_text, improvements, terminology_corrections = await self.strategies[domain](
                text, config
            )
        else:
            enhanced_text, improvements, terminology_corrections = await self._enhance_general_content(
                text, config
            )
        
        # Calculate quality metrics
        quality_metrics = self.quality_metrics[domain](enhanced_text, text)
        
        # Calculate overall confidence
        confidence_score = self._calculate_confidence_score(quality_metrics)
        
        processing_time = time.time() - start_time
        
        return EnhancementResult(
            original_text=text,
            enhanced_text=enhanced_text,
            domain=domain,
            confidence_score=confidence_score,
            improvements=improvements,
            terminology_corrections=terminology_corrections,
            quality_metrics=quality_metrics,
            processing_time=processing_time
        )
    
    async def _enhance_technical_content(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance technical content with specialized terminology handling."""
        improvements = []
        terminology_corrections = []
        
        # Technical terminology enhancement
        if config.enable_terminology_enhancement:
            enhanced_text, tech_improvements, tech_corrections = await self._enhance_technical_terminology(
                text, config
            )
            improvements.extend(tech_improvements)
            terminology_corrections.extend(tech_corrections)
        else:
            enhanced_text = text
        
        # Formatting optimization for technical content
        if config.enable_formatting_optimization:
            enhanced_text = self._optimize_technical_formatting(enhanced_text)
            improvements.append("Applied technical formatting standards")
        
        # Add domain prefix
        enhanced_text = f"[TECHNICAL] {enhanced_text}"
        improvements.append("Added technical domain prefix")
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_medical_content(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance medical content with specialized vocabulary optimization."""
        improvements = []
        terminology_corrections = []
        
        # Medical terminology enhancement
        if config.enable_terminology_enhancement:
            enhanced_text, med_improvements, med_corrections = await self._enhance_medical_terminology(
                text, config
            )
            improvements.extend(med_improvements)
            terminology_corrections.extend(med_corrections)
        else:
            enhanced_text = text
        
        # Medical formatting standards
        if config.enable_formatting_optimization:
            enhanced_text = self._apply_medical_formatting(enhanced_text)
            improvements.append("Applied medical documentation standards")
        
        # Add domain prefix
        enhanced_text = f"[MEDICAL] {enhanced_text}"
        improvements.append("Added medical domain prefix")
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_academic_content(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance academic content with citation and reference handling."""
        improvements = []
        terminology_corrections = []
        
        # Citation and reference handling
        if config.enable_citation_handling:
            enhanced_text, citation_improvements = await self._enhance_citations_and_references(
                text, config
            )
            improvements.extend(citation_improvements)
        else:
            enhanced_text = text
        
        # Academic terminology enhancement
        if config.enable_terminology_enhancement:
            enhanced_text, acad_improvements, acad_corrections = await self._enhance_academic_terminology(
                enhanced_text, config
            )
            improvements.extend(acad_improvements)
            terminology_corrections.extend(acad_corrections)
        
        # Academic formatting
        if config.enable_formatting_optimization:
            enhanced_text = self._apply_academic_formatting(enhanced_text)
            improvements.append("Applied academic formatting standards")
        
        # Add domain prefix
        enhanced_text = f"[ACADEMIC] {enhanced_text}"
        improvements.append("Added academic domain prefix")
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_legal_content(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance legal content with precision and terminology optimization."""
        improvements = []
        terminology_corrections = []
        
        # Legal terminology enhancement
        if config.enable_terminology_enhancement:
            enhanced_text, legal_improvements, legal_corrections = await self._enhance_legal_terminology(
                text, config
            )
            improvements.extend(legal_improvements)
            terminology_corrections.extend(legal_corrections)
        else:
            enhanced_text = text
        
        # Legal precision optimization
        enhanced_text = self._optimize_legal_precision(enhanced_text)
        improvements.append("Applied legal precision standards")
        
        # Add domain prefix
        enhanced_text = f"[LEGAL] {enhanced_text}"
        improvements.append("Added legal domain prefix")
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_general_content(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance general content with standard improvements."""
        improvements = []
        terminology_corrections = []
        
        # Use the base enhancement service if available
        if self.enhancement_service is not None:
            try:
                result = await self.enhancement_service.enhance_transcript(text)
                enhanced_text = result.get("enhanced_text", text)
                improvements.append("Applied general enhancement")
            except Exception as e:
                logger.warning(f"General enhancement failed: {e}")
                enhanced_text = text
        else:
            # Fallback behavior when no enhancement service is available
            enhanced_text = text
            improvements.append("No enhancement service available - using original text")
        
        # Add general domain prefix
        enhanced_text = f"[GENERAL] {enhanced_text}"
        improvements.append("Added general domain prefix")
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_technical_terminology(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance technical terminology using AI."""
        improvements = []
        terminology_corrections = []
        
        # Check if enhancement service is available
        if self.enhancement_service is None:
            enhanced_text = text
            improvements.append("No enhancement service available - using original text")
            return enhanced_text, improvements, terminology_corrections
        
        # Technical enhancement prompt
        prompt = f"""Enhance this technical transcript by:
1. Correcting technical terms and jargon
2. Fixing programming language syntax
3. Improving technical accuracy
4. Maintaining technical precision

Technical transcript:
{text}

Return ONLY the enhanced transcript with corrected technical terminology."""

        try:
            result = await self.enhancement_service.enhance_transcript(text, prompt=prompt)
            enhanced_text = result.get("enhanced_text", text)
            
            # Identify technical improvements
            if enhanced_text != text:
                improvements.append("Enhanced technical terminology")
                terminology_corrections.extend(self._identify_technical_corrections(text, enhanced_text))
        except Exception as e:
            logger.warning(f"Technical terminology enhancement failed: {e}")
            enhanced_text = text
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_medical_terminology(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance medical terminology using AI."""
        improvements = []
        terminology_corrections = []
        
        # Check if enhancement service is available
        if self.enhancement_service is None:
            enhanced_text = text
            improvements.append("No enhancement service available - using original text")
            return enhanced_text, improvements, terminology_corrections
        
        # Medical enhancement prompt
        prompt = f"""Enhance this medical transcript by:
1. Correcting medical terminology and drug names
2. Fixing anatomical and physiological terms
3. Improving medical accuracy and precision
4. Maintaining medical documentation standards

Medical transcript:
{text}

Return ONLY the enhanced transcript with corrected medical terminology."""

        try:
            result = await self.enhancement_service.enhance_transcript(text, prompt=prompt)
            enhanced_text = result.get("enhanced_text", text)
            
            if enhanced_text != text:
                improvements.append("Enhanced medical terminology")
                terminology_corrections.extend(self._identify_medical_corrections(text, enhanced_text))
        except Exception as e:
            logger.warning(f"Medical terminology enhancement failed: {e}")
            enhanced_text = text
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_citations_and_references(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str]]:
        """Enhance academic citations and references."""
        improvements = []
        
        # Citation enhancement prompt
        prompt = f"""Enhance this academic transcript by:
1. Identifying and formatting citations properly
2. Improving reference formatting
3. Adding missing citation markers
4. Maintaining academic citation standards

Academic transcript:
{text}

Return ONLY the enhanced transcript with proper citations and references."""

        try:
            result = await self.enhancement_service.enhance_transcript(text, prompt=prompt)
            enhanced_text = result.get("enhanced_text", text)
            
            if enhanced_text != text:
                improvements.append("Enhanced citations and references")
        except Exception as e:
            logger.warning(f"Citation enhancement failed: {e}")
            enhanced_text = text
        
        return enhanced_text, improvements
    
    async def _enhance_academic_terminology(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance academic terminology."""
        improvements = []
        terminology_corrections = []
        
        # Academic enhancement prompt
        prompt = f"""Enhance this academic transcript by:
1. Correcting academic terminology
2. Improving research methodology terms
3. Enhancing theoretical framework language
4. Maintaining academic precision

Academic transcript:
{text}

Return ONLY the enhanced transcript with improved academic terminology."""

        try:
            result = await self.enhancement_service.enhance_transcript(text, prompt=prompt)
            enhanced_text = result.get("enhanced_text", text)
            
            if enhanced_text != text:
                improvements.append("Enhanced academic terminology")
                terminology_corrections.extend(self._identify_academic_corrections(text, enhanced_text))
        except Exception as e:
            logger.warning(f"Academic terminology enhancement failed: {e}")
            enhanced_text = text
        
        return enhanced_text, improvements, terminology_corrections
    
    async def _enhance_legal_terminology(
        self, 
        text: str, 
        config: DomainEnhancementConfig
    ) -> Tuple[str, List[str], List[str]]:
        """Enhance legal terminology."""
        improvements = []
        terminology_corrections = []
        
        # Legal enhancement prompt
        prompt = f"""Enhance this legal transcript by:
1. Correcting legal terminology and case law references
2. Fixing statutory and regulatory citations
3. Improving legal precision and accuracy
4. Maintaining legal documentation standards

Legal transcript:
{text}

Return ONLY the enhanced transcript with corrected legal terminology."""

        try:
            result = await self.enhancement_service.enhance_transcript(text, prompt=prompt)
            enhanced_text = result.get("enhanced_text", text)
            
            if enhanced_text != text:
                improvements.append("Enhanced legal terminology")
                terminology_corrections.extend(self._identify_legal_corrections(text, enhanced_text))
        except Exception as e:
            logger.warning(f"Legal terminology enhancement failed: {e}")
            enhanced_text = text
        
        return enhanced_text, improvements, terminology_corrections
    
    def _optimize_technical_formatting(self, text: str) -> str:
        """Apply technical formatting standards."""
        # Code block formatting
        text = re.sub(r'\b(code|function|method|class)\b', r'`\1`', text, flags=re.IGNORECASE)
        
        # File path formatting
        text = re.sub(r'([A-Za-z]:\\[^\s]+|/[^\s]+)', r'`\1`', text)
        
        # Version number formatting
        text = re.sub(r'\b(v\d+\.\d+\.\d+)\b', r'**\1**', text)
        
        return text
    
    def _apply_medical_formatting(self, text: str) -> str:
        """Apply medical documentation standards."""
        # Drug name formatting
        text = re.sub(r'\b(aspirin|ibuprofen|acetaminophen)\b', r'**\1**', text, flags=re.IGNORECASE)
        
        # Vital signs formatting
        text = re.sub(r'\b(\d+/\d+ mmHg|\d+ bpm|\d+\.\d+°[CF])\b', r'`\1`', text)
        
        return text
    
    def _apply_academic_formatting(self, text: str) -> str:
        """Apply academic formatting standards."""
        # Citation formatting - simpler pattern without word boundaries
        text = re.sub(r'(et al\.|ibid\.|op\. cit\.)', r'*\1*', text)
        
        # Figure and table references
        text = re.sub(r'\b(Figure \d+|Table \d+)\b', r'**\1**', text)
        
        return text
    
    def _optimize_legal_precision(self, text: str) -> str:
        """Optimize legal precision and clarity."""
        # Legal term emphasis
        legal_terms = ['shall', 'must', 'may', 'hereby', 'whereas', 'therefore']
        for term in legal_terms:
            # Use a lambda function to avoid regex group reference issues
            text = re.sub(rf'\b{re.escape(term)}\b', lambda m: f'**{m.group(0)}**', text, flags=re.IGNORECASE)
        
        return text
    
    def _identify_technical_corrections(self, original: str, enhanced: str) -> List[str]:
        """Identify technical terminology corrections."""
        corrections = []
        
        # Common technical corrections
        tech_corrections = {
            'python free': 'Python 3',
            'my sequel': 'MySQL',
            'java script': 'JavaScript',
            'see sharp': 'C#',
            'see plus plus': 'C++'
        }
        
        for error, correction in tech_corrections.items():
            if error in original.lower() and correction.lower() in enhanced.lower():
                corrections.append(f"Corrected '{error}' to '{correction}'")
        
        return corrections
    
    def _identify_medical_corrections(self, original: str, enhanced: str) -> List[str]:
        """Identify medical terminology corrections."""
        corrections = []
        
        # Common medical corrections
        medical_corrections = {
            'hippa': 'HIPAA',
            'prozack': 'Prozac',
            'ambulance': 'ambulance',
            'diagnosis': 'diagnosis'
        }
        
        for error, correction in medical_corrections.items():
            if error in original.lower() and correction.lower() in enhanced.lower():
                corrections.append(f"Corrected '{error}' to '{correction}'")
        
        return corrections
    
    def _identify_academic_corrections(self, original: str, enhanced: str) -> List[str]:
        """Identify academic terminology corrections."""
        corrections = []
        
        # Common academic corrections
        academic_corrections = {
            'methodology': 'methodology',
            'hypothesis': 'hypothesis',
            'literature': 'literature'
        }
        
        for error, correction in academic_corrections.items():
            if error in original.lower() and correction.lower() in enhanced.lower():
                corrections.append(f"Corrected '{error}' to '{correction}'")
        
        return corrections
    
    def _identify_legal_corrections(self, original: str, enhanced: str) -> List[str]:
        """Identify legal terminology corrections."""
        corrections = []
        
        # Common legal corrections
        legal_corrections = {
            'jurisdiction': 'jurisdiction',
            'statute': 'statute',
            'compliance': 'compliance'
        }
        
        for error, correction in legal_corrections.items():
            if error in original.lower() and correction.lower() in enhanced.lower():
                corrections.append(f"Corrected '{error}' to '{correction}'")
        
        return corrections
    
    def _calculate_technical_quality(self, enhanced_text: str, original_text: str) -> Dict[str, float]:
        """Calculate technical content quality metrics."""
        # Technical term density
        tech_terms = ['algorithm', 'system', 'software', 'hardware', 'implementation', 'code', 'programming']
        tech_term_count = sum(1 for term in tech_terms if term.lower() in enhanced_text.lower())
        tech_density = tech_term_count / max(len(enhanced_text.split()), 1)
        
        # Code reference accuracy
        code_patterns = r'`[^`]+`|\*\*[^*]+\*\*'
        code_references = len(re.findall(code_patterns, enhanced_text))
        code_accuracy = min(code_references / max(len(enhanced_text.split()) * 0.1, 1), 1.0)
        
        return {
            'technical_term_density': tech_density,
            'code_reference_accuracy': code_accuracy,
            'technical_precision': (tech_density + code_accuracy) / 2
        }
    
    def _calculate_medical_quality(self, enhanced_text: str, original_text: str) -> Dict[str, float]:
        """Calculate medical content quality metrics."""
        # Medical terminology accuracy
        medical_terms = ['patient', 'diagnosis', 'treatment', 'symptom', 'clinical', 'medical']
        medical_term_count = sum(1 for term in medical_terms if term.lower() in enhanced_text.lower())
        medical_accuracy = min(medical_term_count / max(len(enhanced_text.split()) * 0.05, 1), 1.0)
        
        # Medical formatting compliance
        formatting_score = 0.0
        if re.search(r'\*\*[^*]+\*\*', enhanced_text):  # Bold medical terms
            formatting_score += 0.5
        if re.search(r'`[^`]+`', enhanced_text):  # Code vital signs
            formatting_score += 0.5
        
        return {
            'medical_terminology_accuracy': medical_accuracy,
            'formatting_compliance': formatting_score,
            'medical_precision': (medical_accuracy + formatting_score) / 2
        }
    
    def _calculate_academic_quality(self, enhanced_text: str, original_text: str) -> Dict[str, float]:
        """Calculate academic content quality metrics."""
        # Citation handling
        citation_patterns = r'\*[^*]+\*|\*\*[^*]+\*\*'
        citations = len(re.findall(citation_patterns, enhanced_text))
        citation_score = min(citations / max(len(enhanced_text.split()) * 0.02, 1), 1.0)
        
        # Academic terminology
        academic_terms = ['research', 'study', 'analysis', 'theory', 'hypothesis', 'methodology']
        academic_term_count = sum(1 for term in academic_terms if term.lower() in enhanced_text.lower())
        academic_accuracy = min(academic_term_count / max(len(enhanced_text.split()) * 0.05, 1), 1.0)
        
        return {
            'citation_handling': citation_score,
            'academic_terminology': academic_accuracy,
            'academic_quality': (citation_score + academic_accuracy) / 2
        }
    
    def _calculate_legal_quality(self, enhanced_text: str, original_text: str) -> Dict[str, float]:
        """Calculate legal content quality metrics."""
        # Legal terminology precision
        legal_terms = ['contract', 'agreement', 'law', 'regulation', 'compliance', 'legal']
        legal_term_count = sum(1 for term in legal_terms if term.lower() in enhanced_text.lower())
        legal_accuracy = min(legal_term_count / max(len(enhanced_text.split()) * 0.05, 1), 1.0)
        
        # Legal formatting
        formatting_score = 0.0
        if re.search(r'\*\*[^*]+\*\*', enhanced_text):  # Bold legal terms
            formatting_score += 0.5
        if re.search(r'`[^`]+`', enhanced_text):  # Code references
            formatting_score += 0.5
        
        return {
            'legal_terminology_precision': legal_accuracy,
            'legal_formatting': formatting_score,
            'legal_quality': (legal_accuracy + formatting_score) / 2
        }
    
    def _calculate_general_quality(self, enhanced_text: str, original_text: str) -> Dict[str, float]:
        """Calculate general content quality metrics."""
        # Basic quality metrics
        length_ratio = len(enhanced_text) / max(len(original_text), 1)
        length_score = 1.0 if 0.8 <= length_ratio <= 1.3 else 0.5
        
        # Punctuation improvement
        original_punct = len(re.findall(r'[.!?]', original_text))
        enhanced_punct = len(re.findall(r'[.!?]', enhanced_text))
        punct_score = min(enhanced_punct / max(original_punct, 1), 1.0)
        
        return {
            'length_ratio': length_score,
            'punctuation_improvement': punct_score,
            'general_quality': (length_score + punct_score) / 2
        }
    
    def _calculate_confidence_score(self, quality_metrics: Dict[str, float]) -> float:
        """Calculate overall confidence score from quality metrics."""
        if not quality_metrics:
            return 0.0
        
        # Weight different quality aspects
        weights = {
            'technical_precision': 0.3,
            'medical_precision': 0.3,
            'academic_quality': 0.3,
            'legal_quality': 0.3,
            'general_quality': 0.2
        }
        
        total_score = 0.0
        total_weight = 0.0
        
        for metric, value in quality_metrics.items():
            weight = weights.get(metric, 0.1)
            total_score += value * weight
            total_weight += weight
        
        return total_score / max(total_weight, 1.0)
