from analogai.foundation.common.enums.criterion import Criterion
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.common.dtos.hypothetical_statement_expression import HypotheticalStatementExpression
from analogai.foundation.common.utils.expressions_serializer import (
    serialize_hypothetical_statement_expression,
)
from analogai.foundation.common.logging.app_logger import app_logger
from analogai.deepthink.application.usecases.learning.make_conditional_statement.models import (
    MakeConditionalStatementResponse,
    CriterionData,
)
from analogai.deepthink.application.usecases.learning.make_conditional_statement.ports import MakeConditionalStatementOutputPort
from analogai.deepthink.presentation.presenters.presenter_response import PresenterResponse

_CRITERION_BY_VALUE = {c.value: c for c in Criterion}


class MakeConditionalStatementPresenter(MakeConditionalStatementOutputPort):
    def output_create_statement_success(self, response: MakeConditionalStatementResponse):
        cause_dicts = [self._to_criterion_dict(cause.criteria) for cause in response.causes]
        effect_dict = self._to_criterion_dict(response.effect.criteria)
        hypothetical = HypotheticalStatementExpression(
            causes=cause_dicts,
            effect=effect_dict,
            probability=response.probability,
            validity=response.validity,
            effect_belief_id=response.effect_belief_id,
        )
        timezone = response.user_agent.timezone if response.user_agent else None
        message = serialize_hypothetical_statement_expression(hypothetical, timezone=timezone)
        return PresenterResponse(message=message)

    def _to_criterion_dict(self, criteria: CriterionData) -> dict:
        result = {}
        if criteria.complement_caption is not None:
            result[Criterion.ComplementCaption] = criteria.complement_caption
        if criteria.subject_caption is not None:
            result[Criterion.SubjectCaption] = criteria.subject_caption
        if criteria.relation is not None:
            relation_value = criteria.relation
            if isinstance(relation_value, str):
                relation_value = Relation.from_string(relation_value)
            result[Criterion.Relation] = relation_value
        if criteria.location is not None:
            result[Criterion.Location] = criteria.location
        if criteria.time is not None:
            result[Criterion.Time] = criteria.time
        if criteria.from_time is not None:
            result[Criterion.FromTime] = criteria.from_time
        if criteria.to_time is not None:
            result[Criterion.ToTime] = criteria.to_time
        if criteria.quantity is not None:
            result[Criterion.Quantity] = criteria.quantity
        if criteria.deontic_modality is not None:
            result[Criterion.DeonticModality] = criteria.deontic_modality
        if criteria.certainty is not None:
            result[Criterion.Certainty] = criteria.certainty.value
        if criteria.attribute_values:
            result[Criterion.AttributeValue] = [
                {
                    "tag": value.tag,
                    "value": value.value,
                    "unit": value.unit,
                    "min_value": value.min_value,
                    "max_value": value.max_value,
                }
                for value in criteria.attribute_values
            ]
        return result

    def output_forbidden(self, response: MakeConditionalStatementResponse):
        app_logger.info("Outputting forbidden conditional statement")
        return self.output_create_statement_success(response)
