"""
CorvOS - Temporal Audit Module v1.0
Tracking de tentativas de manipulacao passado/futuro
Synapse-k | Arkhe(n) | Rio de Janeiro
"""
import numpy as np
from dataclasses import dataclass, field
from typing import List, Dict, Tuple, Set, Optional
from datetime import datetime, timedelta
from enum import Enum
import hashlib, asyncio
from collections import deque, defaultdict

class ManipulationType(Enum):
    PAST_FALSIFICATION = "past_falsification"
    FUTURE_TAMPERING = "future_tampering"
    RETROCAUSAL_LOOP = "retrocausal_loop"
    PARADOX_INJECTION = "paradox_injection"
    CAUSALITY_BREAK = "causality_break"

class ManipulationSeverity(Enum):
    CRITICAL = 4   # Paradoxo causal real
    HIGH = 3       # Tentativa de alteracao significativa
    MEDIUM = 2     # Anomalia temporal detectada
    LOW = 1        # Ruido temporal benigno

@dataclass
class TemporalAuditEntry:
    entry_id: str
    timestamp: datetime
    manipulation_type: ManipulationType
    severity: ManipulationSeverity
    source_node: str
    target_time: Optional[datetime]
    altered_fields: List[str]
    integrity_hash_before: str
    integrity_hash_after: str
    quarantined: bool = False
    resolved: bool = False
    resolution: Optional[str] = None

class TemporalAuditLog:
    def __init__(self):
        self.entries: List[TemporalAuditEntry] = []
        self.paradox_counter: Dict[str, int] = defaultdict(int)
        self.causality_graph: Dict[str, Set[str]] = defaultdict(set)
        self.integrity_chain: deque = deque(maxlen=10000)
        self.hash_chain_tip: str = "GENESIS"

    def compute_integrity_hash(self, data: dict) -> str:
        raw = str(sorted(data.items())).encode()
        return hashlib.sha256(raw + self.hash_chain_tip.encode()).hexdigest()

    def append(self, entry: TemporalAuditEntry):
        entry.integrity_hash_before = self.hash_chain_tip
        entry.integrity_hash_after = self.compute_integrity_hash(entry.__dict__)
        self.hash_chain_tip = entry.integrity_hash_after
        self.entries.append(entry)
        self.integrity_chain.append({
            'entry_id': entry.entry_id,
            'hash': entry.integrity_hash_after,
            'timestamp': entry.timestamp
        })
        if entry.target_time:
            self.causality_graph[str(entry.timestamp)].add(str(entry.target_time))
        if entry.manipulation_type == ManipulationType.PARADOX_INJECTION:
            self.paradox_counter[entry.source_node] += 1

    def detect_causality_violation(self, proposed_time: datetime,
                                   source_node: str) -> Tuple[bool, str]:
        source_str = str(source_node)
        if source_str in self.paradox_counter and self.paradox_counter[source_str] > 3:
            return True, f"Node {source_node} has {self.paradox_counter[source_str]} paradox attempts"
        return False, "OK"

    def verify_chain_integrity(self) -> Tuple[bool, str]:
        for i, entry in enumerate(self.entries):
            if i == 0:
                continue
            prev_hash = self.entries[i-1].integrity_hash_after
            if entry.integrity_hash_before != prev_hash:
                return False, f"Chain broken at entry {i}: expected {prev_hash[:16]}, got {entry.integrity_hash_before[:16]}"
        return True, "Chain intact"

    def get_tampering_report(self) -> Dict:
        by_type = defaultdict(list)
        for e in self.entries:
            by_type[e.manipulation_type.value].append(e)
        return {
            'total_entries': len(self.entries),
            'by_type': {k: len(v) for k, v in by_type.items()},
            'quarantined': sum(1 for e in self.entries if e.quarantined),
            'resolved': sum(1 for e in self.entries if e.resolved),
            'chain_integrity': self.verify_chain_integrity()[0],
            'top_paradox_nodes': sorted(self.paradox_counter.items(), key=lambda x: -x[1])[:5]
        }

class TemporalAuditEngine:
    def __init__(self):
        self.audit_log = TemporalAuditLog()
        self.blocked_time_windows: Dict[str, datetime] = {}
        self.causality_lock: Dict[str, bool] = {}

    async def audit_packet(self, packet: Dict, direction: str) -> Tuple[bool, Optional[TemporalAuditEntry]]:
        now = datetime.now()
        packet_hash = hashlib.sha256(str(packet).encode()).hexdigest()[:16]
        node = packet.get('node_id', 'UNKNOWN')
        target_time = packet.get('target_time')
        altered = packet.get('altered_fields', [])
        severity = ManipulationSeverity.LOW
        mtype = ManipulationType.PAST_FALSIFICATION if direction == "retrocausal" else ManipulationType.FUTURE_TAMPERING
        if altered:
            severity = ManipulationSeverity.HIGH
            mtype = ManipulationType.PARADOX_INJECTION
        entry = TemporalAuditEntry(
            entry_id=f"AUD-{now.timestamp()}-{packet_hash}",
            timestamp=now,
            manipulation_type=mtype,
            severity=severity,
            source_node=node,
            target_time=target_time,
            altered_fields=altered,
            integrity_hash_before="",
            integrity_hash_after=""
        )
        violation, msg = self.audit_log.detect_causality_violation(target_time or now, node)
        if violation:
            entry.quarantined = True
            entry.resolution = msg
        self.audit_log.append(entry)
        return not violation, entry

    def get_status(self) -> Dict:
        report = self.audit_log.get_tampering_report()
        return {
            'audit_entries': report['total_entries'],
            'integrity_verified': report['chain_integrity'],
            'blocked_windows': len(self.blocked_time_windows),
            'top_manipulation_types': dict(sorted(report['by_type'].items(), key=lambda x: -x[1])[:3])
        }
