from datetime import datetime
from typing import Dict

from analogai.foundation.modules.direct_statement.direct_statement import DirectStatement
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.common.utils.modifier_utils import ModifierBuilder
from analogai.foundation.common.enums.deontic_modality import DeonticModality
from analogai.foundation.infrastructure.mappers.notion_storage_mapper import NotionStorageMapper
from analogai.foundation.infrastructure.mappers.time_storage_mapper import TimeStorageMapper


class StatementStorageMapper:
    @staticmethod
    def to_dict(statement: DirectStatement) -> Dict:
        result = {
            "id": statement.id,
            "user_id": statement.user_id,
            "agent_id": statement.agent_id,
            "created_at": statement.created_at.isoformat() if statement.created_at else None,
            "subject_notion": NotionStorageMapper.to_dict(statement.subject_notion),
            "relation": statement.relation.value,
            "complement_notion": NotionStorageMapper.to_dict(statement.complement_notion),
            "probability": statement.probability,
            "validity": statement.validity,
        }
        if statement.quantity is not None:
            result["quantity"] = statement.quantity
        if statement.modifier:
            modifier = statement.modifier
            if modifier.location:
                result["location"] = modifier.location
            if modifier.from_time:
                result.update(TimeStorageMapper.flatten_to_dict(modifier.from_time, "from_time"))
            if modifier.to_time:
                result.update(TimeStorageMapper.flatten_to_dict(modifier.to_time, "to_time"))
            if modifier.deontic_modality:
                result["deontic_modality"] = modifier.deontic_modality.value
            if modifier.attributes is not None:
                result["attributes"] = [
                    {"tag": attribute.tag, "value": attribute.value, "unit": attribute.unit}
                    for attribute in modifier.attributes
                ]
        return result

    @staticmethod
    def from_dict(data: Dict) -> DirectStatement:
        subject_notion = NotionStorageMapper.from_dict(data.get("subject_notion", {}))
        relation_str = data.get("relation") or data.get("relationship_type") or data.get("relationship")
        relation = Relation.from_string(relation_str)
        complement_notion = NotionStorageMapper.from_dict(data.get("complement_notion", {}))
        modifier = None
        from_time = TimeStorageMapper.unflatten_from_dict(data, "from_time") or (
            data.get("from_time") and TimeStorageMapper.from_dict(data["from_time"])
        )
        to_time = TimeStorageMapper.unflatten_from_dict(data, "to_time") or (
            data.get("to_time") and TimeStorageMapper.from_dict(data["to_time"])
        )
        location = data.get("location")
        deontic_modality = data.get("deontic_modality")
        if location or from_time or to_time or deontic_modality:
            builder = ModifierBuilder()
            if location:
                builder.with_location(location)
            if from_time:
                builder.with_from_time(
                    year=from_time.year,
                    month=from_time.month,
                    day=from_time.day,
                    hour=from_time.hour,
                    minute=from_time.minute,
                )
            if to_time:
                builder.with_to_time(
                    year=to_time.year,
                    month=to_time.month,
                    day=to_time.day,
                    hour=to_time.hour,
                    minute=to_time.minute,
                )
            if deontic_modality:
                builder.with_deontic_modality(DeonticModality(deontic_modality))
            modifier = builder.build()
        attributes_payload = data.get("attributes")
        if attributes_payload is None:
            attributes_payload = data.get("measures")
        if attributes_payload is not None:
            from analogai.foundation.core.value_objects.attribute import Attribute
            attributes = [
                Attribute(tag=m.get("tag") or m.get("kind"), value=m.get("value"), unit=m.get("unit"))
                for m in attributes_payload or []
            ]
            if modifier is None:
                modifier = ModifierBuilder().build()
            modifier.attributes = attributes
        if data.get("quantity") is not None:
            if modifier is None:
                modifier = ModifierBuilder().build()
            modifier.quantity = data.get("quantity")
        created_at = None
        if data.get("created_at"):
            raw = data["created_at"]
            try:
                created_at = datetime.fromisoformat(raw)
            except TypeError:
                created_at = raw
        return DirectStatement(
            id=data.get("id"),
            user_id=data["user_id"],
            agent_id=data["agent_id"],
            subject_notion=subject_notion,
            relation=relation,
            complement_notion=complement_notion,
            modifier=modifier,
            probability=data.get("probability", 1.0),
            validity=data.get("validity", 1.0),
            created_at=created_at,
        )