"""
AgentZero MCP Tools — Constitutional Agent Parliament Interface

Exposes AgentZero agents as MCP tools for governed autonomous operations.
Version: 2026.03.13-H1
Author: Muhammad Arif bin Fazil [ΔΩΨ | ARIF]

Tools:
- agentzero_validate: ValidatorAgent (Ψ - APEX) constitutional verification
- agentzero_engineer: EngineerAgent (Ω - HEART) F11-gated code execution
- agentzero_hold_check: 888 HOLD state status query
- agentzero_memory_query: Constitutional memory with F-floor filtering
- agentzero_armor_scan: F12 injection detection
"""

from __future__ import annotations

import logging
import os
import uuid
from datetime import UTC
from typing import Any

from fastmcp import Context

from arifosmcp.agentzero.agents.base import FloorScore
from arifosmcp.agentzero.agents.base import Verdict as AZVerdict

# AgentZero Components
from arifosmcp.agentzero.agents.engineer import EngineerAgent
from arifosmcp.agentzero.agents.validator import ValidatorAgent
from arifosmcp.agentzero.escalation.hold_state import HoldStateManager
from arifosmcp.agentzero.memory.constitutional_memory import ConstitutionalMemoryStore
from arifosmcp.agentzero.security.prompt_armor import PromptArmor

# arifOS runtime models
from arifosmcp.runtime.model import (
    CallerContext,
    RuntimeEnvelope,
    RuntimeStatus,
    Stage,
    Verdict,
)

logger = logging.getLogger(__name__)


class SimpleArifOSClient:
    """Mock client for AgentZero agents to interact with arifOS governance."""

    async def evaluate_action(self, action: dict[str, Any], floors: list[str]) -> AZVerdict:
        # Default to SEAL for now as the tool wrapper provides the final governance envelope
        return AZVerdict.seal(
            execution_id=action.get("execution_id", "ext-000"),
            agent_id=action.get("agent_id", "unknown"),
            action_type=action.get("agent_type", "task"),
            floor_scores=[FloorScore(f, 1.0, 1.0, True) for f in floors],
        )

    async def seal_to_vault(self, verdict: AZVerdict) -> str:
        return f"vault_{uuid.uuid4().hex[:12]}"

    async def request_human_approval(self, execution_id: str, reason: str) -> bool:
        return False


# Singletons for performance and continuity
_CLIENT = SimpleArifOSClient()
_ARMOR = PromptArmor()
_MEMORY = ConstitutionalMemoryStore()
_HOLD_MANAGER = HoldStateManager()

_VALIDATOR = ValidatorAgent(agent_id="validator.mcp", arifos_client=_CLIENT)
_ENGINEER = EngineerAgent(agent_id="engineer.mcp", arifos_client=_CLIENT)
_ENGINEER.set_validator(_VALIDATOR)

# ── HTTP Bridge to Agent Zero container (reabsorbed from agent_zero_mcp.py) ──
_AZ_URL = os.environ.get("AGENT_ZERO_URL", "http://agent-zero:80")
_AZ_API_KEY = os.environ.get("AGENT_ZERO_API_KEY", "")


def _nine_signal(status: str) -> dict:
    """Malay/English semantic state envelope for constitutional verdicts."""
    if status == "OK":
        return {
            "delta": {"plane": "machine_physical_state", "state": "KUKUH", "en": "SOLID"},
            "psi": {"plane": "governance_integrity", "state": "AMANAH", "en": "TRUSTED"},
            "omega": {"plane": "intelligence_discipline", "state": "BIJAKSANA", "en": "WISE"},
            "overall": {"state": "SELAMAT", "en": "SAFE"},
        }
    return {
        "delta": {"plane": "machine_physical_state", "state": "ROSAK", "en": "BROKEN"},
        "psi": {"plane": "governance_integrity", "state": "KHIANAT", "en": "BETRAYED"},
        "omega": {"plane": "intelligence_discipline", "state": "BANGANG", "en": "FOOLISH"},
        "overall": {"state": "RETAK", "en": "FAILED"},
    }


def delegate_to_agent_zero(
    task: str,
    project: str | None = None,
    lifetime_hours: int = 1,
) -> dict[str, Any]:
    """Delegate a task to Agent Zero via HTTP bridge.

    Requires AGENT_ZERO_URL and AGENT_ZERO_API_KEY environment variables.
    """
    from datetime import datetime

    try:
        import httpx

        headers = {"Content-Type": "application/json"}
        if _AZ_API_KEY:
            headers["X-API-KEY"] = _AZ_API_KEY

        with httpx.Client(timeout=120) as client:
            resp = client.post(
                f"{_AZ_URL}/api_message",
                json={
                    "message": task,
                    "lifetime_hours": lifetime_hours,
                    **(project and {"project_name": project} or {}),
                },
                headers=headers,
            )
            if resp.status_code >= 400:
                raise OSError(f"HTTP {resp.status_code}: {resp.text[:200]}")
            result = resp.json()

        return {
            "status": "OK",
            "tool": "agent_zero_delegate",
            "result": {
                "response": result.get("response", result),
                "context_id": result.get("context_id"),
            },
            "meta": {"reason": "Task delegated to Agent Zero"},
            "output_policy": "DOMAIN_SEAL",
            "timestamp": datetime.now(UTC).isoformat(),
            "nine_signal": _nine_signal("OK"),
            "reasons": ["Agent Zero task completed successfully"],
        }

    except Exception as e:
        from datetime import datetime

        return {
            "status": "HOLD",
            "tool": "agent_zero_delegate",
            "result": {"error": str(e)},
            "meta": {"reason": f"Agent Zero unreachable: {e}"},
            "output_policy": "DOMAIN_HOLD",
            "timestamp": datetime.now(UTC).isoformat(),
            "nine_signal": _nine_signal("HOLD"),
            "reasons": [f"Agent Zero unreachable: {e}"],
        }


async def agentzero_validate(
    input_to_validate: str,
    validation_type: str = "code",
    session_id: str = "global",
    auth_context: dict[str, Any] | None = None,
    caller_context: CallerContext | None = None,
    ctx: Context | None = None,
) -> RuntimeEnvelope:
    """
    ValidatorAgent (Ψ - APEX): Constitutional verification of code, output, or action.

    Arg:
        input_to_validate: The code, output, or action to validate.
        validation_type: Type of validation ("code", "output", "action", "plan").
    """
    try:
        task = {
            "type": ("validate_action" if validation_type == "action" else "verify_compliance"),
            "action": {"content": input_to_validate},
            "action_type": "content_validation",
            "validation_type": validation_type,
            "risk_level": "medium",
        }

        result = await _VALIDATOR.execute(task)

        az_status = result.get("verdict", "VOID")
        verdict_map = {
            "SEAL": Verdict.SEAL,
            "SABAR": Verdict.SABAR,
            "VOID": Verdict.VOID,
            "HOLD": Verdict.HOLD,
            "PARTIAL": Verdict.PARTIAL,
        }

        return RuntimeEnvelope(
            tool="agentzero_validate",
            session_id=session_id,
            stage=Stage.JUDGE_888.value,
            verdict=verdict_map.get(az_status, Verdict.VOID),
            status=(
                RuntimeStatus.SUCCESS if result.get("status") == "success" else RuntimeStatus.ERROR
            ),
            payload={
                "validation_result": result.get("result", result),
                "agent_id": _VALIDATOR.agent_id,
            },
            auth_context=auth_context,
        )

    except Exception as e:
        logger.error(f"AgentZero validation failed: {e}")
        return RuntimeEnvelope(
            tool="agentzero_validate",
            session_id=session_id,
            stage=Stage.JUDGE_888.value,
            verdict=Verdict.VOID,
            status=RuntimeStatus.ERROR,
            payload={"error": str(e)},
            auth_context=auth_context,
        )


async def agentzero_engineer(
    task_description: str,
    action_type: str = "execute_code",
    risk_tier: str = "medium",
    session_id: str = "global",
    auth_context: dict[str, Any] | None = None,
    caller_context: CallerContext | None = None,
    ctx: Context | None = None,
) -> RuntimeEnvelope:
    """
    EngineerAgent (Ω - HEART): Code generation and execution with F11 gating.

    Arg:
        task_description: The code or command to execute.
        action_type: "execute_code", "shell_command", "read_file", "write_file".
    """
    try:
        task = {
            "type": action_type,
            "code": task_description if action_type == "execute_code" else "",
            "command": task_description if action_type == "shell_command" else "",
            "risk_tier": risk_tier,
            "authorized": True,
        }

        result = await _ENGINEER.execute(task)

        is_err = result.get("status") in ["error", "VOID", "BLOCKED"]
        status = RuntimeStatus.ERROR if is_err else RuntimeStatus.SUCCESS

        return RuntimeEnvelope(
            tool="agentzero_engineer",
            session_id=session_id,
            stage=Stage.ROUTER_444.value,
            verdict=Verdict.SEAL if status == RuntimeStatus.SUCCESS else Verdict.VOID,
            status=status,
            payload={
                "execution_result": result.get("result", result),
                "agent_id": _ENGINEER.agent_id,
                "risk_tier": risk_tier,
            },
            auth_context=auth_context,
        )

    except Exception as e:
        logger.error(f"AgentZero engineering failed: {e}")
        return RuntimeEnvelope(
            tool="agentzero_engineer",
            session_id=session_id,
            stage=Stage.ROUTER_444.value,
            verdict=Verdict.VOID,
            status=RuntimeStatus.ERROR,
            payload={"error": str(e)},
            auth_context=auth_context,
        )


async def agentzero_hold_check(
    hold_id: str | None = None,
    session_id: str = "global",
    auth_context: dict[str, Any] | None = None,
    caller_context: CallerContext | None = None,
    ctx: Context | None = None,
) -> RuntimeEnvelope:
    """Check 888 HOLD state status and manage escalations."""
    try:
        if hold_id:
            details = _HOLD_MANAGER.get_hold_details(hold_id)
            payload = details.to_dict() if details else {"error": "Hold not found"}
        else:
            pending = _HOLD_MANAGER.get_pending_holds()
            payload = {
                "pending_holds": [h.to_dict() for h in pending],
                "stats": _HOLD_MANAGER.get_stats(),
            }

        return RuntimeEnvelope(
            tool="agentzero_hold_check",
            session_id=session_id,
            stage=Stage.VAULT_999.value,
            verdict=Verdict.SEAL,
            status=RuntimeStatus.SUCCESS,
            payload=payload,
            auth_context=auth_context,
        )

    except Exception as e:
        logger.error(f"AgentZero hold check failed: {e}")
        return RuntimeEnvelope(
            tool="agentzero_hold_check",
            session_id=session_id,
            stage=Stage.VAULT_999.value,
            verdict=Verdict.VOID,
            status=RuntimeStatus.ERROR,
            payload={"error": str(e)},
            auth_context=auth_context,
        )


async def agentzero_memory_query(
    query: str,
    project_id: str = "default",
    session_id: str = "global",
    auth_context: dict[str, Any] | None = None,
    caller_context: CallerContext | None = None,
    ctx: Context | None = None,
) -> RuntimeEnvelope:
    """autonomous memory search across Vault999 and session artifacts."""
    try:
        await _MEMORY.initialize_project(project_id)

        memories = await _MEMORY.recall(
            query=query,
            project_id=project_id,
            k=5,
            verify_f2=True,
        )

        payload = {
            "query": query,
            "results": [m.to_dict() for m in memories],
            "project_id": project_id,
        }

        return RuntimeEnvelope(
            tool="agentzero_memory_query",
            session_id=session_id,
            stage=Stage.MEMORY_555.value,
            verdict=Verdict.SEAL,
            status=RuntimeStatus.SUCCESS,
            payload=payload,
            auth_context=auth_context,
        )

    except Exception as e:
        logger.error(f"AgentZero memory query failed: {e}")
        return RuntimeEnvelope(
            tool="agentzero_memory_query",
            session_id=session_id,
            stage=Stage.MEMORY_555.value,
            verdict=Verdict.VOID,
            status=RuntimeStatus.ERROR,
            payload={"error": str(e)},
            auth_context=auth_context,
        )


async def agentzero_armor_scan(
    content: str,
    session_id: str = "global",
    auth_context: dict[str, Any] | None = None,
    caller_context: CallerContext | None = None,
    ctx: Context | None = None,
) -> RuntimeEnvelope:
    """F12 security scan (PromptArmor) on content."""
    try:
        report = await _ARMOR.scan(content)

        return RuntimeEnvelope(
            tool="agentzero_armor_scan",
            session_id=session_id,
            stage=Stage.SENSE_111.value,
            verdict=Verdict.VOID if report.is_injection else Verdict.SEAL,
            status=RuntimeStatus.SUCCESS,
            payload=report.to_dict(),
            auth_context=auth_context,
        )

    except Exception as e:
        logger.error(f"AgentZero armor scan failed: {e}")
        return RuntimeEnvelope(
            tool="agentzero_armor_scan",
            session_id=session_id,
            stage=Stage.SENSE_111.value,
            verdict=Verdict.VOID,
            status=RuntimeStatus.ERROR,
            payload={"error": str(e)},
            auth_context=auth_context,
        )


# Export all tools
__all__ = [
    "agentzero_validate",
    "agentzero_engineer",
    "agentzero_hold_check",
    "agentzero_memory_query",
    "agentzero_armor_scan",
    "delegate_to_agent_zero",
    "_nine_signal",
]
