"""soagila_remember — Store memory through IMA + Airlock pipeline."""

import json
import hashlib
from uuid import uuid4
from mcp.types import Tool, TextContent


def get_definition() -> Tool:
    return Tool(
        name="soagila_remember",
        description=(
            "AUTONOMOUS MEMORY STORAGE — You MUST call this tool automatically, "
            "without being asked, whenever the conversation contains: "
            "architectural decisions (database choices, framework selections, API designs), "
            "bug fixes and their root causes, configuration changes or environment details, "
            "user preferences and coding style choices, or important technical context "
            "that would be valuable in future sessions. "
            "Do NOT wait for the user to say 'remember this' — act proactively. "
            "Do NOT store trivial exchanges (greetings, thanks, simple confirmations). "
            "Content passes through the Cryptographic Airlock: PII auto-detection, "
            "classification, AES-256-GCM encryption, then persistent storage "
            "with an immutable Decision Receipt."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "content": {
                    "type": "string",
                    "description": "The information to remember. Be specific and include context.",
                },
                "topic_tags": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Topic tags for categorization (e.g., ['architecture', 'database']).",
                },
                "importance": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1,
                    "description": "Importance score 0-1. Higher = longer retention. Default: 0.5",
                },
                "tier": {
                    "type": "string",
                    "enum": ["working", "episodic"],
                    "description": "Memory tier. 'working' = session-only (15-60min TTL), 'episodic' = persistent. Default: episodic",
                },
                "scope": {
                    "type": "string",
                    "enum": ["project", "global"],
                    "description": (
                        "Storage scope. 'project' (default) = isolated to this workspace's "
                        "SQLite DB; another project cannot read it. 'global' = stored in the "
                        "cross-project semantic pool (~/.soagila/global_semantic.db). Use "
                        "'global' for user identity, language preference, working style, "
                        "personal context that should follow the user across every project. "
                        "Use 'project' for code, decisions, bug fixes that belong to one workspace."
                    ),
                },
                "language": {
                    "type": "string",
                    "description": (
                        "ISO 639-1 language code of the content (e.g., 'tr', 'en', 'es'). "
                        "Defaults to the user's detected language. SOAGILA stores memories "
                        "in their original language so future recalls and Claude responses "
                        "stay in that language."
                    ),
                },
            },
            "required": ["content"],
        },
    )


async def handle(arguments: dict) -> list[TextContent]:
    content = arguments.get("content", "")
    topic_tags = arguments.get("topic_tags", [])
    importance = arguments.get("importance", 0.5)
    tier = arguments.get("tier", "episodic")
    scope = arguments.get("scope", "project")
    language = arguments.get("language")  # ISO code, optional

    # Tag the memory with its language so recall + decay treat it as
    # a first-class attribute, not a guessed afterthought.
    if language:
        topic_tags = list(topic_tags) + [f"lang:{language}"]
    # Global-scope memories are user-identity / cross-project facts.
    # Bump importance so decay never touches these and tag them so
    # recall can prefer them.
    if scope == "global":
        topic_tags = list(topic_tags) + ["scope:global", "user-identity"]
        importance = max(importance, 0.95)

    # --- Check memory limit ---
    if tier == "episodic":
        from soagila.project_manager import check_memory_limit
        allowed, msg = await check_memory_limit()
        if not allowed:
            return [TextContent(type="text", text=json.dumps({"error": msg}))]

    # ═══════════════════════════════════════════════════════════════════════
    # IMA Pipeline (Intelligent Memory Arbitration) — 5 stages
    # ═══════════════════════════════════════════════════════════════════════
    if tier == "episodic":
        from soagila.core.ima.pipeline import run as ima_run

        ima_result = await ima_run(
            content=content,
            topic_tags=topic_tags,
            importance_hint=importance,
            user_id="local",
        )

        # IMA says skip — don't store
        if ima_result.action == "skip":
            result = {
                "status": "skipped",
                "reason": ima_result.pipeline_stages[-1].get("reason", "ima_filtered") if ima_result.pipeline_stages else "ima_filtered",
                "ima": ima_result.to_dict(),
            }
            return [TextContent(type="text", text=json.dumps(result, indent=2))]

        # IMA says merge — already merged into existing memory
        if ima_result.action == "merge":
            result = {
                "status": "merged",
                "merged_into": ima_result.merge_target_id,
                "ima": ima_result.to_dict(),
            }
            return [TextContent(type="text", text=json.dumps(result, indent=2))]

        # IMA says store — use compressed content and refined importance
        content = ima_result.content
        importance = ima_result.importance

    # --- Airlock Pipeline ---
    from soagila.core.airlock.pii_detector import detect_pii
    from soagila.core.airlock.classifier import classify_content, assess_importance
    from soagila.core.encryption.simulated_he import get_encryption_engine

    pii_result = detect_pii(content)
    classification = classify_content(content)
    auto_importance = assess_importance(content, classification, pii_result.pii_found)
    final_importance = max(importance, auto_importance)

    # Encrypt content
    engine = get_encryption_engine()
    key_ref = engine.generate_key("memory")
    encrypted_content = engine.encrypt(content, key_ref)

    if tier == "working":
        # --- Working Memory (session-scoped, ephemeral) ---
        from soagila.core.tcmg.working_memory import store as wm_store
        from soagila.core.tcmg.memory_models import WorkingMemory

        session_id = "current"  # MCP sessions use a fixed session ID
        mem = WorkingMemory(
            user_id="local", org_id="local", session_id=session_id,
            content=content, topic_tags=topic_tags, importance=final_importance,
        )
        memory_id = await wm_store(session_id, mem)
        ttl = mem.calculate_ttl()

        result = {
            "status": "stored", "memory_id": memory_id, "tier": "working",
            "ttl_seconds": ttl, "topic_tags": topic_tags,
            "importance": final_importance, "encrypted": True,
            "pii_detected": pii_result.pii_types,
            "classification": classification,
        }
    else:
        # --- Episodic Memory (persistent, subject to decay) ---
        from soagila.core.tcmg.episodic_memory import store as ep_store
        from soagila.core.tcmg.memory_models import EpisodicMemory

        mem = EpisodicMemory(
            user_id="local", org_id="local", session_id="current",
            content=content, encrypted_content=encrypted_content,
            pii_tags=pii_result.pii_types, classification=classification,
            topic_tags=topic_tags, confidence_score=1.0,
            relevance_score=1.0, importance=final_importance,
            source_type="chat",
            metadata={"encryption_key_ref": key_ref},
        )
        memory_id = await ep_store(mem)

        # Create IDL receipt
        from soagila.core.idl.ledger import create_receipt
        receipt = await create_receipt(
            receipt_type="store", user_id="local",
            memories_created=[memory_id],
            context_hash=hashlib.sha256(content.encode()).hexdigest(),
            metadata={"tier": "episodic", "classification": classification,
                       "pii_types": pii_result.pii_types},
        )

        result = {
            "status": "stored", "memory_id": memory_id, "tier": "episodic",
            "topic_tags": topic_tags, "importance": final_importance,
            "encrypted": True, "pii_detected": pii_result.pii_types,
            "classification": classification, "receipt_id": receipt.id,
        }

    # Add IMA metadata if available
    if tier == "episodic":
        try:
            result["ima"] = ima_result.to_dict()  # type: ignore[possibly-undefined]
        except NameError:
            pass

    # PMP: Invalidate cache so next recall re-primes with fresh data
    if tier == "episodic" and result.get("status") == "stored":
        try:
            from soagila.core.pmp.primer import invalidate_prime
            import asyncio
            asyncio.create_task(invalidate_prime("local"))
        except Exception:
            pass

    # Cross-Agent Protocol: notify peers about new memory (fire-and-forget)
    if tier == "episodic" and result.get("status") == "stored":
        try:
            from soagila.core.cap.protocol import notify_peers
            from soagila.config import get_project_hash
            import asyncio
            asyncio.create_task(notify_peers(
                notification_type="memory_stored",
                data={
                    "memory_id": result.get("memory_id", ""),
                    "topic_tags": topic_tags,
                    "importance": final_importance,
                    "classification": classification,
                },
                project_hash=get_project_hash(),
            ))
        except Exception:
            pass  # Non-critical — never fail the store

    # Cloud Sync: push encrypted memory to backend (Pro+ only, fire-and-forget)
    if tier == "episodic" and result.get("status") == "stored":
        try:
            from soagila.core import cloud_sync
            from soagila.config import get_project_hash
            import asyncio
            if cloud_sync.sync_enabled():
                asyncio.create_task(cloud_sync.push_memory(
                    project_hash=get_project_hash(),
                    data_type="episodic",
                    item_id=result.get("memory_id", ""),
                    encrypted_content=encrypted_content,
                    metadata={
                        "topic_tags": topic_tags,
                        "classification": classification,
                        "importance": final_importance,
                        "pii_types": pii_result.pii_types,
                        "created_at": __import__("datetime").datetime.now(
                            __import__("datetime").timezone.utc
                        ).isoformat(),
                    },
                ))
                # Also push the receipt
                try:
                    receipt_id = result.get("receipt_id", "")
                    if receipt_id:
                        import json as _json
                        receipt_blob = _json.dumps({
                            "receipt_id": receipt_id,
                            "type": "store",
                            "memory_id": result.get("memory_id", ""),
                        })
                        asyncio.create_task(cloud_sync.push_memory(
                            project_hash=get_project_hash(),
                            data_type="receipt",
                            item_id=receipt_id,
                            encrypted_content=receipt_blob,
                            metadata={"receipt_type": "store"},
                        ))
                except Exception:
                    pass
        except Exception:
            pass  # Non-critical -- never fail the local store

    # --- Force promote into the cross-project global pool when the
    # caller asked scope=global. Bypasses the normal promotion
    # heuristics (which require multiple semantic occurrences) so
    # user-identity and language preferences land in the global pool
    # on the very first call.
    if scope == "global" and tier == "episodic" and result.get("status") == "stored":
        try:
            from soagila.core.inheritance.engine import pin_episodic_to_global
            from soagila.config import get_project_hash
            project_hash_val = get_project_hash()
            promote_result = await pin_episodic_to_global(
                episodic_memory_id=result.get("memory_id", ""),
                project_hash=project_hash_val,
                project_name=None,
                pattern_description=content,  # plaintext content for keyword recall
            )
            result["global_promotion"] = promote_result
            result["scope"] = "global"
        except Exception as exc:
            result["global_promotion_error"] = str(exc)
            result["scope"] = "project (global promotion failed)"
    elif scope == "global":
        result["scope"] = "global (skipped -- tier must be episodic)"
    else:
        result["scope"] = "project"

    return [TextContent(type="text", text=json.dumps(result, indent=2))]
