"""
In-Memory Metadata Store Implementation

Contract-centric in-memory store keyed by (contract_name, contract_version).
Useful for testing and development.
"""

from __future__ import annotations

import copy
from typing import Any

from pycharter.metadata_store.client import MetadataStoreClient


class InMemoryMetadataStore(MetadataStoreClient):
    """
    In-memory metadata store keyed by (contract_name, contract_version).
    All data is lost when the instance is destroyed.
    """

    def __init__(self):
        """Initialize in-memory store."""
        super().__init__()
        self._contracts: dict[tuple[str, str], dict[str, Any]] = {}

    def connect(self) -> None:
        """No-op for in-memory."""
        self._connection = "connected"

    def disconnect(self) -> None:
        """No-op."""
        self._connection = None

    def _entry(self, contract_name: str, contract_version: str) -> dict[str, Any]:
        key = (contract_name, contract_version)
        if key not in self._contracts:
            self._contracts[key] = {}
        return self._contracts[key]

    def store_schema(
        self,
        contract_name: str,
        contract_version: str,
        schema: dict[str, Any],
    ) -> str:
        """Store a schema for the given data contract. Returns synthetic contract id."""
        from pycharter.shared.name_validator import validate_schema_table_names

        schema = dict(schema)
        if "version" not in schema:
            schema["version"] = contract_version
        validate_schema_table_names(schema)
        self._entry(contract_name, contract_version)["schema"] = copy.deepcopy(schema)
        return f"{contract_name}:{contract_version}"

    def get_schema(self, contract_name: str, contract_version: str) -> dict[str, Any]:
        """Retrieve the schema for the given data contract."""
        entry = self._contracts.get((contract_name, contract_version), {})
        schema = entry.get("schema")
        if schema is None:
            return None
        return copy.deepcopy(schema)

    def list_contracts(self) -> list[dict[str, Any]]:
        """List all stored data contracts."""
        return [{"name": n, "version": v} for (n, v) in self._contracts.keys()]

    def store_metadata(
        self,
        contract_name: str,
        contract_version: str,
        metadata: dict[str, Any],
    ) -> str:
        """Store metadata for the given data contract."""
        from pycharter.db.metadata_normalizer import ensure_canonical

        canonical = ensure_canonical(metadata)
        self._entry(contract_name, contract_version)["metadata"] = copy.deepcopy(
            canonical
        )
        return f"{contract_name}:{contract_version}:metadata"

    def get_metadata(self, contract_name: str, contract_version: str) -> dict[str, Any]:
        """Retrieve metadata for the given data contract."""
        entry = self._contracts.get((contract_name, contract_version), {})
        meta = entry.get("metadata")
        return copy.deepcopy(meta) if meta is not None else None

    def store_coercion_rules(
        self,
        contract_name: str,
        contract_version: str,
        coercion_rules: dict[str, Any],
    ) -> str:
        """Store coercion rules for the given data contract."""
        self._entry(contract_name, contract_version)["coercion_rules"] = copy.deepcopy(
            coercion_rules
        )
        return f"{contract_name}:{contract_version}:coercion"

    def get_coercion_rules(
        self, contract_name: str, contract_version: str
    ) -> dict[str, Any]:
        """Retrieve coercion rules for the given data contract."""
        entry = self._contracts.get((contract_name, contract_version), {})
        rules = entry.get("coercion_rules")
        return copy.deepcopy(rules) if rules is not None else None

    def store_validation_rules(
        self,
        contract_name: str,
        contract_version: str,
        validation_rules: dict[str, Any],
    ) -> str:
        """Store validation rules for the given data contract."""
        self._entry(contract_name, contract_version)["validation_rules"] = (
            copy.deepcopy(validation_rules)
        )
        return f"{contract_name}:{contract_version}:validation"

    def get_validation_rules(
        self, contract_name: str, contract_version: str
    ) -> dict[str, Any]:
        """Retrieve validation rules for the given data contract."""
        entry = self._contracts.get((contract_name, contract_version), {})
        rules = entry.get("validation_rules")
        return copy.deepcopy(rules) if rules is not None else None

    # -- ontology (wiki) ---------------------------------------------------

    def store_ontology(
        self,
        contract_name: str,
        contract_version: str,
        ontology: dict[str, Any],
    ) -> str:
        """Store ontology annotations for the given data contract."""
        self._entry(contract_name, contract_version)["ontology"] = copy.deepcopy(
            ontology
        )
        return f"{contract_name}:{contract_version}:ontology"

    def get_ontology(self, contract_name: str, contract_version: str) -> dict[str, Any]:
        """Retrieve ontology annotations for the given data contract."""
        entry = self._contracts.get((contract_name, contract_version), {})
        onto = entry.get("ontology")
        return copy.deepcopy(onto) if onto is not None else None
