"""Micron emitter — read CharGrid and output Micron markup with style tags.

Scans each line left-to-right, tracks style state, and opens/closes
Micron format codes at style transitions. Box-drawing characters pass
through as literal text.

Micron format reference:
  `!bold`!   `*italic`*   `_underline`_
  `Fhex text`f   `Bhex text`b
  `c center`a   `r right`a
  [label`dest]   [label`dest.mu]
  >H1   >>H2   >>>H3
"""

from __future__ import annotations

from uframe.grid import CharGrid, CellStyle
from uframe.ir import Page, Heading, HeadingLevel


def _emit_style_open(style: CellStyle) -> str:
    """Emit Micron opening tags for a style."""
    tags: list[str] = []
    if style.bold:
        tags.append("`!")
    if style.italic:
        tags.append("`*")
    if style.underline:
        tags.append("`_")
    if style.fg:
        tags.append(f"`F{style.fg}")
    if style.bg:
        tags.append(f"`B{style.bg}")
    return "".join(tags)


def _emit_style_close(style: CellStyle) -> str:
    """Emit Micron closing tags for a style (in reverse order)."""
    tags: list[str] = []
    if style.bg:
        tags.append("`b")
    if style.fg:
        tags.append("`f")
    if style.underline:
        tags.append("`_")
    if style.italic:
        tags.append("`*")
    if style.bold:
        tags.append("`!")
    return "".join(tags)


_EMPTY_STYLE = CellStyle()


def emit_micron(grid: CharGrid, page_title: str = "") -> str:
    """Emit the CharGrid as Micron markup."""
    lines: list[str] = []

    for row in range(grid.height):
        line_parts: list[str] = []
        cur_style = _EMPTY_STYLE
        in_link: str | None = None

        for col in range(grid.width):
            cell = grid.cells[row][col]
            ch = cell.char
            style = cell.style
            link = cell.link

            # Handle link transitions
            if link != in_link:
                if in_link is not None:
                    # Close previous link: [label`dest]
                    line_parts.append(f"`{in_link}]")
                if link is not None:
                    # Close any open style before link
                    if cur_style != _EMPTY_STYLE:
                        line_parts.append(_emit_style_close(cur_style))
                        cur_style = _EMPTY_STYLE
                    # Open new link
                    line_parts.append("[")
                in_link = link

            # Handle style transitions (not inside links — links handle their own style)
            if link is None and style != cur_style:
                # Close previous style
                if cur_style != _EMPTY_STYLE:
                    line_parts.append(_emit_style_close(cur_style))
                # Open new style
                if style != _EMPTY_STYLE:
                    line_parts.append(_emit_style_open(style))
                cur_style = style

            line_parts.append(ch)

        # Close any trailing link: [label`dest]
        if in_link is not None:
            line_parts.append(f"`{in_link}]")
            in_link = None

        # Close any trailing style
        if cur_style != _EMPTY_STYLE:
            line_parts.append(_emit_style_close(cur_style))

        line = "".join(line_parts).rstrip()
        lines.append(line)

    # Strip trailing blank lines
    while lines and not lines[-1]:
        lines.pop()

    return "\n".join(lines)
