from typing import List

from analogai.foundation.modules.conditionals.hypothetical_statement import HypotheticalStatement
from analogai.foundation.modules.conditionals.hypothetical_statement_repository import HypotheticalStatementRepository
from analogai.foundation.core.value_objects.cause import Cause
from analogai.foundation.core.value_objects.effect import Effect
from analogai.foundation.common.enums.criterion import Criterion
from analogai.foundation.common.enums.certainty import certainty_from_value
from analogai.foundation.core.value_objects.relation import Relation


class HypotheticalStatementService:
    def __init__(
        self,
        hypothetical_statement_repository: HypotheticalStatementRepository,
    ):
        self._hypothetical_statement_repository = hypothetical_statement_repository

    def create(
        self,
        user_id: str,
        agent_id: str,
        causes: List[Cause],
        effect: Effect,
        probability: float = 1.0,
        validity: float = 1.0,
        effect_belief_id: str | None = None,
    ) -> HypotheticalStatement:
        if effect is None:
            raise ValueError("Effect is required")
        if any(not isinstance(cause, Cause) for cause in (causes or [])):
            raise ValueError("Causes must be Cause objects")
        subject_caption = effect.criteria.get(Criterion.SubjectCaption)
        object_caption = effect.criteria.get(Criterion.ObjectCaption)
        relation = effect.criteria.get(Criterion.Relation)
        if not subject_caption or not object_caption or not relation:
            raise ValueError("Effect must contain SubjectCaption, ObjectCaption, and Relation")
        if not isinstance(relation, Relation):
            raise TypeError("Effect criterion Relation must be a Relation instance")
        certainty_value = effect.criteria.get(Criterion.Certainty)
        probability = certainty_from_value(certainty_value).to_probability()
        hypothetical = HypotheticalStatement(
            agent_id=agent_id,
            causes=causes,
            effect=effect,
            probability=probability,
            validity=validity,
            effect_belief_id=effect_belief_id,
        )
        result = self._hypothetical_statement_repository.create(hypothetical)
        return result

    def find(self, agent_id: str) -> List[HypotheticalStatement]:
        return self._hypothetical_statement_repository.find_by_agent_id(agent_id)

    def find_by_agent_id(self, agent_id: str) -> List[HypotheticalStatement]:
        return self._hypothetical_statement_repository.find_by_agent_id(agent_id)