from typing import Optional, Any

from analogai.foundation.modules.shared.statement_base import StatementBase
from analogai.foundation.modules.notion.notion import Notion
from analogai.foundation.core.value_objects.modifier import Modifier
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.common.logging.app_logger import app_logger
from analogai.foundation.modules.belief.belief import Belief
from analogai.foundation.common.utils.entity_formatters import format_categorical_deduction_repr


class CategoricalDeduction(StatementBase):
    def __init__(
        self,
        agent_id: str,
        major_premise: Belief,
        minor_premise: Belief,
        subject_notion: Notion,
        complement_notion: Notion,
        relation: Relation,
        id: Optional[str] = None,
        modifier: Optional[Modifier] = None,
    ):
        super().__init__(
            agent_id=agent_id,
            subject_notion=subject_notion,
            complement_notion=complement_notion,
            relation=relation,
            id=id,
            modifier=modifier,
        )
        self._major_premise = major_premise
        self._minor_premise = minor_premise
        self._log_creation()

    @property
    def major_premise(self):
        return self._major_premise

    @property
    def minor_premise(self):
        return self._minor_premise

    @property
    def probability(self) -> float:
        return round(self.major_premise.probability * self.minor_premise.probability, 2)

    @property
    def validity(self) -> float:
        return min(self.major_premise.validity, self.minor_premise.validity)

    def visit(self, visitor: Any) -> Any:
        return visitor.visit_categorical_deduction(self)

    def _log_creation(self):
        from analogai.foundation.common.utils.statement_serializers import serialize_statement
        try:
            probability = float(self.probability)
            serialized = serialize_statement(
                subject_notion_caption=self.subject_notion.caption,
                complement_notion_caption=self.complement_notion.caption,
                relation=self.relation,
                probability=probability,
                modifier=self.modifier,
                subject_attributes=self.subject_notion.attributes,
                complement_attributes=self.complement_notion.attributes,
            )
            app_logger.debug(f"Created CategoricalDeduction: {serialized} (id: {self.id})")
        except (ValueError, AttributeError, TypeError):
            app_logger.debug(f"Created CategoricalDeduction (id: {self.id})")

    def __repr__(self) -> str:
        return format_categorical_deduction_repr(self)