from typing import Optional, Union, List

from analogai.foundation.core.value_objects.modifier import Modifier
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.core.value_objects.attribute import Attribute
from analogai.foundation.common.enums.relationship_type import RelationshipType
from analogai.foundation.common.utils.statement_serializers.helpers.verbalization import Verbalization
from analogai.foundation.common.utils.statement_serializers.helpers.verb_selector import (
    VerbSelector,
    DefaultVerbSelectionStrategy,
)
from analogai.foundation.common.utils.statement_serializers.helpers.sentence_builder import NaturalSentenceBuilder
from analogai.foundation.common.utils.statement_serializers.helpers.modifier_handler import ModifierHandler
from analogai.foundation.common.utils.statement_serializers.helpers import (
    normalize_timezone,
    is_plural_subject,
)


class StatementSerializer:
    def __init__(self, verb_selector: Optional[VerbSelector] = None):
        if verb_selector is None:
            verb_selector = VerbSelector(DefaultVerbSelectionStrategy(Verbalization))
        self.verb_selector = verb_selector

    def serialize(
        self,
        subject_notion_caption: str,
        relation: str,
        complement_notion_caption: str,
        probability: float = 1.0,
        modifier: Optional[Modifier] = None,
        timezone: Optional[str] = None,
        subject_attributes: Optional[List[Attribute]] = None,
        complement_attributes: Optional[List[Attribute]] = None,
    ) -> str:
        timezone = normalize_timezone(timezone)
        subject_notion_caption = subject_notion_caption.strip()
        is_plural = is_plural_subject(subject_notion_caption)
        verb = self.verb_selector.select(relation, probability, is_plural)

        quantity = modifier.quantity if modifier is not None else None

        subject_caption = self._append_attributes(
            subject_notion_caption,
            subject_attributes,
        )
        complement_caption = self._append_attributes(
            complement_notion_caption,
            complement_attributes,
        )

        builder = NaturalSentenceBuilder(timezone=timezone)
        builder.with_base_statement(
            subject_caption,
            verb,
            complement_caption,
            is_plural,
            quantity,
        )

        ModifierHandler.apply_to_builder(builder, modifier)

        result = builder.build()
        return result.capitalize() if result else ""

    @staticmethod
    def _append_attributes(caption: str, attributes: Optional[List[Attribute]]) -> str:
        if not attributes:
            return caption
        caption_lower = caption.lower()
        parts = []
        year_parts = []

        def _format_value(raw) -> str:
            if isinstance(raw, float) and raw.is_integer():
                return str(int(raw))
            return str(raw)

        for attr in attributes:
            tag = str(attr.tag)
            tag_lower = tag.lower()
            value = attr.value
            unit = attr.unit

            if tag_lower in caption_lower:
                continue

            if "year" in tag_lower:
                if value is not None:
                    year_parts.append(f"({_format_value(value)})")
                continue

            if unit:
                parts.append(f"with {tag} {_format_value(value)} {unit}")
            else:
                parts.append(f"with {tag} {_format_value(value)}")
        suffix = " and ".join(parts)
        year_suffix = " ".join(year_parts)
        if suffix and year_suffix:
            return f"{caption} {year_suffix} {suffix}"
        if year_suffix:
            return f"{caption} {year_suffix}"
        if suffix:
            return f"{caption} {suffix}"
        return caption

    @staticmethod
    def create_default() -> "StatementSerializer":
        return StatementSerializer()


def serialize_statement(
    subject_notion_caption: str,
    complement_notion_caption: str,
    relation: Union[Relation, RelationshipType, str],
    probability: float = 1.0,
    modifier: Optional[Modifier] = None,
    timezone: Optional[str] = None,
    subject_attributes: Optional[List[Attribute]] = None,
    complement_attributes: Optional[List[Attribute]] = None,
) -> str:
    serializer = StatementSerializer.create_default()
    if relation is None:
        relation_str = "unknown"
    elif isinstance(relation, Relation):
        relation_str = relation.value
    elif isinstance(relation, RelationshipType):
        relation_str = relation.value
    elif isinstance(relation, str):
        relation_str = relation
    else:
        raise TypeError("relation must be a Relation or RelationshipType")
    return serializer.serialize(
        subject_notion_caption,
        relation_str,
        complement_notion_caption,
        probability,
        modifier,
        timezone,
        subject_attributes,
        complement_attributes,
    )




if __name__ == "__main__":
    # Example usage
    from analogai.foundation.core.value_objects.modifier import Modifier
    from analogai.foundation.core.value_objects.relation import Relation
    from analogai.foundation.core.value_objects.time import Time

    modifier = Modifier(from_time=Time(year=1990))
    relation = Relation.from_string("is")
    sentence = serialize_statement(
        subject_notion_caption="socrates",
        relation=relation,
        complement_notion_caption="mortal",
        probability=0.9,
        modifier=modifier,
        timezone="UTC",
    )
    print(sentence)  # Output: "The cat has 5 whiskers."


    modifier = Modifier(from_time=Time(year=1990), to_time=Time(year=1990))
    relation = Relation.from_string("is")
    sentence = serialize_statement(
        subject_notion_caption="socrates",
        relation=relation,
        complement_notion_caption="mortal",
        probability=0.9,
        modifier=modifier,
        timezone="UTC",
    )
    print(sentence)  # Output: "The cat has 5 whiskers."    