import unittest
from unittest.mock import Mock

from analogai.foundation.core.value_objects.cause import Cause
from analogai.foundation.common.enums.criterion import Criterion
from analogai.deepthink.application.usecases.learning.make_causal_statement.usecase import MakeCausalStatementUseCase
from analogai.deepthink.application.usecases.learning.make_causal_statement.models import (
    CauseCriteria,
    MakeCausalStatementRequest,
)
from analogai.deepthink.application.value_objects.user_agent import UserAgent


class TestMakeCausalStatementUseCase(unittest.TestCase):
    def setUp(self):
        self.domain_service_factory = Mock()
        self.causal_service = Mock()
        self.notion_service = Mock()
        self.statement_service = Mock()
        self.domain_service_factory.get_causal_service.return_value = self.causal_service
        self.domain_service_factory.get_notion_service.return_value = self.notion_service
        self.domain_service_factory.get_statement_service.return_value = self.statement_service
        self.output_port = Mock()
        self.usecase = MakeCausalStatementUseCase(
            domain_service_factory=self.domain_service_factory,
            output_port=self.output_port,
        )

    def test_execute_creates_causal_statement(self):
        self.causal_service.create.return_value = Mock()

        user_agent = UserAgent(user_id="u1", agent_id="a1", user_authority=1.0)
        cause = CauseCriteria(criteria={
            "subject_caption": "rain",
            "object_caption": "wet ground",
            "relation": "causes",
        })
        effect = CauseCriteria(criteria={
            "subject_caption": "rain",
            "object_caption": "wet ground",
            "relation": "causes",
        })
        request = MakeCausalStatementRequest(
            user_agent=user_agent,
            probability=0.9,
            causes=[cause],
            effect=effect,
        )

        self.usecase.execute(request)
        
        self.causal_service.create.assert_called_once()
        call_kwargs = self.causal_service.create.call_args[1]
        self.assertEqual(call_kwargs["user_id"], "u1")
        self.assertEqual(call_kwargs["agent_id"], "a1")
        self.assertEqual(call_kwargs["probability"], 0.9)
        self.assertEqual(len(call_kwargs["causes"]), 1)
        self.assertIsInstance(call_kwargs["causes"][0], Cause)
        cause_criteria = call_kwargs["causes"][0].criteria
        self.assertEqual(cause_criteria[Criterion.SubjectCaption], "rain")
        self.assertEqual(cause_criteria[Criterion.Relation], "causes")
        self.assertEqual(cause_criteria[Criterion.ComplementCaption], "wet ground")
        effect_obj = call_kwargs["effect"]
        self.assertIsInstance(effect_obj, Cause)
        effect_criteria = effect_obj.criteria
        self.assertEqual(effect_criteria[Criterion.SubjectCaption], "rain")
        self.assertEqual(effect_criteria[Criterion.Relation], "causes")
        self.assertEqual(effect_criteria[Criterion.ComplementCaption], "wet ground")
