"""
Cube of Space attributes and data structures.

Defines the CubeOfSpace, Wall, and WallDirection classes for the Cube of Space
Kabbalistic model with hierarchical wall and direction structure.
"""

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


@dataclass(frozen=True, repr=False)
class WallDirection:
    """
    Represents a single direction within a Wall of the Cube of Space.

    Each wall has 5 directions: North, South, East, West, Center.
    Each direction has a Hebrew letter and zodiac correspondence.
    """

    name: str  # "North", "South", "East", "West", "Center"
    letter: str  # Hebrew letter (e.g., "Aleph", "Bet", etc.)
    zodiac: Optional[str] = None  # Zodiac sign if applicable
    element: Optional[str] = None  # Associated element if any
    planet: Optional[str] = None  # Associated planet if any
    keywords: List[str] = field(default_factory=list)
    description: str = ""

    VALID_DIRECTION_NAMES = {"North", "South", "East", "West", "Center"}

    def __post_init__(self) -> None:
        if self.name not in self.VALID_DIRECTION_NAMES:
            raise ValueError(
                f"Invalid direction name '{self.name}'. "
                f"Valid names: {', '.join(sorted(self.VALID_DIRECTION_NAMES))}"
            )
        if not self.letter or not isinstance(self.letter, str):
            raise ValueError(f"Direction must have a letter, got {self.letter}")

    def __repr__(self) -> str:
        """Custom repr showing key attributes."""
        return f"WallDirection({self.name}, {self.letter})"


@dataclass(frozen=True, repr=False)
class Wall:
    """
    Represents one of the 6 walls of the Cube of Space.

    Each wall has 5 directions: North, South, East, West, Center.
    The 6 walls are: North, South, East, West, Above, Below.
    Opposite walls: North↔South, East↔West, Above↔Below.
    Each direction has a Hebrew letter and zodiac correspondence.
    """

    name: str  # "North", "South", "East", "West", "Above", "Below"
    side: str  # Alias for name, used for filtering (e.g., "north", "south")
    opposite: str  # Opposite wall name (e.g., "South" for North wall)
    element: Optional[str] = None  # Associated element
    planet: Optional[str] = None  # Associated planet
    archangel: Optional[str] = None  # Associated archangel
    keywords: List[str] = field(default_factory=list)
    description: str = ""
    directions: Dict[str, "WallDirection"] = field(default_factory=dict)

    VALID_WALL_NAMES = {"North", "South", "East", "West", "Above", "Below"}

    # Opposite wall mappings
    OPPOSITE_WALLS = {
        "North": "South",
        "South": "North",
        "East": "West",
        "West": "East",
        "Above": "Below",
        "Below": "Above",
    }

    def __post_init__(self) -> None:
        if self.name not in self.VALID_WALL_NAMES:
            raise ValueError(
                f"Invalid wall name '{self.name}'. "
                f"Valid walls: {', '.join(sorted(self.VALID_WALL_NAMES))}"
            )

        # Validate side matches name (case-insensitive)
        if self.side.capitalize() != self.name:
            raise ValueError(f"Wall side '{self.side}' must match name '{self.name}'")

        # Validate opposite wall
        expected_opposite = self.OPPOSITE_WALLS.get(self.name)
        if self.opposite != expected_opposite:
            raise ValueError(
                f"Wall '{self.name}' must have opposite '{expected_opposite}', got '{self.opposite}'"
            )

        # Ensure all 5 directions exist
        if len(self.directions) != 5:
            raise ValueError(
                f"Wall '{self.name}' must have exactly 5 directions (North, South, East, West, Center), "
                f"got {len(self.directions)}"
            )

        required_directions = {"North", "South", "East", "West", "Center"}
        if set(self.directions.keys()) != required_directions:
            raise ValueError(
                f"Wall '{self.name}' must have directions: {required_directions}, "
                f"got {set(self.directions.keys())}"
            )

    def __repr__(self) -> str:
        """Custom repr showing wall name and element."""
        return f"Wall({self.name}, {self.element})"

    def __str__(self) -> str:
        """Custom string representation for printing wall details with recursive direction details."""
        keywords_str = ", ".join(self.keywords) if self.keywords else "None"
        lines = [
            f"Wall: {self.name}",
            f"  Side: {self.side}",
            f"  Opposite: {self.opposite}",
            f"  Element: {self.element}",
            f"  Planet: {self.planet}",
            f"  Archangel: {self.archangel}",
            f"  Keywords: {keywords_str}",
        ]

        # Add directions with their details recursively
        if self.directions:
            lines.append("  Directions:")
            # Order: Center, North, South, East, West
            direction_order = ["Center", "North", "South", "East", "West"]
            for dir_name in direction_order:
                if dir_name in self.directions:
                    direction = self.directions[dir_name]
                    lines.append(f"    --- {direction.name} ---")
                    lines.append(f"      Letter: {direction.letter}")
                    if direction.zodiac:
                        lines.append(f"      Zodiac: {direction.zodiac}")
                    if direction.element:
                        lines.append(f"      Element: {direction.element}")
                    if direction.planet:
                        lines.append(f"      Planet: {direction.planet}")
                    if direction.keywords:
                        keywords = ", ".join(direction.keywords)
                        lines.append(f"      Keywords: {keywords}")
                    if direction.description:
                        lines.append(f"      Description: {direction.description}")

        return "\n".join(lines)

    def direction(self, direction_name: str) -> Optional["WallDirection"]:
        """Get a specific direction by name. Usage: wall.direction("North")"""
        return self.directions.get(direction_name.capitalize())

    def all_directions(self) -> list:
        """Return all 5 directions as a list."""
        return list(self.directions.values())

    # Aliases for backward compatibility
    def get_direction(self, direction_name: str) -> Optional["WallDirection"]:
        """Deprecated: use direction() instead."""
        return self.direction(direction_name)

    def get_opposite_wall_name(self) -> str:
        """Deprecated: use the opposite property instead."""
        return self.opposite


@dataclass
class CubeOfSpace:
    """
    Represents the Cube of Space with 6 walls.

    The Cube of Space is a 3D sacred geometry model consisting of:
    - 6 walls (North, South, East, West, Above, Below)
    - Each wall contains 5 areas (center, above, below, east, west)
    - Opposite walls: North↔South, East↔West, Above↔Below
    - Total: 30 positions plus central core
    """

    walls: Dict[str, Wall] = field(default_factory=dict)
    center: Optional[WallDirection] = None  # Central core position

    # Built-in wall definitions with all correspondences
    _WALL_DEFINITIONS = {
        "North": {
            "element": "Air",
            "planet": "Mercury",
            "archangel": "Raphael",
            "keywords": ["Thought", "Communication", "Intellect"],
            "description": "Northern Wall - Air element, Mercury correspondence",
            "areas": {
                "center": {
                    "element": "Spirit",
                    "keywords": ["Integration", "Balance", "Foundation"],
                    "description": "Center of North wall - synthesis of thought",
                },
                "above": {
                    "element": "Fire",
                    "keywords": ["Higher Mind", "Spiritual Thought", "Ascent"],
                    "description": "Above area - elevated intellectual consciousness",
                },
                "below": {
                    "element": "Earth",
                    "keywords": ["Practical Thought", "Grounded Mind", "Implementation"],
                    "description": "Below area - material manifestation of thought",
                },
                "east": {
                    "element": "Air",
                    "keywords": ["Clarity", "Awakening", "Dawn Thought"],
                    "description": "East area - morning mind, new perspectives",
                },
                "west": {
                    "element": "Water",
                    "keywords": ["Emotional Thought", "Reflection", "Dreams"],
                    "description": "West area - intuitive mind, introspection",
                },
            },
        },
        "South": {
            "element": "Fire",
            "planet": "Mars",
            "archangel": "Samael",
            "keywords": ["Will", "Action", "Passion"],
            "description": "Southern Wall - Fire element, Mars correspondence",
            "areas": {
                "center": {
                    "element": "Spirit",
                    "keywords": ["Pure Will", "Center of Power", "Drive"],
                    "description": "Center of South wall - focal point of action",
                },
                "above": {
                    "element": "Fire",
                    "keywords": ["Divine Will", "Higher Purpose", "Spiritual Force"],
                    "description": "Above area - transcendent power and courage",
                },
                "below": {
                    "element": "Earth",
                    "keywords": ["Physical Action", "Embodied Will", "Manifestation"],
                    "description": "Below area - action in material world",
                },
                "east": {
                    "element": "Air",
                    "keywords": ["Active Mind", "Strategic Will", "Beginning Action"],
                    "description": "East area - dawn of new endeavors",
                },
                "west": {
                    "element": "Water",
                    "keywords": ["Passionate Emotion", "Emotional Drive", "Desire"],
                    "description": "West area - feeling-guided action",
                },
            },
        },
        "East": {
            "element": "Air",
            "planet": "Venus",
            "archangel": "Haniel",
            "keywords": ["Dawn", "Beginning", "Ascent"],
            "description": "Eastern Wall - Air element, new beginnings",
            "areas": {
                "center": {
                    "element": "Spirit",
                    "keywords": ["New Potential", "Morning Star", "Awakening"],
                    "description": "Center of East wall - point of emergence",
                },
                "above": {
                    "element": "Fire",
                    "keywords": ["Spiritual Dawn", "Divine Light", "Inspiration"],
                    "description": "Above area - celestial promise",
                },
                "below": {
                    "element": "Earth",
                    "keywords": ["Material Growth", "Physical Sunrise", "Earthly Beginning"],
                    "description": "Below area - manifestation of new potential",
                },
                "east": {
                    "element": "Air",
                    "keywords": ["Pure Beginning", "First Breath", "Clarity"],
                    "description": "East area - absolute dawn principle",
                },
                "west": {
                    "element": "Water",
                    "keywords": ["Emotional Renewal", "Feelings Awakening", "Hope"],
                    "description": "West area - emotional opening toward new day",
                },
            },
        },
        "West": {
            "element": "Water",
            "planet": "Venus",
            "archangel": "Uriel",
            "keywords": ["Emotion", "Decline", "Closure"],
            "description": "Western Wall - Water element, endings and emotions",
            "areas": {
                "center": {
                    "element": "Spirit",
                    "keywords": ["Emotional Core", "Sunset Synthesis", "Integration"],
                    "description": "Center of West wall - emotional balance point",
                },
                "above": {
                    "element": "Fire",
                    "keywords": ["Spiritual Emotion", "Divine Love", "Transcendence"],
                    "description": "Above area - love beyond form",
                },
                "below": {
                    "element": "Earth",
                    "keywords": ["Physical Emotion", "Embodied Feeling", "Sensuality"],
                    "description": "Below area - emotion in material form",
                },
                "east": {
                    "element": "Air",
                    "keywords": ["Mental Emotion", "Thoughts Felt", "Understanding Feeling"],
                    "description": "East area - intellectual understanding of emotion",
                },
                "west": {
                    "element": "Water",
                    "keywords": ["Pure Emotion", "Deep Feeling", "Subconscious"],
                    "description": "West area - pure emotional depths",
                },
            },
        },
        "Above": {
            "element": "Fire",
            "planet": "Sun",
            "archangel": "Michael",
            "keywords": ["Heaven", "Spirit", "Light"],
            "description": "Upper Wall - Fire element, divine consciousness",
            "areas": {
                "center": {
                    "element": "Spirit",
                    "keywords": ["Divine Center", "Oneness", "Source"],
                    "description": "Center of Above wall - point of divine unity",
                },
                "above": {
                    "element": "Fire",
                    "keywords": ["Pure Spirit", "Infinite Light", "Transcendence"],
                    "description": "Above area - highest divine realm",
                },
                "below": {
                    "element": "Earth",
                    "keywords": ["Spirit in Matter", "Divine Manifestation", "Incarnation"],
                    "description": "Below area - spirit descending to form",
                },
                "east": {
                    "element": "Air",
                    "keywords": ["Divine Thought", "Holy Wisdom", "Inspiration"],
                    "description": "East area - divine intellect and inspiration",
                },
                "west": {
                    "element": "Water",
                    "keywords": ["Divine Love", "Compassion", "Mercy"],
                    "description": "West area - divine love and compassion",
                },
            },
        },
        "Below": {
            "element": "Earth",
            "planet": "Saturn",
            "archangel": "Cassiel",
            "keywords": ["Matter", "Foundation", "Manifestation"],
            "description": "Lower Wall - Earth element, material foundation",
            "areas": {
                "center": {
                    "element": "Spirit",
                    "keywords": ["Material Foundation", "Grounding", "Embodiment"],
                    "description": "Center of Below wall - anchor point of manifestation",
                },
                "above": {
                    "element": "Fire",
                    "keywords": ["Active Force", "Will to Build", "Transformation"],
                    "description": "Above area - active principle in matter",
                },
                "below": {
                    "element": "Earth",
                    "keywords": ["Pure Earth", "Deep Matter", "Grounding Root"],
                    "description": "Below area - deepest material foundation",
                },
                "east": {
                    "element": "Air",
                    "keywords": ["Material Structure", "Physical Form", "Manifestation"],
                    "description": "East area - form emerging into manifestation",
                },
                "west": {
                    "element": "Water",
                    "keywords": ["Nurturing Matter", "Fertile Ground", "Sustenance"],
                    "description": "West area - material nourishment and growth",
                },
            },
        },
    }

    def __post_init__(self) -> None:
        """Validate that all 6 walls are present."""
        required_walls = {"North", "South", "East", "West", "Above", "Below"}
        if set(self.walls.keys()) != required_walls:
            raise ValueError(f"CubeOfSpace must have all 6 walls, got: {set(self.walls.keys())}")

    @classmethod
    def create_default(cls) -> "CubeOfSpace":
        """
        Create a CubeOfSpace with all 6 walls fully populated with built-in definitions.

        Each wall has 5 directions (North, South, East, West, Center) positioned on that wall.
        Each direction has a Hebrew letter and optional zodiac correspondence.

        Returns:
            CubeOfSpace: Fully initialized cube with all walls and directions
        """
        walls = {}

        # Direction name mapping - same 5 directions on every wall
        # Maps old area names to consistent direction names
        direction_map = {
            "center": {"name": "Center", "letter": "Aleph", "zodiac": None},
            "above": {"name": "North", "letter": "Bet", "zodiac": None},
            "below": {"name": "South", "letter": "Gimel", "zodiac": None},
            "east": {"name": "East", "letter": "Daleth", "zodiac": "Aries"},
            "west": {"name": "West", "letter": "He", "zodiac": "Pisces"},
        }

        for wall_name, wall_data in cls._WALL_DEFINITIONS.items():
            # Create directions for this wall
            # Each wall has the same 5 directions: North, South, East, West, Center
            directions = {}
            for old_name, direction_config in direction_map.items():
                if old_name in wall_data["areas"]:
                    direction_data = wall_data["areas"][old_name]
                    direction = WallDirection(
                        name=direction_config["name"],
                        letter=direction_config["letter"],
                        zodiac=direction_config.get("zodiac"),
                        element=direction_data.get("element"),
                        keywords=direction_data.get("keywords", []),
                        description=direction_data.get("description", ""),
                    )
                    # Use the direction name as key so every wall has North, South, East, West, Center
                    directions[direction_config["name"]] = direction

            # Create the wall
            wall = Wall(
                name=wall_name,
                side=wall_name.lower(),
                opposite=Wall.OPPOSITE_WALLS[wall_name],
                element=wall_data.get("element"),
                planet=wall_data.get("planet"),
                archangel=wall_data.get("archangel"),
                keywords=wall_data.get("keywords", []),
                description=wall_data.get("description", ""),
                directions=directions,
            )
            walls[wall_name] = wall

        # Create central core
        central_core = WallDirection(
            name="Center",
            letter="Aleph",
            element="Spirit",
            keywords=["Unity", "Source", "All"],
            description="Central core of the Cube of Space - synthesis of all forces",
        )

        return cls(walls=walls, center=central_core)

    def wall(self, wall_name: str) -> Optional[Wall]:
        """Get a wall by name. Usage: cube.wall("north")"""
        return self.walls.get(wall_name)

    def opposite(self, wall_name: str) -> Optional[Wall]:
        """Get the opposite wall. Usage: cube.opposite("north")"""
        opposite_name = Wall.OPPOSITE_WALLS.get(wall_name)
        if not opposite_name:
            return None
        return self.walls.get(opposite_name)

    def direction(self, wall_name: str, direction_name: str) -> Optional[WallDirection]:
        """Get a specific direction from a specific wall. Usage: cube.direction("north", "center")"""
        wall = self.wall(wall_name)
        if not wall:
            return None
        return wall.direction(direction_name)

    def walls_all(self) -> List[Wall]:
        """Return all 6 walls as a list."""
        return list(self.walls.values())

    def directions(self, wall_name: str) -> list:
        """Return all 5 directions for a specific wall. Usage: cube.directions("north")"""
        wall = self.wall(wall_name)
        if not wall:
            return []
        return wall.all_directions()

    # Aliases for backward compatibility
    def get_wall(self, wall_name: str) -> Optional[Wall]:
        """Deprecated: use wall() instead."""
        return self.wall(wall_name)

    def get_direction(self, wall_name: str, direction_name: str) -> Optional[WallDirection]:
        """Deprecated: use direction() instead."""
        return self.direction(wall_name, direction_name)

    def get_opposite_wall(self, wall_name: str) -> Optional[Wall]:
        """Deprecated: use opposite() instead."""
        return self.opposite(wall_name)

    def all_walls(self) -> List[Wall]:
        """Deprecated: use walls_all() instead."""
        return self.walls_all()

    def all_directions_for_wall(self, wall_name: str) -> list:
        """Deprecated: use directions() instead."""
        return self.directions(wall_name)
