#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""
// PURPOSE: Byzantine-Resilient Consensus for PULSE Brain.
// [Phase 1.3: Multi-Agent Consensus - HARDENED]
"""

import sys
import json
from pathlib import Path

SCRIPT_DIR = Path(__file__).resolve().parent
ROOT_DIR = SCRIPT_DIR.parent.parent
from datetime import datetime, timezone
from typing import Dict, List, Any

# Add Utilities to path

from pulse.core.brain_utils import load_json, save_json
from pulse.core.pulse_crypto import PulseCrypto

AUTH_FILE = ROOT_DIR / "Corpus_Callosum" / "authorized_humans.json"

class BrainConsensus:
    """
    // Implements > 2/3 Majority Consensus with MANDATORY Human Veto.
    // HARDENED: Signature verification is enforced.
    // STATE SEALED: Protects against direct file tampering.
    """

    def __init__(self):
        self.crypto = PulseCrypto()
        self.state_dir = ROOT_DIR / "state"
        self.proposals_file = self.state_dir / "active_proposals.json"
        self.proposals_sig_file = self.state_dir / "active_proposals.json.sig"
        self.auth_file = AUTH_FILE

    def open_proposal(self, proposer_id: str, action: str, details: Dict[str, Any]) -> str:
        """// Opens a new proposal. Defaults to LOCKED status."""
        proposal_id = f"prop_{int(datetime.now(timezone.utc).timestamp())}"
        
        proposal = {
            "proposal_id": proposal_id,
            "proposer_id": proposer_id,
            "action": action,
            "details": details,
            "votes": {}, 
            "founder_signature": None,
            "status": "LOCKED_PENDING_HUMAN",
            "created_at": datetime.now(timezone.utc).isoformat()
        }
        
        all_proposals = self._load_proposals()
        all_proposals[proposal_id] = proposal
        self._save_proposals(all_proposals)
        
        print(f"  [CONSENSUS] Proposal {proposal_id} LOCKED. Waiting for Human Signature.")
        return proposal_id

    def cast_vote(self, proposal_id: str, agent_id: str, vote: bool) -> bool:
        """// Casts a signed vote. Does NOT resolve until unlocked."""
        all_proposals = self._load_proposals()
        if proposal_id not in all_proposals:
            return False
        
        vote_data = {"proposal_id": proposal_id, "vote": vote, "agent_id": agent_id}
        signature = self.crypto.sign(vote_data)
        
        all_proposals[proposal_id]["votes"][agent_id] = {
            "vote": vote,
            "signature": signature,
            "timestamp": datetime.now(timezone.utc).isoformat()
        }
        
        self._save_proposals(all_proposals)
        print(f"  [CONSENSUS] Vote CAST on {proposal_id} by {agent_id}")
        return True

    def unlock_proposal(self, proposal_id: str, founder_signature: str, public_key_pem: str) -> bool:
        """
        // Unlocks a proposal using the Founder's RSA signature.
        """
        all_proposals = self._load_proposals()
        if proposal_id not in all_proposals: return False
        
        if not self._is_key_authorized(public_key_pem):
            print("🚨 SECURITY ALERT: Unauthorized key!")
            return False

        if self.crypto.verify_human_signature(proposal_id, founder_signature, public_key_pem):
            all_proposals[proposal_id]["status"] = "OPEN"
            all_proposals[proposal_id]["founder_signature"] = founder_signature
            self._save_proposals(all_proposals)
            print(f"  [CONSENSUS] Proposal {proposal_id} UNLOCKED by Founder.")
            return True
        else:
            print("🚨 SECURITY ALERT: Invalid Founder Signature!")
            return False

    def resolve(self, proposal_id: str, required_agents: List[str]) -> Dict[str, Any]:
        """// Resolves a proposal. Enforces Signature Checks."""
        all_proposals = self._load_proposals()
        if proposal_id not in all_proposals:
            return {"status": "ERROR", "reason": "Not Found"}
            
        proposal = all_proposals[proposal_id]
        
        if proposal["status"] == "LOCKED_PENDING_HUMAN":
            return {"status": "LOCKED", "reason": "Missing Founder Signature"}

        votes = proposal["votes"]
        yes_votes = 0
        total_valid = 0
        
        for agent in required_agents:
            if agent in votes:
                vote_entry = votes[agent]
                expected_msg = {
                    "proposal_id": proposal_id, 
                    "vote": vote_entry["vote"], 
                    "agent_id": agent
                }
                temp_item = expected_msg.copy()
                temp_item["_signature"] = vote_entry["signature"]
                
                if self.crypto.verify(temp_item):
                    total_valid += 1
                    if vote_entry["vote"]:
                        yes_votes += 1
                else:
                    print(f"🚨 SECURITY ALERT: Invalid Signature from {agent}!")
        
        total_needed = len(required_agents)
        threshold = (2 * total_needed) / 3
        
        if yes_votes > threshold:
            proposal["status"] = "APPROVED"
        elif (total_valid - yes_votes) >= (total_needed / 3):
            proposal["status"] = "REJECTED"
        else:
            proposal["status"] = "INCONCLUSIVE"
            
        self._save_proposals(all_proposals)
        return proposal

    def _is_key_authorized(self, pub_key: str) -> bool:
        """// Checks if the public key exists in authorized_humans.json."""
        if not self.auth_file.exists(): return False
        try:
            whitelist = load_json(self.auth_file)
            for user in whitelist.values():
                if user.get("public_key") == pub_key:
                    return True
        except Exception:
            return False
        return False

    def _load_proposals(self) -> Dict[str, Any]:
        """// Loads and VERIFIES the proposals file. [State Sealing]"""
        if not self.proposals_file.exists() or not self.proposals_sig_file.exists():
            return {}
            
        # 1. Read Signature
        with open(self.proposals_sig_file, "r") as f:
            expected_sig = f.read()
            
        # 2. Re-calculate Signature
        with open(self.proposals_file, "rb") as f:
            data_bytes = f.read()
            
        # Create a temporary item for verification
        verify_item = {"data": data_bytes.decode(), "_signature": expected_sig}
        
        # 3. Verify
        if self.crypto.verify(verify_item):
            return json.loads(data_bytes.decode())
        else:
            print("🚨 CRITICAL SECURITY ALERT: PROPOSAL FILE TAMPERED!")
            # Return empty dict, discarding the corrupted state
            return {}

    def _save_proposals(self, data: Dict[str, Any]):
        """// Saves and SIGNS the proposals file. [State Sealing]"""
        json_str = json.dumps(data, indent=2)
        
        # Create a signature for the content
        sig = self.crypto.sign({"data": json_str})
        
        # Write files
        with open(self.proposals_file, "w") as f:
            f.write(json_str)
        with open(self.proposals_sig_file, "w") as f:
            f.write(sig)

if __name__ == "__main__":
    # Test Hardened Consensus
    engine = BrainConsensus()
    pid = engine.open_proposal("gemini_cli", "rule_promotion", {"rule_id": "LAW_10"})
    
    # Try to resolve immediately (Should FAIL)
    res = engine.resolve(pid, ["gemini_cli"])
    print(f"Locked Resolution: {res['status']}")
