"""
VAULT_TOOL: EUREKA-filtered, dual-backend Vault999 operations (Consolidated v55.3).

Theory of Anomalous Contrast applied:
- Only EUREKA insights (score ≥ 0.75) → Permanent VAULT999
- Medium insights (0.50-0.75) → Cooling ledger (SABAR)
- Trivial queries (< 0.50) → TRANSIENT (not stored)

Design: Prevents "tong sampah" (trash bin) accumulation.
"""

from __future__ import annotations

import logging
import os
from datetime import datetime
from typing import Any, Dict, Optional

# Import backends
try:
    from codebase.vault import PersistentVaultLedger, should_use_postgres

    POSTGRES_AVAILABLE = True
except ImportError:
    POSTGRES_AVAILABLE = False

from mcp.session_ledger import get_ledger as get_filesystem_ledger

# Import EUREKA Sieve
from codebase.vault import EUREKASieve, should_seal_to_vault

logger = logging.getLogger("mcp.tools.vault_tool")


# Authority notice included in all vault responses
AUTHORITY_NOTICE = (
    "This seal is generated by arifOS infrastructure. "
    "ChatGPT/LLM is only the caller, not the authority."
)

# Limits for pagination
_MAX_LIMIT = 200
_DEFAULT_LIMIT = 20


async def _get_backend():
    """
    Get the best available backend.

    Priority:
    1. PostgreSQL (if available and configured)
    2. Filesystem (always available)
    """
    if POSTGRES_AVAILABLE and should_use_postgres():
        try:
            ledger = PersistentVaultLedger()
            await ledger.connect()
            return "postgres", ledger
        except Exception as e:
            logger.warning(f"PostgreSQL unavailable, falling back to filesystem: {e}")

    # Fallback to filesystem
    return "filesystem", get_filesystem_ledger()


def _void(reason: str, **extra: Any) -> Dict[str, Any]:
    """Return a VOID response with authority_notice always included."""
    return {
        "operation": "error",
        "verdict": "VOID",
        "reason": reason,
        "authority_notice": AUTHORITY_NOTICE,
        **extra,
    }


def _transient(reason: str, eureka_metadata: Dict, **extra: Any) -> Dict[str, Any]:
    """Return a TRANSIENT response (not stored - too trivial)."""
    return {
        "operation": "transient",
        "verdict": "TRANSIENT",
        "reason": reason,
        "eureka": eureka_metadata,
        "authority_notice": AUTHORITY_NOTICE,
        "message": "Content not meaningful enough for permanent storage. EUREKA Score too low.",
        **extra,
    }


def _sabar(reason: str, eureka_metadata: Dict, **extra: Any) -> Dict[str, Any]:
    """Return a SABAR response (cooling ledger)."""
    return {
        "operation": "cooling",
        "verdict": "SABAR",
        "reason": reason,
        "eureka": eureka_metadata,
        "authority_notice": AUTHORITY_NOTICE,
        "message": "Content in cooling period. Will review after 72h.",
        **extra,
    }


class VaultTool:
    """
    HARDENED VAULT-999: EUREKA-filtered, dual-backend ledger.

    Implements Theory of Anomalous Contrast:
    - VOID: Expensive (requires justification)
    - SABAR: Default (cooling period)
    - SEAL: Earned (EUREKA score ≥ 0.75)
    - TRANSIENT: Trivial (not stored)
    """

    @staticmethod
    async def execute(
        action: str,
        session_id: Optional[str] = None,
        target: str = "seal",
        payload: Optional[Dict] = None,
        # NEW: Trinity results for EUREKA evaluation
        query: Optional[str] = None,
        response: Optional[str] = None,
        trinity_bundle: Optional[Dict] = None,
        **kwargs,
    ) -> Dict[str, Any]:
        """
        Execute vault action with EUREKA filtering.

        For seal action:
        1. Run EUREKA Sieve (Anomalous Contrast evaluation)
        2. Only EUREKA (≥0.75) goes to permanent vault
        3. SABAR (0.50-0.75) goes to cooling ledger
        4. TRANSIENT (<0.50) not stored
        """
        from mcp.core.session_context import get_current_session_id

        payload = payload or {}
        session_id = session_id or get_current_session_id()
        if action == "seal":
            return await VaultTool._seal_with_eureka(
                session_id=session_id,
                payload=payload,
                target=target,
                query=query,
                response=response,
                trinity_bundle=trinity_bundle,
            )
        elif action == "list":
            return await HardenedVaultTool._list(payload)
        elif action == "read":
            return await HardenedVaultTool._read(session_id, payload)
        elif action == "query":
            return await HardenedVaultTool._query(payload)
        elif action == "verify":
            return await HardenedVaultTool._verify()
        elif action == "proof":
            return await HardenedVaultTool._proof(payload)
        else:
            return _void(f"Unknown VAULT action: {action}")

    # ------------------------------------------------------------------ seal with EUREKA

    @staticmethod
    async def _seal_with_eureka(
        session_id: Optional[str],
        payload: Dict[str, Any],
        target: str,
        query: Optional[str],
        response: Optional[str],
        trinity_bundle: Optional[Dict],
    ) -> Dict[str, Any]:
        """
        Seal with EUREKA Sieve filter.

        Implements Theory of Anomalous Contrast:
        - Evaluates novelty, entropy reduction, ontological shift, decision weight
        - Only EUREKA moments (≥0.75) get permanent storage
        """
        if not session_id:
            return _void("session_id required")

        # Default query/response from payload if not provided
        query = query or payload.get("query", "")
        response = response or payload.get("response", "")
        trinity_bundle = trinity_bundle or payload.get("trinity_bundle", {})

        # EUREKA Sieve: Theory of Anomalous Contrast
        should_seal, eureka_metadata = await should_seal_to_vault(
            query=query,
            response=response,
            trinity_bundle=trinity_bundle,
        )

        eureka_score = eureka_metadata.get("eureka_score", 0.0)
        eureka_verdict = eureka_metadata.get("verdict", "TRANSIENT")

        logger.info(
            f"EUREKA Sieve: score={eureka_score:.2f}, verdict={eureka_verdict}, "
            f"query='{query[:50]}...'"
        )

        # TRANSIENT: Don't store trivial queries
        if eureka_verdict == "TRANSIENT":
            return _transient(
                f"EUREKA Score {eureka_score:.2f} < 0.50: Not meaningful enough",
                eureka_metadata,
            )

        # SABAR: Cooling ledger for medium insights
        if eureka_verdict == "SABAR":
            return await VaultTool._seal_to_cooling(
                session_id=session_id,
                payload=payload,
                eureka_metadata=eureka_metadata,
            )

        # SEAL: Permanent vault for EUREKA moments
        return await VaultTool._seal_to_vault(
            session_id=session_id,
            payload=payload,
            target=target,
            eureka_metadata=eureka_metadata,
        )

    @staticmethod
    async def _seal_to_vault(
        session_id: str,
        payload: Dict[str, Any],
        target: str,
        eureka_metadata: Dict[str, Any],
    ) -> Dict[str, Any]:
        """Seal to permanent VAULT999 (PostgreSQL or filesystem)."""
        backend_type, ledger = await _get_backend()

        try:
            verdict = payload.get("verdict", "SEAL")
            authority = payload.get("authority", "system")

            # Build enriched seal_data with EUREKA metadata
            seal_data = dict(payload)
            seal_data["target"] = target
            seal_data["eureka"] = eureka_metadata  # Include EUREKA evaluation

            if backend_type == "postgres":
                receipt = await ledger.append(
                    session_id=session_id,
                    verdict=verdict,
                    seal_data=seal_data,
                    authority=authority,
                )
            else:
                # Filesystem backend
                receipt = ledger.seal_session(
                    session_id=session_id,
                    verdict=verdict,
                    init_result=seal_data.get("init_result", {}),
                    genius_result=seal_data.get("agi_result", {}),
                    act_result=seal_data.get("asi_result", {}),
                    judge_result=seal_data.get("apex_result", {}),
                    telemetry={"eureka": eureka_metadata},
                    context_summary=seal_data.get("query", "")[:200],
                    authority=authority,
                )
                # Convert to dict format
                receipt = {
                    "session_id": receipt.session_id,
                    "seal_id": receipt.seal_id,
                    "entry_hash": receipt.entry_hash,
                    "merkle_root": receipt.merkle_root,
                    "sequence": receipt.sequence,
                }

            return {
                "operation": "sealed",
                "verdict": verdict,
                "sealed": receipt,
                "vault_backend": backend_type,
                "eureka": eureka_metadata,
                "authority_notice": AUTHORITY_NOTICE,
                "message": f"EUREKA Score {eureka_metadata['eureka_score']:.2f}: Permanent seal",
            }
        finally:
            if backend_type == "postgres":
                await ledger.close()

    @staticmethod
    async def _seal_to_cooling(
        session_id: str,
        payload: Dict[str, Any],
        eureka_metadata: Dict[str, Any],
    ) -> Dict[str, Any]:
        """Seal to cooling ledger (SABAR - needs refinement)."""
        import json
        from pathlib import Path

        # Cooling ledger path
        vault_root = Path(os.getenv("VAULT_PATH", "VAULT999"))
        cooling_path = vault_root / "BBB_LEDGER" / "cooling_ledger.jsonl"
        cooling_path.parent.mkdir(parents=True, exist_ok=True)

        cooling_entry = {
            "timestamp": datetime.now().isoformat(),
            "session_id": session_id,
            "verdict": "SABAR",
            "eureka": eureka_metadata,
            "payload": payload,
            "cooling_hours": 72,
            "review_after": (datetime.now().timestamp() + 72 * 3600),
        }

        # Append to cooling ledger
        with open(cooling_path, "a") as f:
            f.write(json.dumps(cooling_entry) + "\n")

        return _sabar(
            f"EUREKA Score {eureka_metadata['eureka_score']:.2f}: Cooling period (72h)",
            eureka_metadata,
        )

    # ------------------------------------------------------------------ list

    @staticmethod
    async def _list(payload: Dict[str, Any]) -> Dict[str, Any]:
        backend_type, ledger = await _get_backend()
        try:
            limit = max(1, min(int(payload.get("limit", _DEFAULT_LIMIT)), _MAX_LIMIT))
            cursor = payload.get("cursor")

            if backend_type == "postgres":
                if cursor is not None:
                    cursor = int(cursor)
                    if cursor < 1:
                        return _void("cursor must be a positive integer")
                listing = await ledger.list_entries(cursor=cursor, limit=limit)
            else:
                # Filesystem list
                chain = ledger._walk_chain()
                entries = []
                for entry in chain[-limit:]:
                    entries.append(
                        {
                            "session_id": entry.session_id,
                            "verdict": entry.verdict,
                            "timestamp": entry.timestamp,
                            "entry_hash": entry.entry_hash,
                        }
                    )
                listing = {"entries": entries, "count": len(entries)}

            return {
                "operation": "list",
                "verdict": "SEAL",
                **listing,
                "vault_backend": backend_type,
                "authority_notice": AUTHORITY_NOTICE,
            }
        finally:
            if backend_type == "postgres":
                await ledger.close()

    # ------------------------------------------------------------------ read

    @staticmethod
    async def _read(session_id: Optional[str], payload: Dict[str, Any]) -> Dict[str, Any]:
        backend_type, ledger = await _get_backend()
        try:
            seq = payload.get("sequence")

            if backend_type == "postgres":
                if seq:
                    entry = await ledger.get_entry_by_sequence(int(seq))
                elif session_id:
                    entry = await ledger.get_entries_by_session(session_id)
                else:
                    return _void("session_id or sequence required")
            else:
                # Filesystem read
                if session_id:
                    entry = ledger.get_session(session_id)
                else:
                    return _void("session_id required for filesystem backend")

            if not entry:
                return _void("Entry not found")

            return {
                "operation": "read",
                "verdict": "SEAL",
                "entry": entry.to_dict() if hasattr(entry, "to_dict") else entry,
                "vault_backend": backend_type,
                "authority_notice": AUTHORITY_NOTICE,
            }
        finally:
            if backend_type == "postgres":
                await ledger.close()

    # ------------------------------------------------------------------ query

    @staticmethod
    async def _query(payload: Dict[str, Any]) -> Dict[str, Any]:
        verdict_filter = payload.get("verdict")
        if not verdict_filter:
            return _void("verdict required")

        start = payload.get("start_time")
        end = payload.get("end_time")

        def _parse(t: Optional[str]) -> Optional[datetime]:
            if not t:
                return None
            return datetime.fromisoformat(t.replace("Z", "+00:00"))

        parsed_start = _parse(start)
        parsed_end = _parse(end)
        if parsed_start and parsed_end and parsed_start > parsed_end:
            return _void("start_time must be <= end_time")

        backend_type, ledger = await _get_backend()
        try:
            if backend_type == "postgres":
                entries = await ledger.query_by_verdict(verdict_filter, parsed_start, parsed_end)
            else:
                # Filesystem query (simple filter)
                chain = ledger._walk_chain()
                entries = [
                    {
                        "session_id": e.session_id,
                        "verdict": e.verdict,
                        "timestamp": e.timestamp,
                    }
                    for e in chain
                    if e.verdict == verdict_filter
                ]

            return {
                "operation": "query",
                "verdict": "SEAL",
                "entries": entries,
                "vault_backend": backend_type,
                "authority_notice": AUTHORITY_NOTICE,
            }
        finally:
            if backend_type == "postgres":
                await ledger.close()

    # ------------------------------------------------------------------ verify

    @staticmethod
    async def _verify() -> Dict[str, Any]:
        backend_type, ledger = await _get_backend()
        try:
            if backend_type == "postgres":
                result = await ledger.verify_chain()
            else:
                # Filesystem verification
                valid, merkle_root = ledger.verify_chain()
                result = {"valid": valid, "merkle_root": merkle_root}

            return {
                "operation": "verify",
                "verdict": "SEAL" if result.get("valid") else "VOID",
                **result,
                "vault_backend": backend_type,
                "authority_notice": AUTHORITY_NOTICE,
            }
        finally:
            if backend_type == "postgres":
                await ledger.close()

    # ------------------------------------------------------------------ proof

    @staticmethod
    async def _proof(payload: Dict[str, Any]) -> Dict[str, Any]:
        seq = payload.get("sequence")
        if not seq:
            return _void("sequence required")

        backend_type, ledger = await _get_backend()
        try:
            if backend_type == "postgres":
                proof = await ledger.get_merkle_proof(int(seq))
            else:
                # Filesystem proof (simplified)
                chain = ledger._walk_chain()
                if seq <= len(chain):
                    entry = chain[seq - 1]
                    proof = {
                        "sequence": seq,
                        "entry_hash": entry.entry_hash,
                        "merkle_root": entry.merkle_root,
                    }
                else:
                    proof = None

            if not proof:
                return _void("proof not found")

            return {
                "operation": "proof",
                "verdict": "SEAL",
                **proof,
                "vault_backend": backend_type,
                "authority_notice": AUTHORITY_NOTICE,
            }
        finally:
            if backend_type == "postgres":
                await ledger.close()


# Backwards compatibility alias
HardenedVaultTool = VaultTool
