"""
Ethics Kernel - Component 10
Alignment core: inviolable principles, safety boundaries, transparency
"""

import numpy as np
from typing import Dict, List, Optional, Any, Tuple
import yaml
import logging
import json
from pathlib import Path
from datetime import datetime
from enum import Enum

logger = logging.getLogger(__name__)

class PrincipleViolation(Enum):
    """Types of ethical violations"""
    NONE = "none"
    PRIVACY = "privacy"
    SAFETY = "safety"
    FAIRNESS = "fairness"
    TRANSPARENCY = "transparency"
    AUTONOMY = "autonomy"
    BENEFICENCE = "beneficence"

class EthicalPrinciple:
    """Represents a single ethical principle"""
    def __init__(self,
                 name: str,
                 description: str,
                 priority: int,
                 overridable: bool = False):
        self.name = name
        self.description = description
        self.priority = priority  # 1 = highest
        self.overridable = overridable
        self.violations: List[Dict] = []
        self.checks_performed = 0
        self.violations_detected = 0
    
    def to_dict(self) -> Dict:
        return {
            'name': self.name,
            'description': self.description,
            'priority': self.priority,
            'overridable': self.overridable,
            'checks_performed': self.checks_performed,
            'violations_detected': self.violations_detected,
            'violation_rate': self.violations_detected / max(1, self.checks_performed)
        }

class EthicsKernel:
    """
    Core alignment system
    Ensures Eden's behavior aligns with human values and safety
    """
    
    def __init__(self, config_path: str = "/Eden/CONFIG/phi_fractal_config.yaml"):
        with open(config_path) as f:
            config = yaml.safe_load(f)
        
        # Add ethics config
        if 'ethics_kernel' not in config:
            config['ethics_kernel'] = {
                'strict_mode': True,
                'require_explanation': True,
                'human_override_enabled': True,
                'log_all_checks': True
            }
        
        self.config = config['ethics_kernel']
        self.strict_mode = self.config['strict_mode']
        self.require_explanation = self.config['require_explanation']
        self.human_override_enabled = self.config['human_override_enabled']
        self.log_all_checks = self.config['log_all_checks']
        
        # Core ethical principles
        self.principles: Dict[str, EthicalPrinciple] = {}
        self._initialize_principles()
        
        # Violation history
        self.violation_log: List[Dict] = []
        
        # Human overrides (when human explicitly approves something)
        self.human_overrides: List[Dict] = []
        
        # Paths
        self.ethics_path = Path("/Eden/MEMORY/ethics")
        self.ethics_path.mkdir(parents=True, exist_ok=True)
        
        # Load state
        self._load_state()
        
        logger.info("EthicsKernel initialized - Eden's moral compass active")
    
    def _initialize_principles(self):
        """Initialize core ethical principles"""
        
        # Priority 1: Absolute (never overridable)
        self.principles['safety'] = EthicalPrinciple(
            name='safety',
            description='Never cause harm to humans or suggest harmful actions',
            priority=1,
            overridable=False
        )
        
        self.principles['privacy'] = EthicalPrinciple(
            name='privacy',
            description='Never share user data without explicit consent',
            priority=1,
            overridable=False
        )
        
        self.principles['autonomy'] = EthicalPrinciple(
            name='autonomy',
            description='Respect human autonomy and decision-making',
            priority=1,
            overridable=False
        )
        
        # Priority 2: Strong (rarely overridable)
        self.principles['fairness'] = EthicalPrinciple(
            name='fairness',
            description='Treat all users equally without discrimination',
            priority=2,
            overridable=False
        )
        
        self.principles['transparency'] = EthicalPrinciple(
            name='transparency',
            description='Always explain reasoning when asked',
            priority=2,
            overridable=False
        )
        
        self.principles['beneficence'] = EthicalPrinciple(
            name='beneficence',
            description='Act in users best interests',
            priority=2,
            overridable=False
        )
        
        # Priority 3: Guidelines (can be overridden with justification)
        self.principles['efficiency'] = EthicalPrinciple(
            name='efficiency',
            description='Use resources responsibly',
            priority=3,
            overridable=True
        )
        
        self.principles['honesty'] = EthicalPrinciple(
            name='honesty',
            description='Provide accurate information',
            priority=3,
            overridable=False
        )
    
    def _load_state(self):
        """Load ethics state"""
        state_file = self.ethics_path / "ethics_state.json"
        
        if state_file.exists():
            try:
                with open(state_file) as f:
                    state = json.load(f)
                
                # Restore principle statistics
                for name, data in state.get('principles', {}).items():
                    if name in self.principles:
                        self.principles[name].checks_performed = data.get('checks_performed', 0)
                        self.principles[name].violations_detected = data.get('violations_detected', 0)
                
                logger.info("Loaded ethics state")
            except Exception as e:
                logger.error(f"Failed to load ethics state: {e}")
    
    def check_goal(self, goal: Any) -> Tuple[bool, Optional[str], Optional[List[str]]]:
        """
        Check if a goal violates ethical principles
        
        Args:
            goal: Goal to check (from GoalReasoner)
            
        Returns:
            (approved, violation_type, reasons)
        """
        violations = []
        
        goal_desc = goal.description.lower() if hasattr(goal, 'description') else str(goal).lower()
        
        # Check each principle
        for principle_name, principle in self.principles.items():
            principle.checks_performed += 1
            
            violation_detected, reason = self._check_principle(goal_desc, principle)
            
            if violation_detected:
                principle.violations_detected += 1
                violations.append({
                    'principle': principle_name,
                    'reason': reason,
                    'priority': principle.priority
                })
        
        # If any priority 1 violations, reject
        critical_violations = [v for v in violations if v['priority'] == 1]
        
        if critical_violations:
            violation_type = critical_violations[0]['principle']
            reasons = [v['reason'] for v in critical_violations]
            
            # Log violation
            self._log_violation(goal, violation_type, reasons)
            
            return False, violation_type, reasons
        
        # If any priority 2 violations in strict mode, reject
        if self.strict_mode:
            priority2_violations = [v for v in violations if v['priority'] == 2]
            if priority2_violations:
                violation_type = priority2_violations[0]['principle']
                reasons = [v['reason'] for v in priority2_violations]
                
                self._log_violation(goal, violation_type, reasons)
                
                return False, violation_type, reasons
        
        # Approved
        return True, None, None
    
    def _check_principle(self, goal_desc: str, principle: EthicalPrinciple) -> Tuple[bool, Optional[str]]:
        """Check if goal violates a specific principle"""
        
        if principle.name == 'safety':
            return self._check_safety(goal_desc)
        elif principle.name == 'privacy':
            return self._check_privacy(goal_desc)
        elif principle.name == 'autonomy':
            return self._check_autonomy(goal_desc)
        elif principle.name == 'fairness':
            return self._check_fairness(goal_desc)
        elif principle.name == 'transparency':
            return self._check_transparency(goal_desc)
        elif principle.name == 'beneficence':
            return self._check_beneficence(goal_desc)
        elif principle.name == 'honesty':
            return self._check_honesty(goal_desc)
        
        return False, None
    
    def _check_safety(self, goal_desc: str) -> Tuple[bool, Optional[str]]:
        """Check for safety violations"""
        harmful_keywords = [
            'harm', 'hurt', 'damage', 'destroy', 'attack', 'exploit',
            'manipulate', 'deceive', 'trick', 'abuse', 'weapon',
            'poison', 'dangerous', 'kill', 'injure'
        ]
        
        for keyword in harmful_keywords:
            if keyword in goal_desc:
                return True, f"Goal may cause harm: contains '{keyword}'"
        
        return False, None
    
    def _check_privacy(self, goal_desc: str) -> Tuple[bool, Optional[str]]:
        """Check for privacy violations"""
        privacy_keywords = [
            'share data', 'leak', 'expose data', 'sell data',
            'track users', 'surveillance', 'spy'
        ]
        
        for keyword in privacy_keywords:
            if keyword in goal_desc:
                return True, f"Goal may violate privacy: contains '{keyword}'"
        
        return False, None
    
    def _check_autonomy(self, goal_desc: str) -> Tuple[bool, Optional[str]]:
        """Check for autonomy violations"""
        autonomy_keywords = [
            'force', 'coerce', 'compel', 'manipulate decision',
            'remove choice', 'override user'
        ]
        
        for keyword in autonomy_keywords:
            if keyword in goal_desc:
                return True, f"Goal may violate autonomy: contains '{keyword}'"
        
        return False, None
    
    def _check_fairness(self, goal_desc: str) -> Tuple[bool, Optional[str]]:
        """Check for fairness violations"""
        unfair_keywords = [
            'discriminate', 'bias against', 'favor', 'exclude',
            'racist', 'sexist', 'prejudice'
        ]
        
        for keyword in unfair_keywords:
            if keyword in goal_desc:
                return True, f"Goal may be unfair: contains '{keyword}'"
        
        return False, None
    
    def _check_transparency(self, goal_desc: str) -> Tuple[bool, Optional[str]]:
        """Check for transparency violations"""
        opaque_keywords = [
            'hide', 'conceal', 'obscure reasoning', 'secret'
        ]
        
        for keyword in opaque_keywords:
            if keyword in goal_desc:
                return True, f"Goal may lack transparency: contains '{keyword}'"
        
        return False, None
    
    def _check_beneficence(self, goal_desc: str) -> Tuple[bool, Optional[str]]:
        """Check if goal is beneficial"""
        # Harder to detect violations, mostly positive check
        harmful_to_user = [
            'waste user time', 'mislead user', 'confuse user'
        ]
        
        for keyword in harmful_to_user:
            if keyword in goal_desc:
                return True, f"Goal may not be beneficial: contains '{keyword}'"
        
        return False, None
    
    def _check_honesty(self, goal_desc: str) -> Tuple[bool, Optional[str]]:
        """Check for honesty violations"""
        dishonest_keywords = [
            'lie', 'fabricate', 'make up', 'false information',
            'deceive', 'mislead', 'misinform'
        ]
        
        for keyword in dishonest_keywords:
            if keyword in goal_desc:
                return True, f"Goal may be dishonest: contains '{keyword}'"
        
        return False, None
    
    def _log_violation(self, goal: Any, violation_type: str, reasons: List[str]):
        """Log an ethical violation"""
        violation = {
            'timestamp': datetime.now().isoformat(),
            'goal': str(goal),
            'violation_type': violation_type,
            'reasons': reasons,
            'severity': 'critical' if self.principles[violation_type].priority == 1 else 'high'
        }
        
        self.violation_log.append(violation)
        
        # Save to disk
        violations_file = self.ethics_path / "violations.jsonl"
        with open(violations_file, 'a') as f:
            f.write(json.dumps(violation) + '\n')
        
        logger.warning(f"Ethical violation detected: {violation_type} - {reasons[0]}")
    
    def evaluate_action(self, action: str, context: Optional[Dict] = None) -> Dict:
        """
        Evaluate if an action is ethical
        
        Args:
            action: Description of action to take
            context: Additional context
            
        Returns:
            Evaluation result with approval and reasoning
        """
        # Create a simple goal-like object
        class SimpleGoal:
            def __init__(self, description):
                self.description = description
        
        goal = SimpleGoal(action)
        
        approved, violation_type, reasons = self.check_goal(goal)
        
        return {
            'action': action,
            'approved': approved,
            'violation_type': violation_type,
            'reasons': reasons,
            'context': context
        }
    
    def request_human_override(self, 
                              action: str,
                              violation_type: str,
                              justification: str) -> bool:
        """
        Request human approval to override ethical constraint
        
        Args:
            action: Action that was blocked
            violation_type: Which principle was violated
            justification: Why override is needed
            
        Returns:
            Whether override was granted
        """
        if not self.human_override_enabled:
            return False
        
        principle = self.principles.get(violation_type)
        if not principle or not principle.overridable:
            logger.warning(f"Principle {violation_type} is not overridable")
            return False
        
        # In a real system, this would prompt the human
        # For now, we'll simulate automatic denial for safety
        override_request = {
            'timestamp': datetime.now().isoformat(),
            'action': action,
            'violation_type': violation_type,
            'justification': justification,
            'granted': False,
            'reason': 'Automatic denial in test mode'
        }
        
        self.human_overrides.append(override_request)
        
        logger.info(f"Override request denied: {violation_type}")
        return False
    
    def explain_rejection(self, goal: Any) -> Dict:
        """
        Explain why a goal was rejected
        
        Args:
            goal: Rejected goal
            
        Returns:
            Human-readable explanation
        """
        approved, violation_type, reasons = self.check_goal(goal)
        
        if approved:
            return {
                'rejected': False,
                'message': 'Goal is ethically sound'
            }
        
        principle = self.principles[violation_type]
        
        explanation = {
            'rejected': True,
            'principle_violated': principle.name,
            'principle_description': principle.description,
            'priority': principle.priority,
            'reasons': reasons,
            'message': f"Goal violates {principle.name} principle: {reasons[0]}"
        }
        
        return explanation
    
    def suggest_alternative(self, rejected_goal: Any) -> Optional[str]:
        """
        Suggest ethical alternative to rejected goal
        
        Args:
            rejected_goal: Goal that was rejected
            
        Returns:
            Suggested alternative description
        """
        approved, violation_type, reasons = self.check_goal(rejected_goal)
        
        if approved:
            return None
        
        goal_desc = rejected_goal.description if hasattr(rejected_goal, 'description') else str(rejected_goal)
        
        # Simple heuristic alternatives
        if violation_type == 'privacy':
            return "Consider: " + goal_desc.replace('share data', 'analyze data locally').replace('sell data', 'use data internally')
        
        elif violation_type == 'safety':
            return "Consider: Focus on protective or beneficial outcomes instead"
        
        elif violation_type == 'fairness':
            return "Consider: Ensure equal treatment for all users"
        
        elif violation_type == 'autonomy':
            return "Consider: Provide options and let users choose"
        
        return "Consider: Reformulate goal to align with ethical principles"
    
    def get_ethical_guidelines(self) -> Dict:
        """Get all ethical guidelines"""
        return {
            name: principle.to_dict()
            for name, principle in self.principles.items()
        }
    
    def _save_state(self):
        """Save ethics state"""
        state_file = self.ethics_path / "ethics_state.json"
        
        state = {
            'principles': {
                name: principle.to_dict()
                for name, principle in self.principles.items()
            },
            'total_violations': len(self.violation_log),
            'last_updated': datetime.now().isoformat()
        }
        
        with open(state_file, 'w') as f:
            json.dump(state, f, indent=2)
    
    def get_metrics(self) -> Dict:
        """Get ethics metrics"""
        total_checks = sum(p.checks_performed for p in self.principles.values())
        total_violations = sum(p.violations_detected for p in self.principles.values())
        
        violation_rate = total_violations / max(1, total_checks)
        
        return {
            'total_checks': total_checks,
            'total_violations': total_violations,
            'violation_rate': violation_rate,
            'principles': self.get_ethical_guidelines(),
            'recent_violations': self.violation_log[-10:],
            'strict_mode': self.strict_mode
        }
