"""µFrame Intermediate Representation — node types for the IR tree.

Every .uf source parses into a tree of IRNode subclasses. The layout
engine measures, positions, and paints these nodes into a CharGrid.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum, auto


# ---------------------------------------------------------------------------
# Enums
# ---------------------------------------------------------------------------

class BorderWeight(Enum):
    LIGHT = auto()
    HEAVY = auto()
    DOUBLE = auto()
    ROUNDED = auto()


class HeadingLevel(Enum):
    H1 = 1
    H2 = 2
    H3 = 3


class DividerStyle(Enum):
    LIGHT = auto()
    HEAVY = auto()
    DOUBLE = auto()
    DASH = auto()
    DOT = auto()


class ListStyle(Enum):
    BULLET = auto()
    DASH = auto()
    NUMBER = auto()
    ARROW = auto()


class Align(Enum):
    LEFT = auto()
    CENTER = auto()
    RIGHT = auto()


# ---------------------------------------------------------------------------
# Style
# ---------------------------------------------------------------------------

@dataclass
class Style:
    """Visual style attached to any node."""
    fg: str | None = None       # 3-digit hex
    bg: str | None = None       # 3-digit hex
    bold: bool = False
    italic: bool = False
    underline: bool = False
    align: Align = Align.LEFT


# ---------------------------------------------------------------------------
# Inline text spans (parsed from @modifier{} syntax in text content)
# ---------------------------------------------------------------------------

@dataclass
class TextSpan:
    """A run of text with optional inline styling."""
    text: str
    bold: bool = False
    italic: bool = False
    underline: bool = False
    fg: str | None = None
    bg: str | None = None


# ---------------------------------------------------------------------------
# Layout rect — assigned by the layout engine
# ---------------------------------------------------------------------------

@dataclass
class Rect:
    x: int = 0
    y: int = 0
    w: int = 0
    h: int = 0


# ---------------------------------------------------------------------------
# Base node
# ---------------------------------------------------------------------------

@dataclass
class IRNode:
    """Base class for all IR nodes."""
    children: list[IRNode] = field(default_factory=list)
    style: Style = field(default_factory=Style)
    rect: Rect = field(default_factory=Rect)
    source_line: int | None = None

    # Set by measure pass
    min_width: int = 0
    min_height: int = 0
    pref_width: int = 0
    pref_height: int = 0


# ---------------------------------------------------------------------------
# Layout nodes
# ---------------------------------------------------------------------------

@dataclass
class Page(IRNode):
    """Root container. One per .uf file."""
    title: str = ""
    width: int = 64
    theme_name: str = ""


@dataclass
class Box(IRNode):
    """Bordered panel with optional title."""
    title: str = ""
    weight: BorderWeight = BorderWeight.LIGHT


@dataclass
class Row(IRNode):
    """Horizontal layout — children split available width."""
    gap: int = 1


@dataclass
class Col(IRNode):
    """Explicit column in a row. Width in chars or None (auto)."""
    col_width: int | None = None


@dataclass
class Spacer(IRNode):
    """Vertical whitespace."""
    lines: int = 1


@dataclass
class Pad(IRNode):
    """Inner margin for a container."""
    top: int = 0
    right: int = 0
    bottom: int = 0
    left: int = 0


# ---------------------------------------------------------------------------
# Content nodes
# ---------------------------------------------------------------------------

@dataclass
class Heading(IRNode):
    """Styled heading (levels 1–3)."""
    level: HeadingLevel = HeadingLevel.H1
    text: str = ""


@dataclass
class Text(IRNode):
    """Text content with optional @modifier{} inline styles."""
    content: str = ""
    spans: list[TextSpan] = field(default_factory=list)


@dataclass
class Label(IRNode):
    """Aligned key-value pair."""
    key: str = ""
    value: str = ""


@dataclass
class Divider(IRNode):
    """Full-width horizontal rule."""
    divider_style: DividerStyle = DividerStyle.LIGHT


@dataclass
class Link(IRNode):
    """Clickable link — visual in ASCII, interactive in Micron."""
    display: str = ""
    dest: str = ""


@dataclass
class ListNode(IRNode):
    """Bulleted or numbered list."""
    list_style: ListStyle = ListStyle.BULLET


@dataclass
class ListItem(IRNode):
    """Single entry in a ListNode."""
    content: str = ""


# ---------------------------------------------------------------------------
# Placeholder nodes for future phases
# ---------------------------------------------------------------------------

@dataclass
class Gauge(IRNode):
    """Horizontal bar chart (Phase 4)."""
    label: str = ""
    value: float = 0
    max_val: float = 100
    bar_width: int = 28
    warn: float | None = None
    crit: float | None = None


@dataclass
class Sparkline(IRNode):
    """Braille sparkline (Phase 4)."""
    label: str = ""
    values: list[float] = field(default_factory=list)
    spark_width: int = 20


@dataclass
class Status(IRNode):
    """Status indicator (Phase 4)."""
    label: str = ""
    state: str = "unknown"


@dataclass
class Table(IRNode):
    """Box-drawn table."""
    title: str = ""
    columns: list[tuple[str, int]] = field(default_factory=list)  # (name, width)
    rows: list[list[str]] = field(default_factory=list)


# ---------------------------------------------------------------------------
# Form nodes
# ---------------------------------------------------------------------------

@dataclass
class Form(IRNode):
    """Form container grouping interactive fields."""
    form_name: str = ""


@dataclass
class Field(IRNode):
    """Text input field."""
    field_name: str = ""
    field_width: int = 24
    placeholder: str = ""


@dataclass
class Password(IRNode):
    """Masked password field."""
    field_name: str = ""
    field_width: int = 24
    placeholder: str = ""


@dataclass
class Radio(IRNode):
    """Radio button group — options separated by |."""
    group: str = ""
    options: list[str] = field(default_factory=list)


@dataclass
class Checkbox(IRNode):
    """Checkbox field."""
    field_name: str = ""
    checkbox_label: str = ""
    checked: bool = False


@dataclass
class FormButton(IRNode):
    """Submit button — clickable link in Micron."""
    button_label: str = ""
    dest: str = ""


# ---------------------------------------------------------------------------
# Dynamic nodes (Phase 7)
# ---------------------------------------------------------------------------

class SourceType(Enum):
    SHELL = auto()
    FILE = auto()
    JSON = auto()
    PYTHON = auto()
    RNS = auto()
    PARAM = auto()


@dataclass
class Let(IRNode):
    """Variable assignment: let name = "value" or let name = 1,2,3."""
    var_name: str = ""
    var_value: str = ""


@dataclass
class Source(IRNode):
    """Data source resolved at render time (dynamic pages only)."""
    var_name: str = ""
    source_type: SourceType = SourceType.SHELL
    command: str = ""
    timeout: int = 5


@dataclass
class IfBlock(IRNode):
    """Conditional block: if $var > threshold."""
    condition: str = ""
    # children = the "then" branch
    elif_branches: list[tuple[str, list[IRNode]]] = field(default_factory=list)
    else_children: list[IRNode] = field(default_factory=list)


@dataclass
class ForLoop(IRNode):
    """Iteration: for item in $collection."""
    var_name: str = ""
    iterable: str = ""
    # children = loop body


@dataclass
class CacheControl(IRNode):
    """Cache header: cache 0 (never cache) or cache 300 (5 min)."""
    seconds: int = 0


@dataclass
class OnSubmit(IRNode):
    """Form submission handler: on_submit "form_name"."""
    form_name: str = ""
    # children = handler body


@dataclass
class StateDecl(IRNode):
    """State persistence: state "name" "/path.json"."""
    state_name: str = ""
    path: str = ""


# ---------------------------------------------------------------------------
# Components (Phase 8)
# ---------------------------------------------------------------------------

# ---------------------------------------------------------------------------
# Navigation nodes
# ---------------------------------------------------------------------------

@dataclass
class NavItem:
    """A single item in a navigation bar."""
    kind: str = "item"          # "item", "separator", "heading"
    label: str = ""
    dest: str = ""
    active: bool = False
    children: list["NavItem"] = field(default_factory=list)


@dataclass
class HNav(IRNode):
    """Horizontal navigation bar."""
    nav_style: str = "bar"      # bar, tabs, pills, breadcrumb, underline
    items: list[NavItem] = field(default_factory=list)
    compact: bool = False


@dataclass
class VNav(IRNode):
    """Vertical navigation panel."""
    nav_style: str = "list"     # list, boxed, tree, sidebar, minimal
    nav_width: int = 0          # 0 = auto-fit
    items: list[NavItem] = field(default_factory=list)


@dataclass
class ImageNode(IRNode):
    """Image converted to character art."""
    path: str = ""
    mode: str = "braille"    # braille, block, ascii, halfblock
    img_width: int = 30
    dither: str = "floyd"    # floyd, threshold, none
    invert: bool = False
    use_color: bool = False
    caption: str = ""


@dataclass
class BigTitle(IRNode):
    """Large multi-line ASCII art text."""
    text: str = ""
    font: str = "block"    # block, thin, pixel


@dataclass
class ComponentDef(IRNode):
    """Component definition: component name(arg1, arg2)."""
    comp_name: str = ""
    params: list[str] = field(default_factory=list)
    # children = the component body template


@dataclass
class ComponentUse(IRNode):
    """Component instantiation: name "arg1" "arg2"."""
    comp_name: str = ""
    args: list[str] = field(default_factory=list)
