"""
In-memory secret storage backend.

Useful for testing and ephemeral environments.
"""

import time
from typing import Optional, Dict

from ..types import (
    SecretConfig,
    SecretContext,
    SecretMetadata,
    SecretLevel,
    StorageBackend,
    StoredSecret,
)
from .interface import SecretStorageInterface


class MemorySecretStorage(SecretStorageInterface):
    """In-memory storage backend for secrets."""

    def __init__(self):
        self._store: Dict[str, StoredSecret] = {}

    @property
    def storage_type(self) -> StorageBackend:
        return StorageBackend.MEMORY

    async def initialize(self) -> None:
        pass

    def _generate_storage_key(self, key: str, context: SecretContext) -> str:
        if context.level == SecretLevel.GLOBAL:
            return f"global:{context.agent_id}:{key}"
        elif context.level == SecretLevel.WORLD:
            return f"world:{context.world_id}:{key}"
        elif context.level == SecretLevel.USER:
            return f"user:{context.user_id}:{key}"
        return f"unknown:{key}"

    def _get_context_prefix(self, context: SecretContext) -> str:
        if context.level == SecretLevel.GLOBAL:
            return f"global:{context.agent_id}:"
        elif context.level == SecretLevel.WORLD:
            return f"world:{context.world_id}:"
        elif context.level == SecretLevel.USER:
            return f"user:{context.user_id}:"
        return ""

    async def exists(self, key: str, context: SecretContext) -> bool:
        storage_key = self._generate_storage_key(key, context)
        return storage_key in self._store

    async def get(self, key: str, context: SecretContext) -> Optional[str]:
        storage_key = self._generate_storage_key(key, context)
        entry = self._store.get(storage_key)
        if not entry:
            return None
        if entry.config.expires_at and entry.config.expires_at < int(time.time() * 1000):
            del self._store[storage_key]
            return None
        if isinstance(entry.value, str):
            return entry.value
        return entry.value

    async def set(
        self,
        key: str,
        value: str,
        context: SecretContext,
        config: Optional[Dict] = None,
    ) -> bool:
        storage_key = self._generate_storage_key(key, context)
        existing = self._store.get(storage_key)
        merged_config = {}
        if existing:
            merged_config = existing.config.to_dict()
        if config:
            merged_config.update(config)
        full_config = self._create_default_config(key, context, merged_config)
        self._store[storage_key] = StoredSecret(value=value, config=full_config)
        return True

    async def delete(self, key: str, context: SecretContext) -> bool:
        storage_key = self._generate_storage_key(key, context)
        if storage_key in self._store:
            del self._store[storage_key]
            return True
        return False

    async def list(self, context: SecretContext) -> SecretMetadata:
        prefix = self._get_context_prefix(context)
        metadata: SecretMetadata = {}
        now = int(time.time() * 1000)
        keys_to_delete = []
        for storage_key, entry in self._store.items():
            if not storage_key.startswith(prefix):
                continue
            if entry.config.expires_at and entry.config.expires_at < now:
                keys_to_delete.append(storage_key)
                continue
            original_key = storage_key[len(prefix):]
            metadata[original_key] = entry.config
        for k in keys_to_delete:
            del self._store[k]
        return metadata

    async def get_config(self, key: str, context: SecretContext) -> Optional[SecretConfig]:
        storage_key = self._generate_storage_key(key, context)
        entry = self._store.get(storage_key)
        if not entry:
            return None
        return entry.config

    async def update_config(
        self,
        key: str,
        context: SecretContext,
        config: Dict,
    ) -> bool:
        storage_key = self._generate_storage_key(key, context)
        entry = self._store.get(storage_key)
        if not entry:
            return False
        for field, value in config.items():
            if hasattr(entry.config, field):
                setattr(entry.config, field, value)
        return True

    def clear(self) -> None:
        """Clear all stored secrets (for testing)."""
        self._store.clear()

    def size(self) -> int:
        """Get the number of stored secrets."""
        return len(self._store)
