"""Theme and font helpers for OOXML themes."""

from __future__ import annotations

from typing import TYPE_CHECKING, Dict, List

from lxml import etree

from tokenmoulds.emitters.xml_constants import A_NS, THEMEML_NS
from tokenmoulds.emitters.xml_helpers_colors import create_color_from_ref
from tokenmoulds.emitters.xml_helpers_search import find_element

if TYPE_CHECKING:
    from tokenmoulds.ir.style_primitives import ExtraColorScheme


def create_extra_color_scheme(
    parent: etree._Element,
    scheme: "ExtraColorScheme",
) -> etree._Element:
    """Create an extra color scheme in theme extLst.

    OOXML allows additional color schemes beyond the standard 12 theme colors.
    These can be referenced by name in styles.

    Args:
        parent: Parent element (usually extLst in clrScheme)
        scheme: ExtraColorScheme with name and color slots

    Returns:
        The created ext element containing extra colors

    Example:
        >>> create_extra_color_scheme(ext_lst, extra_scheme)
        >>> # Produces extended color definitions
    """
    # Create extension wrapper
    ext = etree.SubElement(parent, f"{{{A_NS}}}ext")
    ext.set("uri", "{91240B29-F687-4F45-9708-019B960494DF}")  # Extra color scheme URI

    # Create color list
    for slot in scheme.colors:
        color_el = etree.SubElement(ext, f"{{{THEMEML_NS}}}extraClr")
        color_el.set("name", slot.name)
        create_color_from_ref(color_el, slot.color)

    return ext


def apply_extra_color_schemes(
    root: etree._Element,
    schemes: List["ExtraColorScheme"],
) -> None:
    """Apply extra color schemes to theme.xml.

    Finds or creates extLst in clrScheme and adds extra color definitions.

    Args:
        root: Theme root element
        schemes: List of ExtraColorScheme to add
    """
    if not schemes:
        return

    # Find clrScheme
    clr_scheme = find_element(root, ".//a:clrScheme")
    if clr_scheme is None:
        return

    # Find or create extLst
    ext_lst = find_element(clr_scheme, "a:extLst")
    if ext_lst is None:
        ext_lst = etree.SubElement(clr_scheme, f"{{{A_NS}}}extLst")

    # Add each extra color scheme
    for scheme in schemes:
        create_extra_color_scheme(ext_lst, scheme)


# =============================================================================
# FONT MANIPULATION
# =============================================================================


def set_font_typeface(
    root: etree._Element,
    font_type: str,
    script: str,
    typeface: str,
    namespaces: Dict[str, str] | None = None,
) -> bool:
    """Set font typeface in OOXML theme.

    Args:
        root: Theme root element
        font_type: 'majorFont' or 'minorFont'
        script: 'latin', 'ea', or 'cs'
        typeface: Font family name
        namespaces: Namespace map

    Returns:
        True if font was updated

    Example:
        >>> set_font_typeface(root, 'majorFont', 'latin', 'Inter')
    """
    ns = namespaces or {"a": A_NS}
    xpath = f".//a:{font_type}/a:{script}"
    font_el = find_element(root, xpath, ns)
    if font_el is not None:
        font_el.set("typeface", typeface)
        return True
    return False


def set_scheme_name(
    root: etree._Element,
    scheme_type: str,
    name: str,
    namespaces: Dict[str, str] | None = None,
) -> bool:
    """Set the name attribute on a theme scheme element.

    Args:
        root: Theme root element
        scheme_type: 'clrScheme', 'fontScheme', or 'fmtScheme'
        name: Name to set
        namespaces: Namespace map

    Returns:
        True if scheme was found and updated
    """
    ns = namespaces or {"a": A_NS}
    scheme = find_element(root, f".//a:{scheme_type}", ns)
    if scheme is not None:
        scheme.set("name", name)
        return True
    return False


def set_theme_name(
    root: etree._Element,
    name: str,
) -> None:
    """Set the name attribute on the theme root element.

    Args:
        root: Theme root element (<a:theme>)
        name: Theme name
    """
    root.set("name", name)
