"""
Notification Service for Backup System
Sends rich formatted notifications to Mattermost webhook
"""

import logging
import aiohttp
from datetime import datetime
from typing import Dict, Optional, List
from app.core.config import settings
from app.core.database import execute_insert

logger = logging.getLogger(__name__)


class MattermostNotification:
    """Service for sending Mattermost webhook notifications"""
    
    def __init__(self):
        self.webhook_url = settings.MATTERMOST_WEBHOOK_URL
        self.enabled = settings.MATTERMOST_ENABLED
        self.channel = settings.MATTERMOST_CHANNEL
    
    async def send_backup_success(self, job_id: int, job_type: str, file_size_bytes: int, 
                                   duration_seconds: float, checksum: str, is_monthly: bool = False):
        """
        Send success notification for completed backup
        
        Args:
            job_id: Backup job ID
            job_type: database, files, or full
            file_size_bytes: Size of backup file
            duration_seconds: Time taken to complete backup
            checksum: SHA256 checksum of backup
            is_monthly: Whether this is a monthly backup
        """
        if not self._should_send_notification('backup_success'):
            return
        
        file_size_mb = file_size_bytes / 1024 / 1024
        
        payload = {
            "channel": self.channel,
            "username": "BMC Hub Backup",
            "icon_emoji": ":white_check_mark:",
            "text": f"✅ **Backup Complete** - {job_type.capitalize()}",
            "attachments": [{
                "color": "#36a64f",  # Green
                "fields": [
                    {
                        "short": True,
                        "title": "Job ID",
                        "value": f"#{job_id}"
                    },
                    {
                        "short": True,
                        "title": "Type",
                        "value": f"{job_type.capitalize()} {'(Monthly)' if is_monthly else '(Daily)'}"
                    },
                    {
                        "short": True,
                        "title": "Size",
                        "value": f"{file_size_mb:.2f} MB"
                    },
                    {
                        "short": True,
                        "title": "Duration",
                        "value": f"{duration_seconds:.1f}s"
                    },
                    {
                        "short": False,
                        "title": "Checksum (SHA256)",
                        "value": f"`{checksum[:16]}...{checksum[-16:]}`"
                    }
                ],
                "footer": "BMC Hub Backup System",
                "footer_icon": "https://platform.slack-edge.com/img/default_application_icon.png",
                "ts": int(datetime.now().timestamp())
            }]
        }
        
        await self._send_webhook(payload, 'backup_success', job_id)
    
    async def send_backup_failed(self, job_id: int, job_type: str, error_message: str):
        """
        Send failure notification for failed backup
        
        Args:
            job_id: Backup job ID
            job_type: database, files, or full
            error_message: Error message from failed backup
        """
        if not self._should_send_notification('backup_failed'):
            return
        
        payload = {
            "channel": self.channel,
            "username": "BMC Hub Backup",
            "icon_emoji": ":x:",
            "text": f"❌ **Backup Failed** - {job_type.capitalize()}",
            "attachments": [{
                "color": "#ff0000",  # Red
                "fields": [
                    {
                        "short": True,
                        "title": "Job ID",
                        "value": f"#{job_id}"
                    },
                    {
                        "short": True,
                        "title": "Type",
                        "value": job_type.capitalize()
                    },
                    {
                        "short": False,
                        "title": "Error",
                        "value": f"```{error_message[:500]}```"
                    }
                ],
                "actions": [
                    {
                        "name": "view_dashboard",
                        "type": "button",
                        "text": "View Dashboard",
                        "url": f"{self._get_hub_url()}/backups"
                    }
                ],
                "footer": "BMC Hub Backup System",
                "ts": int(datetime.now().timestamp())
            }]
        }
        
        await self._send_webhook(payload, 'backup_failed', job_id)
    
    async def send_offsite_success(self, job_id: int, backup_name: str, file_size_bytes: int):
        """
        Send notification for successful offsite upload
        
        Args:
            job_id: Backup job ID
            backup_name: Name of uploaded backup file
            file_size_bytes: Size of uploaded file
        """
        if not settings.NOTIFY_ON_SUCCESS_OFFSITE:
            return
        
        file_size_mb = file_size_bytes / 1024 / 1024
        
        payload = {
            "channel": self.channel,
            "username": "BMC Hub Backup",
            "icon_emoji": ":cloud:",
            "text": f"☁️ **Offsite Upload Complete**",
            "attachments": [{
                "color": "#0066cc",  # Blue
                "fields": [
                    {
                        "short": True,
                        "title": "Job ID",
                        "value": f"#{job_id}"
                    },
                    {
                        "short": True,
                        "title": "Destination",
                        "value": f"{settings.SFTP_HOST}:{settings.SFTP_REMOTE_PATH}"
                    },
                    {
                        "short": True,
                        "title": "Filename",
                        "value": backup_name
                    },
                    {
                        "short": True,
                        "title": "Size",
                        "value": f"{file_size_mb:.2f} MB"
                    }
                ],
                "footer": "BMC Hub Backup System",
                "ts": int(datetime.now().timestamp())
            }]
        }
        
        await self._send_webhook(payload, 'backup_success', job_id)
    
    async def send_offsite_failed(self, job_id: int, backup_name: str, error_message: str, 
                                   retry_count: int):
        """
        Send notification for failed offsite upload
        
        Args:
            job_id: Backup job ID
            backup_name: Name of backup file
            error_message: Error message
            retry_count: Current retry attempt number
        """
        if not self._should_send_notification('offsite_failed'):
            return
        
        max_retries = settings.OFFSITE_RETRY_MAX_ATTEMPTS
        
        payload = {
            "channel": self.channel,
            "username": "BMC Hub Backup",
            "icon_emoji": ":warning:",
            "text": f"⚠️ **Offsite Upload Failed** (Retry {retry_count}/{max_retries})",
            "attachments": [{
                "color": "#ff9900",  # Orange
                "fields": [
                    {
                        "short": True,
                        "title": "Job ID",
                        "value": f"#{job_id}"
                    },
                    {
                        "short": True,
                        "title": "Destination",
                        "value": f"{settings.SFTP_HOST}:{settings.SFTP_REMOTE_PATH}"
                    },
                    {
                        "short": True,
                        "title": "Filename",
                        "value": backup_name
                    },
                    {
                        "short": True,
                        "title": "Retry Status",
                        "value": f"{retry_count}/{max_retries}"
                    },
                    {
                        "short": False,
                        "title": "Error",
                        "value": f"```{error_message[:300]}```"
                    }
                ],
                "footer": "BMC Hub Backup System",
                "ts": int(datetime.now().timestamp())
            }]
        }
        
        await self._send_webhook(payload, 'offsite_failed', job_id)
    
    async def send_storage_warning(self, usage_pct: float, used_gb: float, max_gb: int):
        """
        Send notification for high storage usage
        
        Args:
            usage_pct: Percentage of storage used
            used_gb: Gigabytes used
            max_gb: Maximum storage capacity
        """
        if not self._should_send_notification('storage_low'):
            return
        
        payload = {
            "channel": self.channel,
            "username": "BMC Hub Backup",
            "icon_emoji": ":warning:",
            "text": f"⚠️ **Backup Storage Warning**",
            "attachments": [{
                "color": "#ff9900",  # Orange
                "fields": [
                    {
                        "short": True,
                        "title": "Usage",
                        "value": f"{usage_pct:.1f}%"
                    },
                    {
                        "short": True,
                        "title": "Space Used",
                        "value": f"{used_gb:.2f} GB / {max_gb} GB"
                    },
                    {
                        "short": False,
                        "title": "Recommendation",
                        "value": "Consider running backup rotation or increasing storage capacity."
                    }
                ],
                "actions": [
                    {
                        "name": "view_dashboard",
                        "type": "button",
                        "text": "View Dashboard",
                        "url": f"{self._get_hub_url()}/backups"
                    }
                ],
                "footer": "BMC Hub Backup System",
                "ts": int(datetime.now().timestamp())
            }]
        }
        
        await self._send_webhook(payload, 'storage_low')
    
    async def send_restore_started(self, job_id: int, backup_name: str, eta_minutes: int):
        """
        Send notification when restore operation starts
        
        Args:
            job_id: Backup job ID being restored
            backup_name: Name of backup file
            eta_minutes: Estimated time to completion
        """
        payload = {
            "channel": self.channel,
            "username": "BMC Hub Backup",
            "icon_emoji": ":gear:",
            "text": f"🔧 **System Maintenance: Restore in Progress**",
            "attachments": [{
                "color": "#ffcc00",  # Yellow
                "fields": [
                    {
                        "short": True,
                        "title": "Backup Job ID",
                        "value": f"#{job_id}"
                    },
                    {
                        "short": True,
                        "title": "ETA",
                        "value": f"{eta_minutes} minutes"
                    },
                    {
                        "short": False,
                        "title": "Backup File",
                        "value": backup_name
                    },
                    {
                        "short": False,
                        "title": "Status",
                        "value": "System is in maintenance mode. All services temporarily unavailable."
                    }
                ],
                "footer": "BMC Hub Backup System",
                "ts": int(datetime.now().timestamp())
            }]
        }
        
        await self._send_webhook(payload, 'restore_started', job_id)
    
    async def _send_webhook(self, payload: Dict, event_type: str, job_id: Optional[int] = None):
        """
        Send webhook to Mattermost and log notification
        
        Args:
            payload: Mattermost webhook payload
            event_type: Type of notification event
            job_id: Optional backup job ID
        """
        if not self.enabled or not self.webhook_url:
            logger.info("📢 Notification (disabled): %s - job_id=%s", event_type, job_id)
            return
        
        try:
            async with aiohttp.ClientSession() as session:
                async with session.post(self.webhook_url, json=payload, timeout=10) as response:
                    if response.status == 200:
                        logger.info("📢 Notification sent: %s - job_id=%s", event_type, job_id)
                        
                        # Log to database
                        execute_insert(
                            """INSERT INTO backup_notifications 
                               (backup_job_id, event_type, message, mattermost_payload)
                               VALUES (%s, %s, %s, %s)""",
                            (job_id, event_type, payload.get('text', ''), str(payload))
                        )
                    else:
                        error_text = await response.text()
                        logger.error("❌ Notification failed: HTTP %s - %s", 
                                   response.status, error_text)
        
        except aiohttp.ClientError as e:
            logger.error("❌ Notification connection error: %s", str(e))
        except Exception as e:
            logger.error("❌ Notification error: %s", str(e))
    
    def _should_send_notification(self, event_type: str) -> bool:
        """Check if notification should be sent based on settings"""
        if not self.enabled or not self.webhook_url:
            return False
        
        if event_type in ['backup_failed', 'offsite_failed', 'storage_low']:
            return settings.NOTIFY_ON_FAILURE
        
        if event_type == 'backup_success' and 'offsite' in event_type:
            return settings.NOTIFY_ON_SUCCESS_OFFSITE
        
        return True
    
    def _get_hub_url(self) -> str:
        """Get BMC Hub base URL for action buttons"""
        # TODO: Add HUB_BASE_URL to config
        return "http://localhost:8000"  # Fallback


# Singleton instance
notifications = MattermostNotification()
