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

import requests
import json
from typing import Dict, Any, List
import logging

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

logger = logging.getLogger(__name__)


class SlackNotifier(BaseNotifier):
    """Slack notification system for health check alerts."""
    
    def __init__(self, config: Dict[str, Any]):
        """
        Initialize Slack notifier.
        
        Args:
            config: Slack notification configuration
        """
        super().__init__(config)
        
        self.api_key = config.get('api_key')
        self.channel = config.get('channel')
        self.webhook_url = config.get('webhook_url')  # Alternative to api_key
        
        # Default message template
        self.default_template = "🚨 Service {name} is {status}\nURL: {url}\nError: {error}\nResponse Time: {response_time}\nTimestamp: {timestamp}"
        self.message_template = config.get('message_template', self.default_template)
        
        # Slack API URLs
        self.chat_post_url = "https://slack.com/api/chat.postMessage"
    
    def validate_config(self) -> List[str]:
        """
        Validate Slack configuration.
        
        Returns:
            List of validation error messages
        """
        errors = []
        
        if not self.webhook_url and not self.api_key:
            errors.append("Either webhook_url or api_key is required")
        
        if not self.channel:
            errors.append("Slack channel is required")
        
        return errors
    
    def test_connection(self) -> bool:
        """
        Test Slack connection.
        
        Returns:
            True if connection test succeeds, False otherwise
        """
        if not self.enabled:
            return True
        
        try:
            if self.webhook_url:
                # Test webhook
                test_payload = {
                    "text": "Health Checker Slack Test",
                    "channel": self.channel
                }
                
                response = requests.post(
                    self.webhook_url,
                    json=test_payload,
                    timeout=10
                )
                
                if response.status_code == 200:
                    self.logger.info("Slack webhook test successful")
                    return True
                else:
                    self.logger.error(f"Slack webhook test failed: {response.text}")
                    return False
                    
            else:
                # Test API key
                headers = {
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json"
                }
                
                test_payload = {
                    "channel": self.channel,
                    "text": "Health Checker Slack Test"
                }
                
                response = requests.post(
                    self.chat_post_url,
                    json=test_payload,
                    headers=headers,
                    timeout=10
                )
                
                if response.status_code == 200:
                    data = response.json()
                    if data.get('ok'):
                        self.logger.info("Slack API test successful")
                        return True
                    else:
                        self.logger.error(f"Slack API test failed: {data.get('error')}")
                        return False
                else:
                    self.logger.error(f"Slack API test failed: {response.text}")
                    return False
                    
        except Exception as e:
            self.logger.error(f"Slack connection test failed: {e}")
            return False
    
    def _send_via_webhook(self, message: str) -> bool:
        """
        Send message via Slack webhook.
        
        Args:
            message: Message to send
            
        Returns:
            True if message was sent successfully
        """
        try:
            # Create rich message payload
            payload = {
                "channel": self.channel,
                "text": message,
                "username": "Health Checker",
                "icon_emoji": ":hospital:"
            }
            
            response = requests.post(
                self.webhook_url,
                json=payload,
                timeout=10
            )
            
            return response.status_code == 200
            
        except Exception as e:
            self.logger.error(f"Failed to send Slack webhook message: {e}")
            return False
    
    def _send_via_api(self, message: str) -> bool:
        """
        Send message via Slack API.
        
        Args:
            message: Message to send
            
        Returns:
            True if message was sent successfully
        """
        try:
            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            }
            
            # Create rich message payload
            payload = {
                "channel": self.channel,
                "text": message,
                "username": "Health Checker"
            }
            
            response = requests.post(
                self.chat_post_url,
                json=payload,
                headers=headers,
                timeout=10
            )
            
            if response.status_code == 200:
                data = response.json()
                return data.get('ok', False)
            else:
                self.logger.error(f"Slack API error: {response.text}")
                return False
                
        except Exception as e:
            self.logger.error(f"Failed to send Slack API message: {e}")
            return False
    
    def send_alert(self, result: HealthCheckResult) -> bool:
        """
        Send Slack alert for health check result.
        
        Args:
            result: Health check result
            
        Returns:
            True if message 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 Slack alert")
            return True
        
        try:
            # Format message
            message = self.format_message(self.message_template, result)
            
            # Determine status color and emoji
            if result.status == 'error':
                emoji = "🚨"
                color = "danger"
            else:  # unhealthy
                emoji = "⚠️"
                color = "warning"
            
            # Add visual indicators
            formatted_message = f"{emoji} *Health Check Alert*\n\n{message}"
            
            # Send based on available method
            if self.webhook_url:
                return self._send_via_webhook(formatted_message)
            else:
                return self._send_via_api(formatted_message)
                
        except Exception as e:
            self.logger.error(f"Failed to send Slack alert for {result.service_name}: {e}")
            return False
    
    def send_recovery_notification(self, result: HealthCheckResult) -> bool:
        """
        Send Slack recovery notification.
        
        Args:
            result: Health check result showing service recovery
            
        Returns:
            True if recovery message was sent successfully
        """
        if not result.is_healthy():
            return True
        
        try:
            # Format recovery message
            message = (
                f"✅ *Service Recovered*\n\n"
                f"Service: {result.service_name}\n"
                f"URL: {result.url}\n"
                f"Response Time: {result.response_time * 1000:.2f}ms\n"
                f"Timestamp: {result.timestamp.strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"Status Code: {result.status_code}"
            )
            
            # Send based on available method
            if self.webhook_url:
                return self._send_via_webhook(message)
            else:
                return self._send_via_api(message)
                
        except Exception as e:
            self.logger.error(f"Failed to send Slack recovery message for {result.service_name}: {e}")
            return False
    
    def on_service_recovery(self, result: HealthCheckResult) -> bool:
        """
        Called when a service recovers.
        
        Args:
            result: Health check result showing service is healthy
            
        Returns:
            True if recovery notification was sent successfully
        """
        return self.send_recovery_notification(result)