"""Metadata classes for mosh objects."""

from dataclasses import dataclass, field
from datetime import UTC, datetime
from typing import Generic, TypeVar
from uuid import uuid4

from pydantic import BaseModel


def _utc_now() -> datetime:
    """Return current UTC time as timezone-aware datetime."""
    return datetime.now(UTC)


@dataclass
class ObjectMetadata:
    """Metadata for a stored object.

    Managed by the Pit, separate from user's BaseModel data.
    """

    id: str = field(default_factory=lambda: str(uuid4()))
    created_at: datetime = field(default_factory=_utc_now)
    updated_at: datetime = field(default_factory=_utc_now)
    tags: list[str] = field(default_factory=list)
    type_name: str = ""

    def touch(self) -> None:
        """Update the updated_at timestamp to now."""
        self.updated_at = datetime.now(UTC)

    def add_tag(self, tag: str) -> None:
        """Add a tag if not already present."""
        if tag not in self.tags:
            self.tags.append(tag)

    def remove_tag(self, tag: str) -> bool:
        """Remove a tag if present. Returns True if tag was removed."""
        if tag in self.tags:
            self.tags.remove(tag)
            return True
        return False

    def has_tag(self, tag: str) -> bool:
        """Check if object has a specific tag."""
        return tag in self.tags

    def has_any_tag(self, tags: list[str]) -> bool:
        """Check if object has any of the specified tags."""
        return any(tag in self.tags for tag in tags)

    def has_all_tags(self, tags: list[str]) -> bool:
        """Check if object has all of the specified tags."""
        return all(tag in self.tags for tag in tags)


T = TypeVar("T", bound=BaseModel)


@dataclass
class StoredObject(Generic[T]):
    """A wrapper pairing a user's BaseModel with its metadata.

    This is what Pit returns from get(), all(), and search() operations.
    """

    metadata: ObjectMetadata
    obj: T

    @property
    def id(self) -> str:
        """Convenience property to access the object's ID."""
        return self.metadata.id

    @property
    def created_at(self) -> datetime:
        """Convenience property to access created_at timestamp."""
        return self.metadata.created_at

    @property
    def updated_at(self) -> datetime:
        """Convenience property to access updated_at timestamp."""
        return self.metadata.updated_at

    @property
    def tags(self) -> list[str]:
        """Convenience property to access tags."""
        return self.metadata.tags

    @property
    def type_name(self) -> str:
        """Convenience property to access type name."""
        return self.metadata.type_name
