"""
Kabbalistic attributes and data structures.

This module defines attributes specific to the Kabbalah module,
including Sephira, Paths, and Tree of Life structures.
"""

from dataclasses import dataclass, field
from typing import Dict, List, Optional, Tuple

from utils.attributes import (
    Color,
    Colorscale,
    ElementType,
    God,
    Perfume,
    Planet,
)


@dataclass
class Sephera:
    """Represents a Sephira on the Tree of Life."""

    number: int
    name: str
    hebrew_name: str
    meaning: str
    archangel: str
    order_of_angels: str
    mundane_chakra: str
    element: Optional["ElementType"] = None
    planetary_ruler: Optional[str] = None
    tarot_trump: Optional[str] = None
    colorscale: Optional["Colorscale"] = None


@dataclass
class PeriodicTable:
    """Represents a Sephirothic position in Kabbalah with cross-correspondences."""

    number: int
    name: str
    sephera: Optional[Sephera]
    element: Optional["ElementType"] = None
    planet: Optional["Planet"] = None
    color: Optional["Color"] = None
    tarot_trump: Optional[str] = None
    hebrew_letter: Optional[str] = None
    divine_name: Optional[str] = None
    archangel: Optional[str] = None
    order_of_angels: Optional[str] = None
    keywords: List[str] = field(default_factory=list)


@dataclass
class TreeOfLife:
    """Represents the Tree of Life structure."""

    sephiroth: Dict[int, str]
    paths: Dict[Tuple[int, int], str]


@dataclass
class Correspondences:
    """Represents Kabbalistic correspondences."""

    number: int
    sephira: str
    element: Optional[str]
    planet: Optional[str]
    zodiac: Optional[str]
    tarot_trump: Optional[str]
    archangel: Optional[str]
    order_of_angels: Optional[str]
    divine_name: Optional[str]


@dataclass
class Path:
    """Represents one of the 22 Paths on the Tree of Life with full correspondences."""

    number: int  # 11-32
    hebrew_letter: str  # Hebrew letter name (Aleph through Tau)
    transliteration: str  # English transliteration
    tarot_trump: str  # Major Arcana card (0-XXI)
    sephera_from: Optional["Sephera"] = None  # Lower Sephira
    sephera_to: Optional["Sephera"] = None  # Upper Sephira
    element: Optional["ElementType"] = None  # Element (Air, Fire, Water, Earth)
    planet: Optional["Planet"] = None  # Planetary ruler
    zodiac_sign: Optional[str] = None  # Zodiac sign (12 paths only)
    colorscale: Optional["Colorscale"] = None  # Golden Dawn color scales
    perfumes: List["Perfume"] = field(default_factory=list)
    gods: Dict[str, List["God"]] = field(default_factory=dict)
    keywords: List[str] = field(default_factory=list)
    description: str = ""

    def __post_init__(self) -> None:
        if not 11 <= self.number <= 32:
            raise ValueError(f"Path number must be between 11 and 32, got {self.number}")

    def is_elemental_path(self) -> bool:
        """Check if this is one of the 4 elemental paths."""
        elemental_numbers = {11, 23, 31, 32}  # Aleph, Mem, Shin, 32-bis
        return self.number in elemental_numbers

    def is_planetary_path(self) -> bool:
        """Check if this path has planetary correspondence."""
        return self.planet is not None

    def is_zodiacal_path(self) -> bool:
        """Check if this path has zodiac correspondence."""
        return self.zodiac_sign is not None

    def add_god(self, god: "God") -> None:
        """Attach a god to this path grouped by culture."""
        culture_key = god.culture_key()
        culture_bucket = self.gods.setdefault(culture_key, [])
        if god not in culture_bucket:
            culture_bucket.append(god)

    def add_perfume(self, perfume: "Perfume") -> None:
        """Attach a perfume correspondence if it is not already present."""
        if perfume not in self.perfumes:
            self.perfumes.append(perfume)

    def get_gods(self, culture: Optional[str] = None) -> List["God"]:
        """Return all gods for this path, optionally filtered by culture."""
        if culture:
            return list(self.gods.get(culture.lower(), []))
        merged: List["God"] = []
        for values in self.gods.values():
            merged.extend(values)
        return merged

    def __str__(self) -> str:
        """Return nicely formatted string representation of the Path."""
        lines = []

        # Header with path number and letter
        lines.append(f"--- Path {self.number}: {self.hebrew_letter} ({self.transliteration}) ---")
        lines.append("")

        # Basic correspondences
        lines.append(f"tarot_trump: {self.tarot_trump}")

        # Connections
        if self.sephera_from or self.sephera_to:
            seph_from = self.sephera_from.name if self.sephera_from else "Unknown"
            seph_to = self.sephera_to.name if self.sephera_to else "Unknown"
            lines.append(f"connects: {seph_from} ↔ {seph_to}")

        # Element
        if self.element:
            element_name = self.element.name if hasattr(self.element, "name") else str(self.element)
            lines.append(f"element: {element_name}")

        # Planet
        if self.planet:
            lines.append("")
            lines.append("--- Planet ---")
            for line in str(self.planet).split("\n"):
                lines.append(f"  {line}")

        # Zodiac
        if self.zodiac_sign:
            lines.append(f"zodiac_sign: {self.zodiac_sign}")

        # Colorscale
        if self.colorscale:
            lines.append("")
            lines.append("--- Colorscale ---")
            lines.append(f"  name: {self.colorscale.name}")
            lines.append(f"  king_scale: {self.colorscale.king_scale}")
            lines.append(f"  queen_scale: {self.colorscale.queen_scale}")
            lines.append(f"  emperor_scale: {self.colorscale.emperor_scale}")
            lines.append(f"  empress_scale: {self.colorscale.empress_scale}")
            if self.colorscale.sephirotic_color:
                lines.append(f"  sephirotic_color: {self.colorscale.sephirotic_color}")
            lines.append(f"  type: {self.colorscale.type}")
            if self.colorscale.keywords:
                lines.append(f"  keywords: {', '.join(self.colorscale.keywords)}")
            if self.colorscale.description:
                lines.append(f"  description: {self.colorscale.description}")

        # Perfumes
        if self.perfumes:
            lines.append("")
            lines.append("--- Perfumes ---")
            for perfume in self.perfumes:
                for line in str(perfume).split("\n"):
                    lines.append(f"  {line}")
                lines.append("")

        # Gods
        if self.gods:
            lines.append("")
            lines.append("--- Gods ---")
            for culture, god_list in self.gods.items():
                lines.append(f"  {culture}:")
                for god in god_list:
                    for line in str(god).split("\n"):
                        lines.append(f"    {line}")
                    lines.append("")

        # Keywords
        if self.keywords:
            lines.append("")
            lines.append("--- Keywords ---")
            lines.append(f"  {', '.join(self.keywords)}")

        # Description
        if self.description:
            lines.append("")
            lines.append("--- Description ---")
            lines.append(f"  {self.description}")

        lines.append("")
        return "\n".join(lines)
