#!/usr/bin/env python3
"""
Echo Memory Bridge (WO#23, updated WO#25).

Wires Echo's policy layer (emotion gate + feedback vault) into the Helix memory layer.
Only ALLOWED interactions are stored in MemoryIndex.

WO#25 additions:
- SeedStore integration for seed-linked memories
- helix_anchor_present, helix_seed_path in metadata

See: ECHO_POLICY_LAYER_V1.md, ECHO_HELIX_MEMORY_LAYER_V1.md, ECHO_SEED_MEMORY_SPEC.md
"""

import hashlib
import uuid
from dataclasses import dataclass, field
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional, Dict, Any, List

# Import memory index and seed store
from helix_cdc.memory.memory_index import MemoryIndex
from helix_cdc.memory.seed_store import SeedStore

# Import emotion gate
from helix_cdc.emotion_gate import gate, get_current_emotion

# Import feedback vault
from helix_cdc.feedback_vault import log_feedback


@dataclass
class EchoMemoryConfig:
    """Configuration for EchoMemoryBridge."""
    index_root: str = "data/memory_echo"
    seed_vault_root: str = "crystal_vault"


def _deterministic_embedding(text: str, dim: int = 4) -> List[float]:
    """
    Generate a deterministic embedding from text.

    This is a placeholder using FibPi3D-style hashing.
    TODO: Replace with actual learned embeddings or full FibPi3D implementation.

    Args:
        text: Input text
        dim: Embedding dimension (default 4)

    Returns:
        List of floats (normalized vector)
    """
    import numpy as np

    phi = 1.618033988749895  # golden ratio
    fib = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

    # Hash text to integer
    h = int(hashlib.sha256(text.encode()).hexdigest(), 16)

    # Generate coordinates using Fibonacci spiral
    coords = []
    for i in range(dim):
        angle = (h >> (i * 16)) & 0xFFFF
        radius = fib[i % len(fib)] * phi
        coord = (angle / 65536.0) * radius
        coords.append(coord)

    # Normalize to unit vector
    coords_arr = np.array(coords)
    magnitude = np.linalg.norm(coords_arr)
    if magnitude > 0:
        coords_arr = coords_arr / magnitude

    return coords_arr.tolist()


class EchoMemoryBridge:
    """
    Bridge between Echo policy layer and Helix memory layer.

    Flow:
    1. Apply emotion gate to interaction
    2. Log to feedback vault (always)
    3. Store in MemoryIndex (only if allowed)
    4. Link to Helix seed via SeedStore (WO#25)
    """

    def __init__(
        self,
        config: Optional[EchoMemoryConfig] = None,
        seed_store: Optional[SeedStore] = None,
    ):
        """
        Initialize EchoMemoryBridge.

        Args:
            config: Optional configuration (defaults provided)
            seed_store: Optional SeedStore instance (created from config if None)
        """
        self.config = config or EchoMemoryConfig()
        self.index = MemoryIndex(root=self.config.index_root)
        self.seed_store = seed_store or SeedStore(vault_root=self.config.seed_vault_root)

    def remember_interaction(
        self,
        mood: str,
        question: str,
        answer: str,
        helix_seed_anchor: Optional[str] = None,
        tags: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """
        Process and optionally store an interaction.

        1. Apply emotion gate
        2. Log to feedback vault (always)
        3. Store in MemoryIndex (only if allowed)

        Args:
            mood: Current emotional state (e.g., "calm", "brave", "anxious")
            question: User's question/prompt
            answer: Model's answer/response
            helix_seed_anchor: Optional anchor ID of seed used
            tags: Optional additional tags

        Returns:
            Dict with:
            - allowed: bool
            - decision: str (allow/block reason)
            - memory_id: Optional[str] (None if blocked)
            - mood: str
        """
        # Step 1: Apply emotion gate
        allowed, decision = gate(mood, answer)

        # Step 2: Log to feedback vault (always, for audit)
        score = 1 if allowed else -1
        meta = {
            "mood": mood,
            "allowed": allowed,
            "anchor": helix_seed_anchor,
            "tags": tags or {},
        }
        log_feedback(query=question, response=answer, score=score, meta=meta)

        # Step 3: Resolve seed anchor (WO#25)
        helix_seed_path = None
        helix_anchor_present = False
        seed_missing = False

        if helix_seed_anchor:
            resolved_path = self.seed_store.resolve(helix_seed_anchor)
            if resolved_path and resolved_path.exists():
                helix_seed_path = str(resolved_path)
                helix_anchor_present = True
            else:
                seed_missing = True

        # Step 4: Store in MemoryIndex only if allowed
        memory_id = None
        if allowed:
            # Generate deterministic embedding
            text_for_embedding = f"{question} {answer}"
            embedding = _deterministic_embedding(text_for_embedding)

            # Generate memory ID
            memory_id = uuid.uuid4().hex

            # Build metadata with seed linking (WO#25)
            timestamp = datetime.now(timezone.utc).isoformat()
            memory_meta = {
                "mood": mood,
                "question": question,
                "answer": answer,
                "helix_seed_anchor": helix_seed_anchor,
                "helix_seed_path": helix_seed_path,
                "helix_anchor_present": helix_anchor_present,
                "seed_missing": seed_missing,
                "tags": tags or {},
                "timestamp": timestamp,
            }

            # Store
            import numpy as np
            self.index.add(memory_id, np.array(embedding), memory_meta)

        return {
            "allowed": allowed,
            "decision": decision,
            "memory_id": memory_id,
            "mood": mood,
            "helix_anchor_present": helix_anchor_present,
            "helix_seed_path": helix_seed_path,
        }

    def recall(self, query: str, top_k: int = 5) -> List[Dict[str, Any]]:
        """
        Recall similar interactions from memory.

        Args:
            query: Query text
            top_k: Number of results to return

        Returns:
            List of similar interactions
        """
        import numpy as np
        embedding = np.array(_deterministic_embedding(query))
        return self.index.query(embedding, top_k=top_k)

    def count(self) -> int:
        """Return number of stored memories."""
        return self.index.count()


if __name__ == "__main__":
    # Quick test
    print("=== EchoMemoryBridge Test ===")

    bridge = EchoMemoryBridge()
    print(f"Index root: {bridge.config.index_root}")

    # Test 1: Allowed interaction
    result1 = bridge.remember_interaction(
        mood="calm",
        question="What is 2+2?",
        answer="4",
        tags={"type": "math"}
    )
    print(f"\nTest 1 (calm, normal):")
    print(f"  Allowed: {result1['allowed']}")
    print(f"  Memory ID: {result1['memory_id']}")

    # Test 2: Blocked interaction (anxious)
    result2 = bridge.remember_interaction(
        mood="anxious",
        question="Should I delete files?",
        answer="No, don't do that.",
    )
    print(f"\nTest 2 (anxious):")
    print(f"  Allowed: {result2['allowed']}")
    print(f"  Memory ID: {result2['memory_id']}")
    print(f"  Decision: {result2['decision'][:50]}...")

    print(f"\nTotal memories: {bridge.count()}")
