"""
Email notification system for health check alerts.
"""

import smtplib
import ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import formatdate
from typing import Dict, Any, List, Optional
import logging

from .base import BaseNotifier
from ..core.checker import HealthCheckResult

logger = logging.getLogger(__name__)


class EmailNotifier(BaseNotifier):
    """Email notification system for health check alerts."""
    
    def __init__(self, config: Dict[str, Any]):
        """
        Initialize email notifier.
        
        Args:
            config: Email notification configuration
        """
        super().__init__(config)
        
        self.smtp_server = config.get('smtp_server')
        self.smtp_port = config.get('smtp_port', 587)
        self.username = config.get('username')
        self.app_password = config.get('app_password')
        self.recipients = config.get('recipients', [])
        
        # Default email template
        self.default_subject_template = "🚨 Health Check Alert: {name} is {status}"
        self.default_body_template = """
Service Health Check Alert

Service Name: {name}
URL: {url}
Status: {status}
Error: {error}
Response Time: {response_time}
Timestamp: {timestamp}
Status Code: {status_code}

Please investigate the issue immediately.

---
Health Checker Monitoring System
        """.strip()
        
        self.subject_template = config.get('subject_template', self.default_subject_template)
        self.body_template = config.get('body_template', self.default_body_template)
    
    def validate_config(self) -> List[str]:
        """
        Validate email configuration.
        
        Returns:
            List of validation error messages
        """
        errors = []
        
        if not self.smtp_server:
            errors.append("SMTP server is required")
        
        if not self.smtp_port or not (1 <= self.smtp_port <= 65535):
            errors.append("Valid SMTP port is required (1-65535)")
        
        if not self.username:
            errors.append("SMTP username is required")
        
        if not self.app_password:
            errors.append("SMTP app password is required")
        
        if not self.recipients:
            errors.append("At least one recipient is required")
        
        # Validate email format for recipients
        import re
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        
        for recipient in self.recipients:
            if not re.match(email_pattern, recipient):
                errors.append(f"Invalid email format: {recipient}")
        
        return errors
    
    def test_connection(self, service_name: Optional[str] = None) -> bool:
        """
        Test email server connection.
        
        Args:
            service_name: Optional name of the service for identification in test messages
            
        Returns:
            True if connection test succeeds, False otherwise
        """
        if not self.enabled:
            return True
        
        try:
            # Format test subject with service name if provided
            test_subject = "Health Checker Email Test"
            if service_name:
                test_subject = f"Health Checker Email Test - Service: {service_name}"
            
            # Create test email
            test_msg = MIMEMultipart()
            test_msg['From'] = self.username
            test_msg['To'] = ', '.join(self.recipients)
            test_msg['Date'] = formatdate(localtime=True)
            test_msg['Subject'] = test_subject
            
            test_msg.attach(MIMEText("This is a test email from Health Checker.", 'plain'))
            
            # Send test email
            context = ssl.create_default_context()
            with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
                server.starttls(context=context)
                server.login(self.username, self.app_password)
                server.send_message(test_msg)
            
            self.logger.info("Email connection test successful")
            return True
            
        except Exception as e:
            self.logger.error(f"Email connection test failed: {e}")
            return False
    
    def send_alert(self, result: HealthCheckResult) -> bool:
        """
        Send email alert for health check result.
        
        Args:
            result: Health check result
            
        Returns:
            True if email was sent successfully, False otherwise
        """
        if not result.status in ['unhealthy', 'error']:
            self.logger.debug(f"Service {result.service_name} is {result.status}, not sending email alert")
            return True
        
        try:
            # Create message
            msg = MIMEMultipart()
            msg['From'] = self.username
            msg['To'] = ', '.join(self.recipients)
            msg['Date'] = formatdate(localtime=True)
            
            # Format subject and body
            subject = self.format_message(self.subject_template, result)
            body = self.format_message(self.body_template, result)
            
            msg['Subject'] = subject
            msg.attach(MIMEText(body, 'plain'))
            
            # Send email
            context = ssl.create_default_context()
            with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
                server.starttls(context=context)
                server.login(self.username, self.app_password)
                server.send_message(msg)
            
            self.logger.info(f"Email alert sent for {result.service_name} to {len(self.recipients)} recipients")
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to send email alert for {result.service_name}: {e}")
            return False
    
    def send_recovery_notification(self, result: HealthCheckResult) -> bool:
        """
        Send email recovery notification.
        
        Args:
            result: Health check result showing service recovery
            
        Returns:
            True if recovery email was sent successfully
        """
        if not result.is_healthy():
            return True
        
        try:
            # Create recovery message
            msg = MIMEMultipart()
            msg['From'] = self.username
            msg['To'] = ', '.join(self.recipients)
            msg['Date'] = formatdate(localtime=True)
            
            # Recovery subject and body
            subject = f"✅ Service Recovered: {result.service_name}"
            body = f"""
Service {result.service_name} has recovered and is now healthy.

URL: {url}
Response Time: {result.response_time * 1000:.2f}ms
Timestamp: {result.timestamp.strftime('%Y-%m-%d %H:%M:%S')}
Status Code: {result.status_code}

The service is back to normal operation.

---
Health Checker Monitoring System
            """.strip().format(name=result.service_name, url=result.url, 
                              response_time=result.response_time * 1000,
                              timestamp=result.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                              status_code=result.status_code)
            
            msg['Subject'] = subject
            msg.attach(MIMEText(body, 'plain'))
            
            # Send email
            context = ssl.create_default_context()
            with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
                server.starttls(context=context)
                server.login(self.username, self.app_password)
                server.send_message(msg)
            
            self.logger.info(f"Recovery email sent for {result.service_name}")
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to send recovery email for {result.service_name}: {e}")
            return False