from __future__ import annotations

from datetime import datetime
from typing import Optional

from synthetic_agents.database.entity.life_memory import LifeMemory as DBLifeMemory
from synthetic_agents.database.entity.memory import Memory as DBMemory
from synthetic_agents.model.entity.memory import Memory

LIFE_MEMORY_TYPE = "life"


class LifeMemory(Memory):
    """
    This class represents a life memory.
    """

    def __init__(
        self,
        creation_timestamp: datetime,
        content: str,
        memory_id: Optional[int] = None,
        similarity_score: float = 0,
        relevance_score: float = 0,
    ):
        """
        Creates a life memory.

        :param creation_timestamp: when the memory was created.
        :param content: textual content of the memory.
        :param memory_id: ID of the memory. It is optional because not persisted memories do not
            have an ID yet.
        :param similarity_score: similarity score between the memory and query used to retrieve the
            memory.
        :param relevance_score: score attributed to relevance during the memory ranking phase.
        :raise: ValueError: raised if the category if not a valid one.
        """
        super().__init__(
            named_type=LIFE_MEMORY_TYPE,
            creation_timestamp=creation_timestamp,
            content=content,
            memory_id=memory_id,
            similarity_score=similarity_score,
            relevance_score=relevance_score,
        )

    def to_persistent_object(self, agent_id: int) -> DBMemory:
        """
        Gets a relational DB representation of the memory for persistence.

        :param agent_id: id of the agent associated with the memory.
        :return: a persistent memory object.
        """

        return DBLifeMemory(
            memory_id=self.memory_id,
            agent_id=agent_id,
            creation_timestamp=self.creation_timestamp,
            content=self.content,
        )

    @classmethod
    def from_persistent_object(cls, db_memory: DBLifeMemory) -> LifeMemory:
        """
        Gets a life memory object from its relational DB representation.

        :param db_memory: relational DB instance of a life memory.
        :return: a life memory object.
        """

        return LifeMemory(
            memory_id=db_memory.memory_id,
            creation_timestamp=db_memory.creation_timestamp,
            content=db_memory.content,
        )
