"""
SVG document element tree.

Represents the parsed SVG document structure with elements, groups, and shapes.
"""

import logging
from abc import ABC
from dataclasses import dataclass, field
from typing import Any, Optional

from .shapes import Shape
from .styles import Style
from .transforms import Transform

logger = logging.getLogger(__name__)


@dataclass
class SVGElement(ABC):
    """
    Base class for all SVG elements.

    Represents any element in the SVG document tree (shapes, groups, etc.).

    Attributes:
        element_type: Element tag name (rect, circle, g, path, etc.).
        id: Element ID attribute for reference.
        classes: CSS class names.
        transform: Cumulative transformation matrix (includes parent transforms).
        style: Visual styling attributes.
        children: Child elements.
        attributes: Raw XML attributes for extensibility.
    """

    element_type: str
    id: str | None = None
    classes: list[str] = field(default_factory=list)
    transform: Transform = field(default_factory=Transform.identity)
    style: Style = field(default_factory=Style)
    children: list["SVGElement"] = field(default_factory=list)
    attributes: dict[str, str] = field(default_factory=dict)

    def find_element_by_id(self, element_id: str) -> Optional["SVGElement"]:
        """
        Find element by ID in this element's subtree.

        Args:
            element_id: The id value to search for.

        Returns:
            SVGElement with matching id, or None if not found.
        """
        if self.id == element_id:
            return self

        for child in self.children:
            result = child.find_element_by_id(element_id)
            if result:
                return result

        return None

    def get_all_shapes(self) -> list["ShapeElement"]:
        """
        Collect all ShapeElement instances from this element's subtree.

        Returns:
            List of ShapeElement objects.
        """
        shapes = []

        if isinstance(self, ShapeElement):
            shapes.append(self)

        for child in self.children:
            shapes.extend(child.get_all_shapes())

        return shapes


@dataclass
class GroupElement(SVGElement):
    """
    Group element (<g>).

    Groups have no visual representation but apply transforms and styles to children.
    """

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(element_type="g", **kwargs)


@dataclass
class ShapeElement(SVGElement):
    """
    Shape element wrapping a Shape geometry object.

    Attributes:
        shape: The geometric shape (Rectangle, Circle, Path, etc.).
    """

    shape: Shape | None = None

    def __init__(
        self, shape: Shape | None = None, element_type: str = "shape", **kwargs: Any
    ) -> None:
        super().__init__(element_type=element_type, **kwargs)
        self.shape = shape
