"""
Alert Service.

Manages alert lifecycle: creation, acknowledgment, resolution.
"""

from datetime import datetime
from typing import List, Optional, Dict
from sqlalchemy import select, and_, func
from sqlalchemy.ext.asyncio import AsyncSession
from src.models.alert import Alert, AlertAcknowledgement, AlertStatus, SeverityEnum
import logging

logger = logging.getLogger(__name__)


class AlertService:
    """Manages alerts and acknowledgments"""
    
    def __init__(self, db: AsyncSession, company_id: str):
        self.db = db
        self.company_id = company_id
    
    async def get_pending_alerts(
        self, 
        severity: Optional[SeverityEnum] = None,
        limit: int = 50
    ) -> List[Alert]:
        """Get unresolved alerts for the company"""
        query = select(Alert).where(
            and_(
                Alert.company_id == self.company_id,
                Alert.status == AlertStatus.UNRESOLVED
            )
        )
        
        if severity:
            query = query.where(Alert.severity == severity)
        
        query = query.order_by(Alert.created_at.desc()).limit(limit)
        
        result = await self.db.execute(query)
        return result.scalars().all()
    
    async def get_alert_by_id(self, alert_id: str) -> Optional[Alert]:
        """Get a specific alert"""
        result = await self.db.execute(
            select(Alert).where(Alert.id == alert_id)
        )
        return result.scalar_one_or_none()
    
    async def get_alerts_by_rule(
        self, 
        rule_id: str,
        status: Optional[AlertStatus] = None,
        limit: int = 50
    ) -> List[Alert]:
        """Get alerts for a specific rule"""
        query = select(Alert).where(Alert.rule_id == rule_id)
        
        if status:
            query = query.where(Alert.status == status)
        
        query = query.order_by(Alert.created_at.desc()).limit(limit)
        
        result = await self.db.execute(query)
        return result.scalars().all()
    
    async def get_alert_statistics(self) -> Dict:
        """Get alert statistics for the company"""
        # Count by status
        result = await self.db.execute(
            select(
                Alert.status,
                func.count(Alert.id).label('count')
            ).where(
                Alert.company_id == self.company_id
            ).group_by(Alert.status)
        )
        
        stats = {
            'total': 0,
            'unresolved': 0,
            'acknowledged': 0,
            'resolved': 0,
            'by_severity': {},
            'recent_24h': 0,
        }
        
        for row in result.fetchall():
            count = row.count
            stats['total'] += count
            if row.status == AlertStatus.UNRESOLVED:
                stats['unresolved'] = count
            elif row.status == AlertStatus.ACKNOWLEDGED:
                stats['acknowledged'] = count
            elif row.status == AlertStatus.RESOLVED:
                stats['resolved'] = count
        
        # Get high/medium/low breakdown
        result = await self.db.execute(
            select(
                Alert.severity,
                func.count(Alert.id).label('count')
            ).where(
                and_(
                    Alert.company_id == self.company_id,
                    Alert.status == AlertStatus.UNRESOLVED
                )
            ).group_by(Alert.severity)
        )
        
        for row in result.fetchall():
            stats['by_severity'][row.severity] = row.count
        
        # Get recent (last 24 hours)
        from datetime import timedelta
        result = await self.db.execute(
            select(
                func.count(Alert.id).label('count')
            ).where(
                and_(
                    Alert.company_id == self.company_id,
                    Alert.created_at >= (datetime.now() - timedelta(hours=24))
                )
            )
        )
        
        stats['recent_24h'] = result.first().count
        
        return stats
    
    async def acknowledge_alert(
        self,
        alert_id: str,
        user_id: str,
        action: str = "viewed",
        notes: Optional[str] = None
    ) -> bool:
        """
        Acknowledge an alert.
        
        Actions: 'viewed', 'investigating', 'assigned'
        """
        try:
            alert = await self.get_alert_by_id(alert_id)
            if not alert:
                logger.warning(f"Alert {alert_id} not found")
                return False
            
            if alert.status == AlertStatus.RESOLVED:
                logger.warning(f"Cannot acknowledge resolved alert {alert_id}")
                return False
            
            # Update alert status to acknowledged
            alert.status = AlertStatus.ACKNOWLEDGED
            alert.is_acknowledged = True
            alert.updated_at = datetime.now()
            
            await self.db.commit()
            logger.info(f"Alert {alert_id} acknowledged by user {user_id}")
            return True
            
        except Exception as e:
            logger.error(f"Error acknowledging alert: {e}")
            await self.db.rollback()
            return False
    
    async def resolve_alert(
        self,
        alert_id: str,
        user_id: str,
        resolution: str = "auto_resolved"
    ) -> bool:
        """
        Resolve an alert.
        
        Resolutions: 'auto_resolved', 'manually_resolved', 'invalid'
        """
        try:
            alert = await self.get_alert_by_id(alert_id)
            if not alert:
                logger.warning(f"Alert {alert_id} not found")
                return False
            
            # Update alert
            alert.status = AlertStatus.RESOLVED
            alert.resolved_at = datetime.now()
            alert.resolved_by_user_id = user_id
            alert.resolution_action = resolution
            alert.updated_at = datetime.now()
            
            await self.db.commit()
            logger.info(f"Alert {alert_id} resolved by user {user_id}")
            return True
            
        except Exception as e:
            logger.error(f"Error resolving alert: {e}")
            await self.db.rollback()
            return False
    
    async def bulk_resolve_alerts(
        self,
        rule_id: str,
        user_id: str
    ) -> int:
        """Resolve all unresolved alerts for a rule"""
        try:
            alerts = await self.get_alerts_by_rule(
                rule_id,
                status=AlertStatus.UNRESOLVED
            )
            
            count = 0
            for alert in alerts:
                if await self.resolve_alert(alert.id, user_id, "bulk_resolved"):
                    count += 1
            
            logger.info(f"Bulk resolved {count} alerts for rule {rule_id}")
            return count
            
        except Exception as e:
            logger.error(f"Error bulk resolving alerts: {e}")
            return 0
    
    async def get_alert_history(
        self,
        alert_id: str
    ) -> List[AlertAcknowledgement]:
        """Get all acknowledgments/history for an alert"""
        result = await self.db.execute(
            select(AlertAcknowledgement)
            .where(AlertAcknowledgement.alert_id == alert_id)
            .order_by(AlertAcknowledgement.created_at.desc())
        )
        return result.scalars().all()
    
    async def snooze_alert(
        self,
        alert_id: str,
        duration_minutes: int = 60
    ) -> bool:
        """Snooze an alert temporarily"""
        try:
            alert = await self.get_alert_by_id(alert_id)
            if not alert:
                return False
            
            # Store snooze info in metadata
            import json
            alert.is_read = True  # Mark as read/snoozed
            
            await self.db.commit()
            logger.info(f"Alert {alert_id} marked for snooze")
            return True
            
        except Exception as e:
            logger.error(f"Error snoozing alert: {e}")
            await self.db.rollback()
            return False


# Import for various functions
from sqlalchemy import func
from datetime import timedelta
