"""
SEO Analysis Service
Handles storing and retrieving SEO analysis data from the database.
"""

from typing import Optional, List, Dict, Any
from datetime import datetime
from sqlalchemy.orm import Session
from sqlalchemy import func
from loguru import logger

from models.seo_analysis import (
    SEOAnalysis,
    SEOIssue,
    SEOWarning,
    SEORecommendation,
    SEOCategoryScore,
    SEOAnalysisHistory,
    create_analysis_from_result,
    create_issues_from_result,
    create_warnings_from_result,
    create_recommendations_from_result,
    create_category_scores_from_result
)
from .core import SEOAnalysisResult

class SEOAnalysisService:
    """Service for managing SEO analysis data in the database."""
    
    def __init__(self, db_session: Session):
        self.db = db_session
    
    def store_analysis_result(self, result: SEOAnalysisResult) -> Optional[SEOAnalysis]:
        """
        Store SEO analysis result in the database.
        
        Args:
            result: SEOAnalysisResult from the analyzer
            
        Returns:
            Stored SEOAnalysis record or None if failed
        """
        try:
            # Create main analysis record
            analysis_record = create_analysis_from_result(result)
            self.db.add(analysis_record)
            self.db.flush()  # Get the ID
            
            # Create related records
            issues = create_issues_from_result(analysis_record.id, result)
            warnings = create_warnings_from_result(analysis_record.id, result)
            recommendations = create_recommendations_from_result(analysis_record.id, result)
            category_scores = create_category_scores_from_result(analysis_record.id, result)
            
            # Add all related records
            for issue in issues:
                self.db.add(issue)
            for warning in warnings:
                self.db.add(warning)
            for recommendation in recommendations:
                self.db.add(recommendation)
            for score in category_scores:
                self.db.add(score)
            
            # Create history record
            history_record = SEOAnalysisHistory(
                url=result.url,
                analysis_date=result.timestamp,
                overall_score=result.overall_score,
                health_status=result.health_status,
                score_change=0,  # Will be calculated later
                critical_issues_count=len(result.critical_issues),
                warnings_count=len(result.warnings),
                recommendations_count=len(result.recommendations)
            )
            
            # Add category scores to history
            for category, data in result.data.items():
                if isinstance(data, dict) and 'score' in data:
                    if category == 'url_structure':
                        history_record.url_structure_score = data['score']
                    elif category == 'meta_data':
                        history_record.meta_data_score = data['score']
                    elif category == 'content_analysis':
                        history_record.content_score = data['score']
                    elif category == 'technical_seo':
                        history_record.technical_score = data['score']
                    elif category == 'performance':
                        history_record.performance_score = data['score']
                    elif category == 'accessibility':
                        history_record.accessibility_score = data['score']
                    elif category == 'user_experience':
                        history_record.user_experience_score = data['score']
                    elif category == 'security_headers':
                        history_record.security_score = data['score']
            
            self.db.add(history_record)
            self.db.commit()
            
            logger.info(f"Stored SEO analysis for {result.url} with score {result.overall_score}")
            return analysis_record
            
        except Exception as e:
            logger.error(f"Error storing SEO analysis: {str(e)}")
            self.db.rollback()
            return None
    
    def get_latest_analysis(self, url: str) -> Optional[SEOAnalysis]:
        """
        Get the latest SEO analysis for a URL.
        
        Args:
            url: The URL to get analysis for
            
        Returns:
            Latest SEOAnalysis record or None
        """
        try:
            return self.db.query(SEOAnalysis).filter(
                SEOAnalysis.url == url
            ).order_by(SEOAnalysis.timestamp.desc()).first()
        except Exception as e:
            logger.error(f"Error getting latest analysis for {url}: {str(e)}")
            return None
    
    def get_analysis_history(self, url: str, limit: int = 10) -> List[SEOAnalysisHistory]:
        """
        Get analysis history for a URL.
        
        Args:
            url: The URL to get history for
            limit: Maximum number of records to return
            
        Returns:
            List of SEOAnalysisHistory records
        """
        try:
            return self.db.query(SEOAnalysisHistory).filter(
                SEOAnalysisHistory.url == url
            ).order_by(SEOAnalysisHistory.analysis_date.desc()).limit(limit).all()
        except Exception as e:
            logger.error(f"Error getting analysis history for {url}: {str(e)}")
            return []
    
    def get_analysis_by_id(self, analysis_id: int) -> Optional[SEOAnalysis]:
        """
        Get SEO analysis by ID.
        
        Args:
            analysis_id: The analysis ID
            
        Returns:
            SEOAnalysis record or None
        """
        try:
            return self.db.query(SEOAnalysis).filter(
                SEOAnalysis.id == analysis_id
            ).first()
        except Exception as e:
            logger.error(f"Error getting analysis by ID {analysis_id}: {str(e)}")
            return None
    
    def get_all_analyses(self, limit: int = 50) -> List[SEOAnalysis]:
        """
        Get all SEO analyses with pagination.
        
        Args:
            limit: Maximum number of records to return
            
        Returns:
            List of SEOAnalysis records
        """
        try:
            return self.db.query(SEOAnalysis).order_by(
                SEOAnalysis.timestamp.desc()
            ).limit(limit).all()
        except Exception as e:
            logger.error(f"Error getting all analyses: {str(e)}")
            return []
    
    def delete_analysis(self, analysis_id: int) -> bool:
        """
        Delete an SEO analysis.
        
        Args:
            analysis_id: The analysis ID to delete
            
        Returns:
            True if successful, False otherwise
        """
        try:
            analysis = self.db.query(SEOAnalysis).filter(
                SEOAnalysis.id == analysis_id
            ).first()
            
            if analysis:
                self.db.delete(analysis)
                self.db.commit()
                logger.info(f"Deleted SEO analysis {analysis_id}")
                return True
            else:
                logger.warning(f"Analysis {analysis_id} not found for deletion")
                return False
                
        except Exception as e:
            logger.error(f"Error deleting analysis {analysis_id}: {str(e)}")
            self.db.rollback()
            return False
    
    def get_analysis_statistics(self) -> Dict[str, Any]:
        """
        Get overall statistics for SEO analyses.
        
        Returns:
            Dictionary with analysis statistics
        """
        try:
            total_analyses = self.db.query(SEOAnalysis).count()
            total_urls = self.db.query(SEOAnalysis.url).distinct().count()
            
            # Get average scores by health status
            excellent_count = self.db.query(SEOAnalysis).filter(
                SEOAnalysis.health_status == 'excellent'
            ).count()
            
            good_count = self.db.query(SEOAnalysis).filter(
                SEOAnalysis.health_status == 'good'
            ).count()
            
            needs_improvement_count = self.db.query(SEOAnalysis).filter(
                SEOAnalysis.health_status == 'needs_improvement'
            ).count()
            
            poor_count = self.db.query(SEOAnalysis).filter(
                SEOAnalysis.health_status == 'poor'
            ).count()
            
            # Calculate average overall score
            avg_score_result = self.db.query(
                func.avg(SEOAnalysis.overall_score)
            ).scalar()
            avg_score = float(avg_score_result) if avg_score_result else 0
            
            return {
                'total_analyses': total_analyses,
                'total_urls': total_urls,
                'average_score': round(avg_score, 2),
                'health_distribution': {
                    'excellent': excellent_count,
                    'good': good_count,
                    'needs_improvement': needs_improvement_count,
                    'poor': poor_count
                }
            }
            
        except Exception as e:
            logger.error(f"Error getting analysis statistics: {str(e)}")
            return {
                'total_analyses': 0,
                'total_urls': 0,
                'average_score': 0,
                'health_distribution': {
                    'excellent': 0,
                    'good': 0,
                    'needs_improvement': 0,
                    'poor': 0
                }
            } 