"""
Storage interface definitions.

Defines the abstract contract and composite pattern for secret storage backends.
"""

from abc import ABC, abstractmethod
from typing import Optional, Dict
import time

from ..types import (
    SecretConfig,
    SecretContext,
    SecretMetadata,
    SecretLevel,
    SecretType,
    SecretStatus,
    StorageBackend,
)


class SecretStorageInterface(ABC):
    """Abstract interface for secret storage backends."""

    @property
    @abstractmethod
    def storage_type(self) -> StorageBackend:
        """Get the storage backend type."""
        pass

    @abstractmethod
    async def initialize(self) -> None:
        """Initialize the storage backend."""
        pass

    @abstractmethod
    async def exists(self, key: str, context: SecretContext) -> bool:
        """Check if a secret exists."""
        pass

    @abstractmethod
    async def get(self, key: str, context: SecretContext) -> Optional[str]:
        """Get a secret value."""
        pass

    @abstractmethod
    async def set(
        self,
        key: str,
        value: str,
        context: SecretContext,
        config: Optional[Dict] = None,
    ) -> bool:
        """Set a secret value."""
        pass

    @abstractmethod
    async def delete(self, key: str, context: SecretContext) -> bool:
        """Delete a secret."""
        pass

    @abstractmethod
    async def list(self, context: SecretContext) -> SecretMetadata:
        """List all secrets in a context."""
        pass

    @abstractmethod
    async def get_config(self, key: str, context: SecretContext) -> Optional[SecretConfig]:
        """Get secret configuration without value."""
        pass

    @abstractmethod
    async def update_config(
        self,
        key: str,
        context: SecretContext,
        config: Dict,
    ) -> bool:
        """Update secret configuration."""
        pass

    def _create_default_config(
        self,
        key: str,
        context: SecretContext,
        partial: Optional[Dict] = None,
    ) -> SecretConfig:
        """Create a default secret configuration."""
        partial = partial or {}
        now = int(time.time() * 1000)

        return SecretConfig(
            type=SecretType(partial.get("type", "secret")),
            required=partial.get("required", False),
            description=partial.get("description", f"Secret: {key}"),
            can_generate=partial.get("canGenerate", False),
            validation_method=partial.get("validationMethod"),
            status=SecretStatus(partial.get("status", "valid")),
            last_error=partial.get("lastError"),
            attempts=partial.get("attempts", 0),
            created_at=partial.get("createdAt") or now,
            validated_at=partial.get("validatedAt") or now,
            plugin=partial.get("plugin", context.level.value),
            level=context.level,
            owner_id=context.user_id,
            world_id=context.world_id,
            encrypted=partial.get("encrypted", True),
            permissions=[],
            shared_with=[],
            expires_at=partial.get("expiresAt"),
        )


class CompositeSecretStorage(SecretStorageInterface):
    """
    Composite storage that delegates to different backends based on context level.
    """

    def __init__(
        self,
        global_storage: SecretStorageInterface,
        world_storage: SecretStorageInterface,
        user_storage: SecretStorageInterface,
    ):
        self._global_storage = global_storage
        self._world_storage = world_storage
        self._user_storage = user_storage

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

    async def initialize(self) -> None:
        await self._global_storage.initialize()
        await self._world_storage.initialize()
        await self._user_storage.initialize()

    def _get_storage_for_context(self, context: SecretContext) -> SecretStorageInterface:
        if context.level == SecretLevel.GLOBAL:
            return self._global_storage
        elif context.level == SecretLevel.WORLD:
            return self._world_storage
        elif context.level == SecretLevel.USER:
            return self._user_storage
        else:
            return self._global_storage

    async def exists(self, key: str, context: SecretContext) -> bool:
        return await self._get_storage_for_context(context).exists(key, context)

    async def get(self, key: str, context: SecretContext) -> Optional[str]:
        return await self._get_storage_for_context(context).get(key, context)

    async def set(
        self,
        key: str,
        value: str,
        context: SecretContext,
        config: Optional[Dict] = None,
    ) -> bool:
        return await self._get_storage_for_context(context).set(key, value, context, config)

    async def delete(self, key: str, context: SecretContext) -> bool:
        return await self._get_storage_for_context(context).delete(key, context)

    async def list(self, context: SecretContext) -> SecretMetadata:
        return await self._get_storage_for_context(context).list(context)

    async def get_config(self, key: str, context: SecretContext) -> Optional[SecretConfig]:
        return await self._get_storage_for_context(context).get_config(key, context)

    async def update_config(
        self,
        key: str,
        context: SecretContext,
        config: Dict,
    ) -> bool:
        return await self._get_storage_for_context(context).update_config(key, context, config)
