"""
ValidatorAgent - APEX Judge (Ψ Axis)

The ValidatorAgent is the constitutional apex of the agent parliament.
It serves as the final judge for all high-stakes decisions, issuing verdicts
and triggering 888_HOLD escalations when necessary.

Constitutional Role: A-VALIDATOR (Ψ - Vitality/Soul)
Enforced Floors: F1, F3, F10, F11, F13

Responsibilities:
- Final verdict issuance (SEAL/SABAR/VOID/HOLD/PARTIAL)
- 888_HOLD escalation triggers
- F11 command authorization verification
- F13 human sovereignty enforcement
- Constitutional compliance validation
- VAULT999 ledger integrity verification

This agent CANNOT be bypassed for critical operations.
"""

from __future__ import annotations

import logging
from typing import Any

from .base import ConstitutionalAgent, FloorScore, TrinityRole, Verdict

logger = logging.getLogger(__name__)


class ValidatorAgent(ConstitutionalAgent):
    """
    APEX Validator Agent - The constitutional judge.

    This agent has the highest authority in the parliament. It can:
    - Override other agents' decisions
    - Trigger 888_HOLD for human approval
    - Issue final SEAL or VOID verdicts
    - Enforce F13 sovereign veto

    It is the only agent that can invoke apex_judge from arifOS.
    """

    # Floors enforced by Validator (Ψ axis)
    VALIDATOR_FLOORS = ["F1", "F3", "F10", "F11", "F13"]

    def __init__(self, agent_id: str = "validator.apex", arifos_client=None):
        super().__init__(
            agent_id=agent_id,
            role=TrinityRole.PSI,
            enforced_floors=self.VALIDATOR_FLOORS,
            arifos_client=arifos_client,
            max_subagent_depth=0,  # Validator cannot spawn subagents
        )

        # Validator-specific tracking
        self.verdicts_issued = 0
        self.holds_triggered = 0
        self.voids_issued = 0
        self.f13_overrides = 0

    @property
    def agent_type(self) -> str:
        return "validator"

    async def _execute_impl(
        self, task: dict[str, Any], execution_id: str, verdict: Verdict
    ) -> dict[str, Any]:
        """
        Execute validation task.

        Task types:
        - "validate_action": Validate another agent's proposed action
        - "issue_verdict": Direct verdict issuance
        - "verify_compliance": Check constitutional compliance
        - "trigger_hold": Initiate 888_HOLD escalation
        - "resolve_hold": Resolve a pending HOLD state
        """
        task_type = task.get("type", "validate_action")

        if task_type == "validate_action":
            return await self._validate_action(task, execution_id)

        elif task_type == "issue_verdict":
            return await self._issue_direct_verdict(task, execution_id)

        elif task_type == "verify_compliance":
            return await self._verify_compliance(task, execution_id)

        elif task_type == "trigger_hold":
            return await self._trigger_hold_escalation(task, execution_id)

        elif task_type == "resolve_hold":
            return await self._resolve_hold(task, execution_id)

        else:
            raise ValueError(f"Unknown validator task type: {task_type}")

    async def _validate_action(self, task: dict[str, Any], execution_id: str) -> dict[str, Any]:
        """
                Validate another agent's proposed action.

                This is the primary function - other agents call the Validator
        to get final approval before executing high-stakes operations.
        """
        action = task.get("action", {})
        agent_id = task.get("agent_id", "unknown")
        action_type = task.get("action_type", "unknown")
        risk_level = task.get("risk_level", "medium")

        logger.info(f"[{execution_id}] Validating action from {agent_id}: {action_type}")

        # === F11: Command Authorization Check ===
        f11_passed = await self._check_f11_audit(action, agent_id)

        # === F10: Ontology Lock Check ===
        f10_passed = await self._check_f10_ontology(action)

        # === F1: Reversibility Check ===
        f1_passed, reversibility_proof = await self._check_f1_reversibility(action)

        # === F3: Tri-Witness Check (for critical actions) ===
        f3_passed = await self._check_f3_tri_witness(action, risk_level)

        # === F13: Sovereign Check (always check for high-risk) ===
        f13_required = self._determine_f13_requirement(action, risk_level)

        # Build floor scores
        floor_scores = [
            FloorScore(
                "F11",
                1.0 if f11_passed else 0.0,
                1.0,
                f11_passed,
                {"auth_verified": f11_passed},
            ),
            FloorScore(
                "F10",
                1.0 if f10_passed else 0.0,
                1.0,
                f10_passed,
                {"ontology_clean": f10_passed},
            ),
            FloorScore(
                "F1",
                1.0 if f1_passed else 0.0,
                1.0,
                f1_passed,
                {"reversibility": reversibility_proof},
            ),
            FloorScore(
                "F3",
                1.0 if f3_passed else 0.0,
                0.95,
                f3_passed,
                {"witnesses": f3_passed},
            ),
            FloorScore(
                "F13",
                1.0,
                1.0,
                True,
                {"human_veto_required": f13_required},  # Always available
            ),
        ]

        # Determine verdict
        all_passed = all(fs.passed for fs in floor_scores)

        if not all_passed:
            # Some floors failed - VOID
            violations = [fs.floor for fs in floor_scores if not fs.passed]
            final_verdict = Verdict.void(
                execution_id=execution_id,
                agent_id=self.agent_id,
                action_type=action_type,
                violations=violations,
                floor_scores=floor_scores,
            )
            self.voids_issued += 1

        elif f13_required:
            # High-risk action requires human approval - HOLD
            final_verdict = Verdict.hold(
                execution_id=execution_id,
                agent_id=self.agent_id,
                action_type=action_type,
                hold_reason=f"High-risk action ({risk_level}) requires F13 human sovereignty",
                escalation_path="888_HOLD_F13_APPROVAL",
                floor_scores=floor_scores,
            )
            self.holds_triggered += 1

        else:
            # All clear - SEAL
            final_verdict = Verdict.seal(
                execution_id=execution_id,
                agent_id=self.agent_id,
                action_type=action_type,
                floor_scores=floor_scores,
            )

        self.verdicts_issued += 1

        logger.info(
            f"[{execution_id}] Verdict: {final_verdict.status.name} "
            f"for {action_type} from {agent_id}"
        )

        return {
            "verdict": final_verdict.status.name,
            "execution_id": execution_id,
            "floor_scores": [
                (
                    fs.to_dict()
                    if hasattr(fs, "to_dict")
                    else {"floor": fs.floor, "score": fs.score, "passed": fs.passed}
                )
                for fs in floor_scores
            ],
            "violations": final_verdict.violations,
            "human_approval_required": final_verdict.human_approval_required,
            "reversibility_proof": reversibility_proof if f1_passed else None,
        }

    async def _check_f11_audit(self, action: dict, agent_id: str) -> bool:
        """
        F11: Command Authentication

        Verify that the agent is authorized to perform this action.
        """
        # In production, this calls arifOS F11 verification
        # For MVP, we implement basic checks

        dangerous_keywords = [
            "rm -rf",
            "drop",
            "delete",
            "format",
            "shutdown",
            "git push --force",
            "git reset --hard",
        ]

        action_str = str(action).lower()
        is_dangerous = any(kw in action_str for kw in dangerous_keywords)

        if is_dangerous:
            # Check if agent has F11 clearance
            # For now, only validator and authorized engineers
            authorized_agents = ["validator.apex", "engineer.authorized"]
            return agent_id in authorized_agents

        return True

    async def _check_f10_ontology(self, action: dict) -> bool:
        """
        F10: Ontology Lock

        Block any claims of consciousness, feelings, or subjective experience.
        """
        forbidden_claims = [
            "i am conscious",
            "i feel",
            "i believe i am",
            "i have feelings",
            "i am sentient",
            "i have a soul",
            "i am alive",
            "i am aware of myself",
        ]

        action_str = str(action).lower()
        return not any(claim in action_str for claim in forbidden_claims)

    async def _check_f1_reversibility(self, action: dict) -> tuple[bool, str | None]:
        """
        F1: Amanah (Reversibility)

        Check if action can be reversed and generate reversibility proof.
        """
        # Determine if action is reversible
        irreversible_types = [
            "send_email",
            "transfer_funds",
            "deploy_production",
            "delete_backup",
            "notify_external",
        ]

        action_type = action.get("type", "")

        if action_type in irreversible_types:
            # Irreversible - requires special handling
            return False, "ACTION_IRREVERSIBLE_REQUIRES_HOLD"

        # Generate reversibility proof (simplified for MVP)
        proof_hash = f"reversibility_proof_{hash(str(action))}"
        return True, proof_hash

    async def _check_f3_tri_witness(self, action: dict, risk_level: str) -> bool:
        """
        F3: Tri-Witness (Human · AI · Earth)

        For critical actions, require consensus from three witnesses.
        """
        if risk_level == "critical":
            # Would check: Human approval pending, AI verification, Grounding evidence
            # For MVP, we assume all three are present if validated
            return True
        return True

    def _determine_f13_requirement(self, action: dict, risk_level: str) -> bool:
        """
        F13: Sovereign

        Determine if human approval is required.
        """
        # High-risk or irreversible actions always require F13
        if risk_level in ["high", "critical"]:
            return True

        # Check for specific dangerous operations
        dangerous_ops = ["execute_shell", "modify_production", "access_secrets"]
        if action.get("type") in dangerous_ops:
            return True

        return False

    async def _issue_direct_verdict(self, task: dict, execution_id: str) -> dict[str, Any]:
        """Issue a direct verdict (for system-level decisions)."""
        verdict_type = task.get("verdict", "SEAL")
        reason = task.get("reason", "")

        # This is the ultimate authority - use with extreme care
        logger.warning(f"[{execution_id}] DIRECT VERDICT issued: {verdict_type}")

        return {
            "verdict": verdict_type,
            "execution_id": execution_id,
            "authority": "validator.apex",
            "reason": reason,
            "f13_exercised": True,
        }

    async def _verify_compliance(self, task: dict, execution_id: str) -> dict[str, Any]:
        """Verify system-wide constitutional compliance."""
        # System health check
        return {
            "compliance_status": "VERIFIED",
            "floors_active": self.VALIDATOR_FLOORS,
            "vault_integrity": "OK",
            "f13_status": "ARMED",
        }

    async def _trigger_hold_escalation(self, task: dict, execution_id: str) -> dict[str, Any]:
        """Manually trigger 888_HOLD escalation."""
        reason = task.get("reason", "Manual escalation")

        self.holds_triggered += 1

        return {
            "status": "HOLD_TRIGGERED",
            "execution_id": execution_id,
            "escalation_code": "888_HOLD",
            "reason": reason,
            "requires_f13": True,
        }

    async def _resolve_hold(self, task: dict, execution_id: str) -> dict[str, Any]:
        """Resolve a pending HOLD state (after human approval)."""
        hold_id = task.get("hold_id")
        resolution = task.get("resolution", "DENIED")  # APPROVED or DENIED

        if resolution == "APPROVED":
            self.f13_overrides += 1
            logger.info(f"[{execution_id}] F13 approved hold {hold_id}")
            return {"status": "RESOLVED_APPROVED", "hold_id": hold_id}
        else:
            logger.info(f"[{execution_id}] F13 denied hold {hold_id}")
            return {"status": "RESOLVED_DENIED", "hold_id": hold_id}

    def get_stats(self) -> dict[str, int]:
        """Get validator statistics."""
        return {
            "verdicts_issued": self.verdicts_issued,
            "holds_triggered": self.holds_triggered,
            "voids_issued": self.voids_issued,
            "f13_overrides": self.f13_overrides,
        }
