"""
Nucleus Incident Operations - Phase E
=====================================
Centralized incident management for the Nucleus engine.
Handles incident artifact creation, auto-healing orchestration, and notification routing.

Part of Phase 5: Automated Incident Response.
"""

import os
import json
import logging
from pathlib import Path
from datetime import datetime, timezone
from typing import Dict, Any, List, Optional, Callable

from .common import get_brain_path
from .outbound_ops import outbound_record, outbound_fail
from .error_telemetry import StructuredError

logger = logging.getLogger("nucleus.incident")

# =============================================================================
# MODELS
# =============================================================================

class IncidentManager:
    """
    Orchestrates incident response including detection, creation, and healing.
    """
    
    def __init__(self, brain_path: Optional[Path] = None):
        self.brain_path = brain_path or get_brain_path()
        self.incidents_dir = self.brain_path / "incidents"
        self._healing_registry: Dict[str, Callable] = {}
        self._setup_incidents_dir()
        self._register_default_healers()

    def _setup_incidents_dir(self):
        """Ensure the incidents directory exists."""
        self.incidents_dir.mkdir(parents=True, exist_ok=True)

    def _register_default_healers(self):
        """Register built-in recovery actions."""
        self._healing_registry["flush_cache"] = self._healer_flush_cache
        self._healing_registry["force_sync"] = self._healer_force_sync
        self._healing_registry["restart_worker"] = self._healer_restart_worker

    # --- Healer Implementations ---

    def _healer_flush_cache(self) -> str:
        """Flushes telemetry and orchestrator caches."""
        try:
            from .telemetry_ops import _invalidate_cache
            _invalidate_cache()
            return "SUCCESS: Flushed telemetry caches."
        except Exception as e:
            return f"FAILED: {str(e)}"

    def _healer_force_sync(self) -> str:
        """Triggers a forced synchronization."""
        try:
            from .sync_ops import perform_sync
            result = perform_sync(force=True, brain_path=self.brain_path)
            return f"SUCCESS: Forced sync completed. {len(result.get('files_synced', []))} files updated."
        except Exception as e:
            return f"FAILED: {str(e)}"

    def _healer_restart_worker(self) -> str:
        """Dummy worker restart (placeholder for runtime process bounce)."""
        return "PENDING: Manual worker restart recommended."

    # --- Core API ---

    def create_incident_artifact(self, error_summary: str, details: Dict[str, Any], severity: str = "ERROR") -> Path:
        """
        Creates a markdown incident artifact in .brain/incidents/YYYY-MM/INCIDENT-<timestamp>.md
        """
        now = datetime.now(timezone.utc)
        month_dir = self.incidents_dir / now.strftime("%Y-%m")
        month_dir.mkdir(parents=True, exist_ok=True)
        
        timestamp = now.strftime("%Y%m%d-%H%M%S")
        incident_id = f"INCIDENT-{timestamp}"
        artifact_path = month_dir / f"{incident_id}.md"
        
        content = f"""# {incident_id}: {error_summary}

**Date:** {now.isoformat()}
**Severity:** {severity}
**Status:** OPEN

## Summary
{error_summary}

## Incident Context
```json
{json.dumps(details, indent=2)}
```

## Recommended Actions
- Review recent logs using `nucleus logs`.
- Check system health with `nucleus status --health`.
- Attempt auto-healing if applicable.

---
*Generated by Nucleus Automated Incident Response*
"""
        artifact_path.write_text(content)
        logger.info(f"Created incident artifact: {artifact_path}")
        return artifact_path

    def handle_alert(self, alert_data: Dict[str, Any]):
        """
        Callback for AlertManager to handle threshold breaches.
        """
        domain = alert_data.get("domain", "UNKNOWN")
        error_rate = alert_data.get("rate_per_min", 0.0)
        threshold = alert_data.get("threshold_rate", 0.0)
        
        summary = f"Threshold breached in {domain}: {error_rate:.2f}/min (Limit: {threshold:.2f}/min)"
        logger.warning(f"ALERT: {summary}")
        
        details = {
            "domain": domain,
            "error_rate": error_rate,
            "threshold": threshold,
            "triggered_at": datetime.now(timezone.utc).isoformat()
        }
        
        # 1. Create Artifact
        artifact_path = self.create_incident_artifact(summary, details, severity="CRITICAL")
        
        # 2. Notify
        self._notify_incident(summary, artifact_path)
        
        # 3. Attempt Auto-Healing (if rule exists for domain)
        if domain == "telemetry":
            self.attempt_auto_heal("flush_cache")
        elif domain == "sync":
            self.attempt_auto_heal("force_sync")

    def attempt_auto_heal(self, healer_name: str) -> str:
        """Executes a registered healing action."""
        if healer_name not in self._healing_registry:
            return f"UNKNOWN HEALER: {healer_name}"
            
        logger.info(f"Attempting auto-heal: {healer_name}")
        result = self._healing_registry[healer_name]()
        logger.info(f"Auto-heal result ({healer_name}): {result}")
        return result

    def _notify_incident(self, summary: str, artifact_path: Path):
        """Sends notifications via Telegram/Slack."""
        from .outbound_ops import outbound_fail
        
        # For now, we use a simple Telegram alert via our secrets module
        from .secrets import get_telegram_token, get_telegram_chat_id
        import urllib.request
        
        token = get_telegram_token()
        chat_id = get_telegram_chat_id()
        
        if not token or not chat_id:
            logger.debug("Telegram credentials missing, skipping incident notification.")
            return

        message = f"🚨 *Nucleus Incident Detected*\n\nSummary: `{summary}`\nArtifact: `{artifact_path.name}`\nTimestamp: `{datetime.now(timezone.utc).isoformat()}`"
        
        try:
            url = f"https://api.telegram.org/bot{token}/sendMessage"
            data = json.dumps({
                "chat_id": chat_id,
                "text": message,
                "parse_mode": "Markdown"
            }).encode()
            req = urllib.request.Request(url, data=data, method="POST")
            req.add_header("Content-Type", "application/json")
            with urllib.request.urlopen(req, timeout=10) as resp:
                if resp.status == 200:
                    logger.info("Incident notification sent via Telegram.")
                else:
                    logger.error(f"Telegram notification failed with status {resp.status}")
        except Exception as e:
            logger.error(f"Failed to send incident notification: {e}")

# Global Manager Instance
_manager: Optional[IncidentManager] = None

def get_incident_manager() -> IncidentManager:
    """Get or create singleton IncidentManager."""
    global _manager
    if _manager is None:
        _manager = IncidentManager()
    return _manager

def handle_alert(alert_data: Dict[str, Any]):
    """Facade for global manager alert handler."""
    get_incident_manager().handle_alert(alert_data)
