from types import SimpleNamespace
from typing import List, Set
from analogai.foundation.common.enums import RelationshipType
from analogai.foundation.core.value_objects.relation import Relation
from analogai.deepthink.application.usecases.chat.shared.relationship_category import RelationshipCategory


def _phrases(types) -> List[str]:
    return [rt.value for rt in types]


def _to_relations(types: Set[RelationshipType]) -> List[Relation]:
    return [Relation.from_type(rt) for rt in types]


def _normalize_for_comparison(value: str) -> str:
    if value is None:
        return ""
    return str(value).strip().lower()


class RelationshipCategorizer:
    @staticmethod
    def get_what_relationships() -> List[Relation]:
        return _to_relations({
            RelationshipType.IS_A,
            RelationshipType.FORM_OF,
            RelationshipType.DEFINED_AS,
            RelationshipType.SYNONYM,
            RelationshipType.ANTONYM,
            RelationshipType.DISTINCT_FROM,
            RelationshipType.SIMILAR_TO,
            RelationshipType.MADE_OF,
            RelationshipType.HAS_CONTEXT,
            RelationshipType.SYMBOL_OF,
            RelationshipType.USED_FOR,
            RelationshipType.RELATED_TO,
            RelationshipType.HAS_A,
            RelationshipType.CAUSES
        })

    @staticmethod
    def get_where_relationships() -> List[Relation]:
        return _to_relations({
            RelationshipType.LOCATED_NEAR,
            RelationshipType.PART_OF,
        })

    @staticmethod
    def get_how_relationships() -> List[Relation]:
        return _to_relations({
            RelationshipType.MANNER_OF,
            RelationshipType.HAS_PREREQUISITE,
            RelationshipType.RECEIVES_ACTION,
            RelationshipType.HAS_SUBEVENT,
            RelationshipType.HAS_FIRST_SUBEVENT,
            RelationshipType.HAS_LAST_SUBEVENT,
            RelationshipType.CAUSES,
        })

    @staticmethod
    def get_why_relationships() -> List[Relation]:
        return _to_relations({
            RelationshipType.CAUSES,
            RelationshipType.MOTIVATED_BY_GOAL,
            RelationshipType.DESIRES,
            RelationshipType.CAUSES_DESIRE,
            RelationshipType.OBSTRUCTED_BY,
            RelationshipType.HAS_PREREQUISITE,
        })

    @staticmethod
    def get_who_relationships() -> List[Relation]:
        return _to_relations({
            RelationshipType.CREATED_BY,
            RelationshipType.IS_A,
            RelationshipType.DO,
            RelationshipType.CAPABLE_OF,
            RelationshipType.LOCATED_NEAR,
            RelationshipType.HAS_A,
            RelationshipType.RELATED_TO,
        })

    @staticmethod
    def get_origin_relationships() -> List[Relation]:
        return _to_relations({
            RelationshipType.DERIVED_FROM,
            RelationshipType.ETYMOLOGICALLY_RELATED_TO,
            RelationshipType.ETYMOLOGICALLY_DERIVED_FROM,
        })

    @staticmethod
    def get_what_relationship_phrases() -> List[str]:
        return _phrases({
            RelationshipType.IS_A,
            RelationshipType.FORM_OF,
            RelationshipType.DEFINED_AS,
            RelationshipType.SYNONYM,
            RelationshipType.ANTONYM,
            RelationshipType.DISTINCT_FROM,
            RelationshipType.SIMILAR_TO,
            RelationshipType.MADE_OF,
            RelationshipType.HAS_CONTEXT,
            RelationshipType.SYMBOL_OF,
            RelationshipType.USED_FOR,
            RelationshipType.RELATED_TO,
            RelationshipType.HAS_A,
        })

    @staticmethod
    def get_where_relationship_phrases() -> List[str]:
        return _phrases({
            RelationshipType.LOCATED_NEAR,
            RelationshipType.PART_OF,
        })

    @staticmethod
    def get_how_relationship_phrases() -> List[str]:
        return _phrases({
            RelationshipType.MANNER_OF,
            RelationshipType.HAS_PREREQUISITE,
            RelationshipType.RECEIVES_ACTION,
            RelationshipType.HAS_SUBEVENT,
            RelationshipType.HAS_FIRST_SUBEVENT,
            RelationshipType.HAS_LAST_SUBEVENT,
            RelationshipType.CAUSES,
        })

    @staticmethod
    def get_why_relationship_phrases() -> List[str]:
        return _phrases({
            RelationshipType.CAUSES,
            RelationshipType.MOTIVATED_BY_GOAL,
            RelationshipType.DESIRES,
            RelationshipType.CAUSES_DESIRE,
            RelationshipType.OBSTRUCTED_BY,
            RelationshipType.HAS_PREREQUISITE,
        })

    @staticmethod
    def get_who_relationship_phrases() -> List[str]:
        return _phrases({
            RelationshipType.CREATED_BY,
            RelationshipType.IS_A,
            RelationshipType.DO,
            RelationshipType.CAPABLE_OF,
            RelationshipType.LOCATED_NEAR,
            RelationshipType.AT_LOCATION,
            RelationshipType.HAS_A,
            RelationshipType.RELATED_TO,
        })

    @staticmethod
    def get_origin_relationship_phrases() -> List[str]:
        return _phrases({
            RelationshipType.DERIVED_FROM,
            RelationshipType.ETYMOLOGICALLY_RELATED_TO,
            RelationshipType.ETYMOLOGICALLY_DERIVED_FROM,
        })

    @staticmethod
    def get_deduction_relationships() -> List[Relation]:
        return _to_relations({
            RelationshipType.IS_A,
            RelationshipType.DO,
            RelationshipType.SYNONYM,
            RelationshipType.RELATED_TO,
            RelationshipType.FORM_OF,
            RelationshipType.HAS_SUBEVENT,
            RelationshipType.HAS_FIRST_SUBEVENT,
            RelationshipType.HAS_LAST_SUBEVENT,
            RelationshipType.HAS_PREREQUISITE,
            RelationshipType.SYMBOL_OF,
            RelationshipType.LOCATED_NEAR,
            RelationshipType.SIMILAR_TO,
            RelationshipType.CAUSES_DESIRE,
            RelationshipType.MADE_OF,
        })

    @staticmethod
    def get_custom_deduction_relations() -> List[str]:
        return ["fly", "need", "orbit", "causes"]

    @staticmethod
    def get_category_for_relationship(relationship_phrase: str) -> RelationshipCategory:
        phrase_norm = _normalize_for_comparison(relationship_phrase or "")
        all_categories = {
            RelationshipCategory.WHAT: RelationshipCategorizer.get_what_relationship_phrases(),
            RelationshipCategory.WHERE: RelationshipCategorizer.get_where_relationship_phrases(),
            RelationshipCategory.HOW: RelationshipCategorizer.get_how_relationship_phrases(),
            RelationshipCategory.WHY: RelationshipCategorizer.get_why_relationship_phrases(),
            RelationshipCategory.WHO: RelationshipCategorizer.get_who_relationship_phrases(),
            RelationshipCategory.ORIGIN: RelationshipCategorizer.get_origin_relationship_phrases(),
        }

        for category, phrases in all_categories.items():
            if phrase_norm in [_normalize_for_comparison(p) for p in phrases]:
                return category

        return RelationshipCategory.UNCATEGORIZED



