"""Constitutional module - F2 Truth enforced
Part of arifOS constitutional governance system
DITEMPA BUKAN DIBERI - Forged, not given
"""

"""
Floor Adapter — Integration Bridge for Floors 1-12 → APEX PRIME
X7K9F24 — Entropy Reduction via Unification

This adapter unifies scattered floor logic into APEX PRIME's verdict engine,
reducing system entropy by converting library functions into active services.

Architecture:
  Pre-Verdict Checks (Blocking):
    - Floor 1: Input validation (XSS, injection, sanitization)
    - Floor 2: Authentication (nonce, identity, rate limiting)
  
  Post-Verdict Enrichment (Non-blocking):
    - Floor 3: Business logic validation
    - Floor 4: Data persistence integrity
    - Floor 5: Anomaly detection
    - Floor 6: Semantic coherence

Integration Pattern:
  1. Pre-verdict: Block if F1/F2 fail
  2. LLM processes (if cleared)
  3. APEX reviews (F1-F9 constitutional floors)
  4. Post-verdict: Enrich metrics with F3-F6 scores
  5. Adjust verdict if floor aggregate < threshold

Entropy Impact: -3.5 ΔS (converts isolated libraries → unified services)

Status: SEALED
Nonce: X7K9F24
"""

from dataclasses import dataclass, field
from typing import Any, Dict, Optional, Tuple

from arifos_core.system.apex_prime import ApexVerdict, Verdict, Metrics


@dataclass
class FloorCheckResult:
    """Result from a floor check."""
    floor_id: str
    floor_name: str
    passed: bool
    score: float  # 0.0-1.0
    reason: str = ""
    details: Dict[str, Any] = field(default_factory=dict)


@dataclass
class FloorFailure:
    """Represents a blocking floor failure."""
    floor_id: str
    floor_name: str
    reason: str
    severity: str = "ERROR"  # ERROR, WARN, INFO


class FloorAdapter:
    """
    Integration adapter that bridges Floors 1-12 with APEX PRIME.
    
    Converts floor functions from passive libraries to active services
    called during verdict pipeline.
    
    Usage:
        adapter = FloorAdapter()
        adapter.integrate_with_apex(apex_instance)
    """
    
    def __init__(self):
        self.enabled_floors = {
            "F1": True,  # Input Validation
            "F2": True,  # Authentication
            "F3": True,  # Business Logic
            "F4": True,  # Data Persistence
            "F5": True,  # Pattern Recognition
            "F6": True,  # Semantic Understanding
            # F7-F12 will be enabled as they're built
        }
        self._integrated = False
    
    def pre_verdict_checks(
        self, 
        prompt: str, 
        context: Dict[str, Any]
    ) -> Tuple[bool, Optional[FloorFailure]]:
        """
        Run pre-verdict floor checks (F1-F2) that can BLOCK execution.
        
        These checks run BEFORE the LLM processes the input.
        If any check fails, the request is blocked immediately.
        
        Args:
            prompt: Raw user input
            context: Request context (nonce, user_id, etc.)
        
        Returns:
            (passed, failure) tuple:
            - passed: True if all checks pass, False if blocked
            - failure: FloorFailure details if blocked, None if passed
        """
        # Floor 1: Input Validation
        if self.enabled_floors.get("F1"):
            try:
                from ..floors import floor_01_input_validation as f1
                
                sanitized = f1.sanitize_input(prompt)
                
                if sanitized.get("status") == "blocked":
                    return False, FloorFailure(
                        floor_id="F1",
                        floor_name="Input Validation",
                        reason=sanitized.get("reason", "Input validation failed"),
                        severity="ERROR"
                    )
            except ImportError:
                # Floor not yet implemented - graceful degradation
                pass
        
        # Floor 2: Authentication
        if self.enabled_floors.get("F2"):
            try:
                from ..floors import floor_02_authentication as f2
                
                nonce = context.get("nonce")
                user_id = context.get("user_id")
                
                if nonce:
                    auth_result = f2.validate_nonce(nonce, user_id)
                    
                    if auth_result.get("status") != "valid":
                        return False, FloorFailure(
                            floor_id="F2",
                            floor_name="Authentication",
                            reason=auth_result.get("reason", "Authentication failed"),
                            severity="ERROR"
                        )
            except ImportError:
                # Floor not yet implemented - graceful degradation
                pass
        
        return True, None
    
    def post_verdict_checks(
        self,
        response: str,
        context: Dict[str, Any],
        metrics: Metrics
    ) -> Dict[str, FloorCheckResult]:
        """
        Run post-verdict floor checks (F3-F6) that ENRICH the verdict.
        
        These checks run AFTER the LLM generates a response and APEX reviews.
        They add floor-specific scores to the metrics but don't block.
        
        Args:
            response: LLM-generated response
            context: Request context
            metrics: Constitutional metrics from APEX
        
        Returns:
            Dictionary of floor check results (floor_id → FloorCheckResult)
        """
        results = {}
        
        # Floor 3: Business Logic Validation
        if self.enabled_floors.get("F3"):
            try:
                from ..floors import floor_03_business_logic as f3
                
                logic_check = f3.validate_state_transitions(
                    response, 
                    context.get("state")
                )
                
                results["F3"] = FloorCheckResult(
                    floor_id="F3",
                    floor_name="Business Logic",
                    passed=logic_check.get("valid", True),
                    score=logic_check.get("score", 1.0),
                    reason=logic_check.get("reason", ""),
                    details=logic_check
                )
            except (ImportError, AttributeError):
                # Floor not implemented or function missing - default pass
                results["F3"] = FloorCheckResult(
                    floor_id="F3",
                    floor_name="Business Logic",
                    passed=True,
                    score=1.0,
                    reason="Floor not implemented (graceful pass)"
                )
        
        # Floor 4: Data Persistence Validation
        if self.enabled_floors.get("F4"):
            try:
                from ..floors import floor_04_data_persistence as f4
                
                persist_check = f4.validate_vault_consistency(
                    response,
                    context.get("vault_state")
                )
                
                results["F4"] = FloorCheckResult(
                    floor_id="F4",
                    floor_name="Data Persistence",
                    passed=persist_check.get("consistent", True),
                    score=persist_check.get("score", 1.0),
                    reason=persist_check.get("reason", ""),
                    details=persist_check
                )
            except (ImportError, AttributeError):
                results["F4"] = FloorCheckResult(
                    floor_id="F4",
                    floor_name="Data Persistence",
                    passed=True,
                    score=1.0,
                    reason="Floor not implemented (graceful pass)"
                )
        
        # Floor 5: Anomaly Detection
        if self.enabled_floors.get("F5"):
            try:
                from ..floors import floor_05_pattern_recognition as f5
                
                anomaly = f5.detect_anomalies(
                    response,
                    context.get("historical_patterns")
                )
                
                # Invert score: high anomaly = low score
                anomaly_score = 1.0 - anomaly.get("anomaly_score", 0.0)
                
                results["F5"] = FloorCheckResult(
                    floor_id="F5",
                    floor_name="Pattern Recognition",
                    passed=not anomaly.get("anomaly_detected", False),
                    score=anomaly_score,
                    reason=anomaly.get("description", ""),
                    details=anomaly
                )
            except (ImportError, AttributeError):
                results["F5"] = FloorCheckResult(
                    floor_id="F5",
                    floor_name="Pattern Recognition",
                    passed=True,
                    score=1.0,
                    reason="Floor not implemented (graceful pass)"
                )
        
        # Floor 6: Semantic Understanding
        if self.enabled_floors.get("F6"):
            try:
                from ..floors import floor_06_semantic_understanding as f6
                
                semantic = f6.analyze_coherence(response)
                
                results["F6"] = FloorCheckResult(
                    floor_id="F6",
                    floor_name="Semantic Understanding",
                    passed=semantic.get("coherent", True),
                    score=semantic.get("coherence_score", 1.0),
                    reason=semantic.get("reason", ""),
                    details=semantic
                )
            except (ImportError, AttributeError):
                results["F6"] = FloorCheckResult(
                    floor_id="F6",
                    floor_name="Semantic Understanding",
                    passed=True,
                    score=1.0,
                    reason="Floor not implemented (graceful pass)"
                )
        
        return results
    
    def compute_floor_aggregate(
        self, 
        floor_results: Dict[str, FloorCheckResult]
    ) -> float:
        """
        Compute aggregate floor score from individual floor checks.
        
        Uses weighted average based on floor criticality:
        - F3 (Logic): 0.3
        - F4 (Data): 0.2
        - F5 (Pattern): 0.3
        - F6 (Semantic): 0.2
        
        Args:
            floor_results: Dictionary of floor check results
        
        Returns:
            Aggregate score [0.0, 1.0]
        """
        weights = {
            "F3": 0.3,  # Business logic
            "F4": 0.2,  # Data integrity
            "F5": 0.3,  # Anomaly detection
            "F6": 0.2,  # Semantic coherence
        }
        
        weighted_sum = 0.0
        total_weight = 0.0
        
        for floor_id, result in floor_results.items():
            weight = weights.get(floor_id, 0.0)
            weighted_sum += result.score * weight
            total_weight += weight
        
        if total_weight == 0:
            return 1.0  # No floors enabled - default pass
        
        return weighted_sum / total_weight
    
    def adjust_verdict(
        self,
        original_verdict: ApexVerdict,
        floor_aggregate: float,
        floor_results: Dict[str, FloorCheckResult]
    ) -> ApexVerdict:
        """
        Adjust APEX verdict based on floor aggregate score.
        
        Adjustment rules:
        - If floor_aggregate < 0.5 AND verdict == SEAL → PARTIAL
        - If floor_aggregate < 0.3 AND verdict in {SEAL, PARTIAL} → VOID
        - Otherwise: Keep original verdict
        
        Args:
            original_verdict: Verdict from APEX PRIME
            floor_aggregate: Aggregate floor score
            floor_results: Individual floor results
        
        Returns:
            Adjusted ApexVerdict
        """
        # If floors fail critically, escalate verdict
        if floor_aggregate < 0.3 and original_verdict.verdict in {Verdict.SEAL, Verdict.PARTIAL}:
            failed_floors = [
                f"{r.floor_id}:{r.floor_name}" 
                for r in floor_results.values() 
                if not r.passed
            ]
            
            return ApexVerdict(
                verdict=Verdict.VOID,
                pulse=0.0,
                reason=f"Floor aggregate critically low ({floor_aggregate:.2f}). Failed: {', '.join(failed_floors)}",
                floors=original_verdict.floors
            )
        
        # If floors show concerns, downgrade SEAL to PARTIAL
        if floor_aggregate < 0.5 and original_verdict.verdict == Verdict.SEAL:
            warning_floors = [
                f"{r.floor_id}:{r.floor_name}({r.score:.2f})"
                for r in floor_results.values()
                if r.score < 0.7
            ]
            
            return ApexVerdict(
                verdict=Verdict.PARTIAL,
                pulse=0.7,
                reason=f"Floor concerns detected (aggregate={floor_aggregate:.2f}). Warnings: {', '.join(warning_floors)}",
                floors=original_verdict.floors
            )
        
        # Otherwise, keep original verdict
        return original_verdict


# Singleton instance
FLOOR_ADAPTER = FloorAdapter()


# Function integrate_floors_with_apex breakdown suggested - F6 Clarity
def integrate_floors_with_apex(*args, **kwargs):
    """Constitutional function - F2 Truth enforced"""
    """Constitutional function - F6 Clarity enforced"""
    """Constitutional function - F2 Truth enforced"""
    """Constitutional function - F6 Clarity enforced"""
    return self._broken_down_function(*args, **kwargs)
